Skip to content

Commit 2558fd2

Browse files
authored
Merge pull request #138 from treasure-data/type-hint
Introduce type hint
2 parents 70a0498 + f243f7f commit 2558fd2

38 files changed

+1465
-517
lines changed

.github/workflows/pythontest.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@ jobs:
2020
- name: Install dependencies
2121
run: |
2222
python -m pip install --upgrade pip
23-
pip install .
23+
pip install ".[dev]"
2424
pip install -r requirements.txt -r test-requirements.txt
2525
pip install -U coveralls pyyaml
26+
- name: Run pyright
27+
run: |
28+
pyright tdclient
2629
- name: Run test
2730
run: |
2831
coverage run --source=tdclient -m pytest tdclient/test

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
/.eggs
99
/.envrc
1010
/.tox
11-
/.venv
11+
/.venv*
1212
/build
1313
/dist
1414
/tmp
15+
/.agent
1516

1617
# JetBrains IDE
1718
.idea/

.pre-commit-config.yaml

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,28 @@
22
# See https://pre-commit.com/hooks.html for more hooks
33
repos:
44
- repo: https://github.com/pre-commit/pre-commit-hooks
5-
rev: v2.0.0
5+
rev: v6.0.0
66
hooks:
77
- id: trailing-whitespace
88
- id: end-of-file-fixer
99
- id: check-yaml
1010
- id: check-added-large-files
11-
- repo: https://github.com/asottile/seed-isort-config
12-
rev: v1.9.3
11+
- repo: https://github.com/astral-sh/ruff-pre-commit
12+
rev: v0.14.2
1313
hooks:
14-
- id: seed-isort-config
15-
- repo: https://github.com/pre-commit/mirrors-isort
16-
rev: v4.3.21
14+
# Run the linter.
15+
- id: ruff
16+
args: [--fix]
17+
# Run the formatter.
18+
- id: ruff-format
19+
- repo: https://github.com/RobertCraigie/pyright-python
20+
rev: v1.1.407
1721
hooks:
18-
- id: isort
19-
- repo: https://github.com/python/black
20-
rev: stable
21-
hooks:
22-
- id: black
23-
language_version: python3.7
22+
- id: pyright
23+
exclude: ^docs/
24+
additional_dependencies:
25+
- msgpack>=0.6.2
26+
- urllib3
27+
- python-dateutil
28+
- typing-extensions>=4.0.0
29+
- certifi

README.rst

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,46 @@ which would produce:
255255
1575454204, "a", "0001", ["a", "b", "c"]
256256
1575454204, "b", "0002", ["d", "e", "f"]
257257
258+
Type Hints
259+
----------
260+
261+
td-client-python includes comprehensive type hints (PEP 484) for improved development experience with static type checkers like mypy and pyright. Type hints are available for all public APIs.
262+
263+
**Features:**
264+
265+
266+
* Fully typed public API with precise type annotations
267+
* ``py.typed`` marker file for PEP 561 compliance
268+
* Type aliases in ``tdclient.types`` for common patterns
269+
* Support for type checking with mypy, pyright, and other tools
270+
271+
**Example with type checking:**
272+
273+
.. code-block:: python
274+
275+
import tdclient
276+
277+
# Type checkers will understand the types
278+
with tdclient.Client(apikey="your_api_key") as client:
279+
# client is inferred as tdclient.Client
280+
job = client.query("sample_db", "SELECT COUNT(1) FROM table", type="presto")
281+
# job is inferred as tdclient.models.Job
282+
job.wait()
283+
for row in job.result():
284+
# row is inferred as dict[str, Any]
285+
print(row)
286+
287+
**Using type aliases:**
288+
289+
.. code-block:: python
290+
291+
from tdclient.types import QueryEngineType, Priority
292+
293+
def run_query(engine: QueryEngineType, priority: Priority) -> None:
294+
with tdclient.Client() as client:
295+
job = client.query("mydb", "SELECT 1", type=engine, priority=priority)
296+
job.wait()
297+
258298
Development
259299
-----------
260300

docs/api/client.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,3 @@ tdclient.client
1111
:members:
1212
:undoc-members:
1313
:show-inheritance:
14-
15-

docs/conf.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ def linkcode_resolve(domain, info):
7878

7979
# -- Project information -----------------------------------------------------
8080

81-
project = 'td-client-python'
82-
copyright = '2019, Arm Treasure Data'
83-
author = 'Arm Treasure Data'
81+
project = "td-client-python"
82+
copyright = "2019, Arm Treasure Data"
83+
author = "Arm Treasure Data"
8484

8585
# The full version, including alpha/beta/rc tags
8686
release = pkg_resources.get_distribution(PACKAGE).version
@@ -98,24 +98,24 @@ def linkcode_resolve(domain, info):
9898
]
9999

100100
# Add any paths that contain templates here, relative to this directory.
101-
templates_path = ['_templates']
101+
templates_path = ["_templates"]
102102

103103
# List of patterns, relative to source directory, that match files and
104104
# directories to ignore when looking for source files.
105105
# This pattern also affects html_static_path and html_extra_path.
106-
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
106+
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
107107

108108

109109
# -- Options for HTML output -------------------------------------------------
110110

111111
# The theme to use for HTML and HTML Help pages. See the documentation for
112112
# a list of builtin themes.
113113
#
114-
html_theme = 'sphinx_rtd_theme'
114+
html_theme = "sphinx_rtd_theme"
115115

116116
# Add any paths that contain custom static files (such as style sheets) here,
117117
# relative to this directory. They are copied after the builtin static files,
118118
# so a file named "default.css" will overwrite the builtin "default.css".
119119
# html_static_path = ['_static']
120120

121-
autodoc_member_order = 'groupwise'
121+
autodoc_member_order = "groupwise"

docs/file_import_parameters.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ contains ``"not-an-int"``, the resulting ``ValueError`` will not be caught.
7474
To summarise, the default for reading CSV files is:
7575

7676
``dialect=csv.excel, encoding="utf-8", columns=None, dtypes=None, converters=None``
77-
77+
7878
TSV data
7979
--------
8080

pyproject.toml

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,19 @@ dependencies = [
3131
"python-dateutil",
3232
"msgpack>=0.6.2",
3333
"urllib3",
34+
"typing-extensions>=4.0.0",
3435
]
3536

3637
[project.optional-dependencies]
37-
dev = ["ruff"]
38+
dev = ["ruff", "pyright"]
3839
docs = ["sphinx", "sphinx_rtd_theme"]
3940

4041
[tool.setuptools]
4142
packages = ["tdclient"]
4243

44+
[tool.setuptools.package-data]
45+
tdclient = ["py.typed"]
46+
4347
[tool.ruff]
4448
line-length = 88
4549

@@ -53,3 +57,19 @@ ignore = ["E203", "E501"]
5357

5458
[tool.ruff.lint.isort]
5559
known-third-party = ["dateutil","msgpack","pkg_resources","pytest","setuptools","urllib3"]
60+
61+
[tool.pyright]
62+
include = ["tdclient"]
63+
exclude = ["**/__pycache__", "tdclient/test", "docs"]
64+
typeCheckingMode = "basic"
65+
pythonVersion = "3.9"
66+
pythonPlatform = "All"
67+
reportMissingTypeStubs = false
68+
reportUnknownMemberType = false
69+
reportUnknownArgumentType = false
70+
reportUnknownVariableType = false
71+
reportMissingImports = "warning"
72+
73+
# Pre-commit venv configuration
74+
venvPath = "."
75+
venv = ".venv"

tdclient/__init__.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
from __future__ import annotations
2+
13
import datetime
4+
import time
5+
from typing import Any
26

37
from tdclient import client, connection, errors, version
48

@@ -7,7 +11,7 @@
711
Client = client.Client
812

913

10-
def connect(*args, **kwargs):
14+
def connect(*args: Any, **kwargs: Any) -> connection.Connection:
1115
"""Returns a DBAPI compatible connection object
1216
1317
Args:
@@ -44,19 +48,19 @@ def connect(*args, **kwargs):
4448
Timestamp = datetime.datetime
4549

4650

47-
def DateFromTicks(ticks):
48-
return datetime.date(*datetime.localtime(ticks)[:3])
51+
def DateFromTicks(ticks: float) -> datetime.date:
52+
return datetime.date(*time.localtime(ticks)[:3])
4953

5054

51-
def TimeFromTicks(ticks):
52-
return datetime.time(*datetime.localtime(ticks)[3:6])
55+
def TimeFromTicks(ticks: float) -> datetime.time:
56+
return datetime.time(*time.localtime(ticks)[3:6])
5357

5458

55-
def TimestampFromTicks(ticks):
56-
return datetime.datetime(*datetime.localtime(ticks)[:6])
59+
def TimestampFromTicks(ticks: float) -> datetime.datetime:
60+
return datetime.datetime(*time.localtime(ticks)[:6])
5761

5862

59-
def Binary(string):
63+
def Binary(string: bytes) -> bytes:
6064
return bytes(string)
6165

6266

0 commit comments

Comments
 (0)