Skip to content

Commit 8331245

Browse files
authored
chore: Migrate to ty type checker (#562)
1 parent 0fa43bc commit 8331245

20 files changed

+85
-181
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ __pycache__
33
.mypy_cache
44
.pytest_cache
55
.ruff_cache
6+
.ty_cache
67
.uv-cache
78

89
# Virtual envs

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ make format
4646

4747
### Type checking
4848

49-
Type checking is handled by [mypy](https://mypy.readthedocs.io/), verifying code against type annotations. Configuration settings can be found in `pyproject.toml`.
49+
Type checking is handled by [ty](https://docs.astral.sh/ty/), verifying code against type annotations. Configuration settings can be found in `pyproject.toml`.
5050

5151
To run type checking:
5252

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
INTEGRATION_TESTS_CONCURRENCY = 1
77

88
clean:
9-
rm -rf .mypy_cache .pytest_cache .ruff_cache build dist htmlcov .coverage
9+
rm -rf .ty_cache .pytest_cache .ruff_cache build dist htmlcov .coverage
1010

1111
install-dev:
1212
uv sync --all-extras
@@ -24,7 +24,7 @@ lint:
2424
uv run ruff check
2525

2626
type-check:
27-
uv run mypy
27+
uv run ty check
2828

2929
unit-tests:
3030
uv run pytest \

docs/02_concepts/code/03_nested_async.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ async def main() -> None:
1313
actor_runs = (await runs_client.list(limit=10, desc=True)).items
1414

1515
# Select the last run of the Actor that finished with a SUCCEEDED status
16-
last_succeeded_run_client = actor_client.last_run(status='SUCCEEDED') # type: ignore[arg-type]
16+
last_succeeded_run_client = actor_client.last_run(status='SUCCEEDED') # ty: ignore[invalid-argument-type]
1717

1818
# Get dataset
1919
actor_run_dataset_client = last_succeeded_run_client.dataset()

docs/02_concepts/code/03_nested_sync.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def main() -> None:
1313
actor_runs = runs_client.list(limit=10, desc=True).items
1414

1515
# Select the last run of the Actor that finished with a SUCCEEDED status
16-
last_succeeded_run_client = actor_client.last_run(status='SUCCEEDED') # type: ignore[arg-type]
16+
last_succeeded_run_client = actor_client.last_run(status='SUCCEEDED') # ty: ignore[invalid-argument-type]
1717

1818
# Get dataset
1919
actor_run_dataset_client = last_succeeded_run_client.dataset()

pyproject.toml

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ dependencies = [
4444
dev = [
4545
"dycw-pytest-only<3.0.0",
4646
"griffe",
47-
"mypy~=1.19.0",
4847
"pre-commit<5.0.0",
4948
"pydoc-markdown<5.0.0",
5049
"pytest-asyncio<2.0.0",
@@ -56,6 +55,7 @@ dev = [
5655
"redbaron<1.0.0",
5756
"ruff~=0.14.0",
5857
"setuptools", # setuptools are used by pytest but not explicitly required
58+
"ty~=0.0.0",
5959
"types-colorama<0.5.0",
6060
"werkzeug<4.0.0", # Werkzeug is used by pytest-httpserver
6161
]
@@ -158,30 +158,21 @@ asyncio_default_fixture_loop_scope = "function"
158158
asyncio_mode = "auto"
159159
timeout = 1200
160160

161-
[tool.mypy]
162-
python_version = "3.10"
163-
files = ["src", "tests", "scripts", "docs", "website"]
164-
check_untyped_defs = true
165-
disallow_incomplete_defs = true
166-
disallow_untyped_calls = true
167-
disallow_untyped_decorators = true
168-
disallow_untyped_defs = true
169-
no_implicit_optional = true
170-
warn_redundant_casts = true
171-
warn_return_any = true
172-
warn_unreachable = true
173-
warn_unused_ignores = true
174-
exclude = []
175-
176-
[[tool.mypy.overrides]]
177-
module = ["pandas"]
178-
ignore_missing_imports = true
179-
180-
[tool.basedpyright]
181-
pythonVersion = "3.10"
182-
typeCheckingMode = "standard"
161+
[tool.ty.environment]
162+
python-version = "3.10"
163+
164+
[tool.ty.src]
183165
include = ["src", "tests", "scripts", "docs", "website"]
184166

167+
[[tool.ty.overrides]]
168+
include = [
169+
"docs/**/*.py",
170+
"website/**/*.py",
171+
]
172+
173+
[tool.ty.overrides.rules]
174+
unresolved-import = "ignore"
175+
185176
[tool.coverage.report]
186177
exclude_lines = ["pragma: no cover", "if TYPE_CHECKING:", "assert_never()"]
187178

scripts/check_async_docstrings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import sys
77
from pathlib import Path
88

9-
from redbaron import RedBaron # type: ignore[import-untyped]
9+
from redbaron import RedBaron
1010
from utils import sync_to_async_docstring
1111

1212
found_issues = False

scripts/fix_async_docstrings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import re
44
from pathlib import Path
55

6-
from redbaron import RedBaron # type: ignore[import-untyped]
6+
from redbaron import RedBaron
77
from utils import sync_to_async_docstring
88

99
# Get the directory of the source files

src/apify_client/_logging.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def _injects_client_details_to_log_context(fun: Callable) -> Callable:
5959

6060
@functools.wraps(fun)
6161
async def async_wrapper(resource_client: _BaseBaseClient, *args: Any, **kwargs: Any) -> Any:
62-
log_context.client_method.set(fun.__qualname__)
62+
log_context.client_method.set(fun.__qualname__) # ty: ignore[unresolved-attribute]
6363
log_context.resource_id.set(resource_client.resource_id)
6464

6565
return await fun(resource_client, *args, **kwargs)
@@ -69,7 +69,7 @@ async def async_wrapper(resource_client: _BaseBaseClient, *args: Any, **kwargs:
6969

7070
@functools.wraps(fun)
7171
async def async_generator_wrapper(resource_client: _BaseBaseClient, *args: Any, **kwargs: Any) -> Any:
72-
log_context.client_method.set(fun.__qualname__)
72+
log_context.client_method.set(fun.__qualname__) # ty: ignore[unresolved-attribute]
7373
log_context.resource_id.set(resource_client.resource_id)
7474

7575
async for item in fun(resource_client, *args, **kwargs):
@@ -80,7 +80,7 @@ async def async_generator_wrapper(resource_client: _BaseBaseClient, *args: Any,
8080

8181
@functools.wraps(fun)
8282
def wrapper(resource_client: _BaseBaseClient, *args: Any, **kwargs: Any) -> Any:
83-
log_context.client_method.set(fun.__qualname__)
83+
log_context.client_method.set(fun.__qualname__) # ty: ignore[unresolved-attribute]
8484
log_context.resource_id.set(resource_client.resource_id)
8585

8686
return fun(resource_client, *args, **kwargs)

src/apify_client/_types.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
from typing import Any, Generic, TypeVar
44

55
JSONSerializable = str | int | float | bool | None | dict[str, Any] | list[Any]
6-
"""Type for representing json-serializable values. It's close enough to the real thing supported
7-
by json.parse, and the best we can do until mypy supports recursive types. It was suggested in
8-
a discussion with (and approved by) Guido van Rossum, so I'd consider it correct enough.
6+
"""Type for representing json-serializable values. It's close enough to the real thing supported by json.parse.
7+
It was suggested in a discussion with (and approved by) Guido van Rossum, so I'd consider it correct enough.
98
"""
109

1110
T = TypeVar('T')

0 commit comments

Comments
 (0)