Skip to content

Commit 0314d20

Browse files
Migrate from mypy to ty for type checking (#252)
* Migrate from mypy to ty for type checking - Replace mypy with ty (Astral's new type checker) - Update all configuration files (pyproject.toml, setup.cfg) - Update GitHub Actions workflow to use uvx ty check - Update AGENT.md, Makefile, and dev.py with new command - Remove mypy and types-setuptools from requirements-dev.in - Fix type errors detected by ty (remove unused imports, add type ignore comments for intentional monkey patching) - All 153 tests pass - Ty type checking passes with no errors Amp-Thread-ID: https://ampcode.com/threads/T-3de57a05-de3a-47f2-a4f0-bc95e78d8d13 Co-authored-by: Amp <amp@ampcode.com> * Fix ty typecheck in CI by using venv Ty needs to find installed packages in a virtual environment. Create a venv and activate it before running ty check. * Replace mypy with ty in lint.yml workflow Update the lint workflow to use ty instead of mypy for type checking. Verified locally: - ✅ ruff check passed - ✅ ty check passed - ✅ all 153 tests passed --------- Co-authored-by: Amp <amp@ampcode.com>
1 parent b616dd1 commit 0314d20

File tree

11 files changed

+36
-52
lines changed

11 files changed

+36
-52
lines changed

.github/workflows/lint.yml

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ jobs:
2727
ruff check tests
2828
2929
30-
mypy:
31-
name: mypy
30+
typecheck:
31+
name: ty typecheck
3232
runs-on: ubuntu-latest
3333
steps:
3434
- name: Checkout
@@ -37,11 +37,15 @@ jobs:
3737
uses: actions/setup-python@v5.2.0
3838
with:
3939
python-version: '3.13'
40-
cache: 'pip'
41-
- run: pip install --upgrade mypy types-requests types-urllib3
42-
- name: mypy
43-
uses: liskin/gh-problem-matcher-wrap@v2
40+
- name: Install uv
41+
uses: astral-sh/setup-uv@v6
4442
with:
45-
linters: mypy
46-
run: |
47-
mypy json2xml
43+
enable-cache: true
44+
- name: Install dependencies
45+
run: |
46+
uv venv
47+
uv pip install -e .
48+
- name: Run ty
49+
run: |
50+
source .venv/bin/activate
51+
uvx ty check json2xml tests

.github/workflows/pythonpackage.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,11 @@ jobs:
142142
143143
- name: Install dependencies
144144
run: |
145-
uv pip install --system -e .
146-
uv pip install --system mypy>=1.0.0 types-setuptools
145+
uv venv
146+
uv pip install -e .
147147
148-
- name: Run mypy
149-
run: mypy json2xml tests
148+
- name: Run ty
149+
run: |
150+
source .venv/bin/activate
151+
uvx ty check json2xml tests
150152

AGENT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
- Test: `pytest -vv` (all tests) or `pytest tests/test_<name>.py -vv` (single test file)
55
- Test with coverage: `pytest --cov=json2xml --cov-report=xml:coverage/reports/coverage.xml --cov-report=term -xvs`
66
- Lint: `ruff check json2xml tests`
7-
- Type check: `mypy json2xml tests`
7+
- Type check: `uvx ty check json2xml tests`
88
- Test all Python versions: `tox`
99
- Clean artifacts: `make clean`
1010

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ lint: ## check style with ruff
5656
lint-fix: ## automatically fix ruff issues
5757
ruff check --fix json2xml tests
5858

59-
typecheck: ## check types with mypy
60-
mypy json2xml tests
59+
typecheck: ## check types with ty
60+
uvx ty check json2xml tests
6161

6262
test: ## run tests quickly with the default Python
6363
pytest --cov=json2xml --cov-report=xml:coverage/reports/coverage.xml --cov-report=term -xvs tests -n auto

dev.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def main() -> None:
3737
], "Tests")
3838

3939
if command in ("typecheck", "all"):
40-
success &= run_command(["mypy", "json2xml", "tests"], "Type checking")
40+
success &= run_command(["uvx", "ty", "check", "json2xml", "tests"], "Type checking")
4141

4242
if command == "help":
4343
print("Usage: python dev.py [command]")

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,6 @@ lint.select = [
7272
"F",
7373
"W",
7474
]
75+
76+
[tool.ty]
77+
# Type checking configuration with ty

requirements-dev.in

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,4 @@ pytest-xdist==3.8.0
77
coverage==7.10.3
88
ruff==0.12.8
99
setuptools==80.9.0
10-
mypy==1.17.1
11-
types-setuptools==80.9.0.20250809
10+
# Note: ty is run via uvx, not installed as a dependency

requirements-dev.txt

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
#
2-
# This file is autogenerated by pip-compile with Python 3.13
3-
# by the following command:
4-
#
5-
# pip-compile requirements-dev.in
6-
#
7-
coverage[toml]==7.10.3
1+
# This file was autogenerated by uv via the following command:
2+
# uv pip compile requirements-dev.in -o requirements-dev.txt
3+
coverage==7.10.3
84
# via
95
# -r requirements-dev.in
106
# pytest-cov
@@ -14,14 +10,8 @@ execnet==2.1.1
1410
# via pytest-xdist
1511
iniconfig==2.0.0
1612
# via pytest
17-
mypy==1.17.1
18-
# via -r requirements-dev.in
19-
mypy-extensions==1.0.0
20-
# via mypy
2113
packaging==24.2
2214
# via pytest
23-
pathspec==0.12.1
24-
# via mypy
2515
pluggy==1.5.0
2616
# via
2717
# pytest
@@ -39,14 +29,9 @@ pytest-xdist==3.8.0
3929
# via -r requirements-dev.in
4030
ruff==0.12.8
4131
# via -r requirements-dev.in
42-
types-setuptools==80.9.0.20250809
32+
setuptools==80.9.0
4333
# via -r requirements-dev.in
44-
typing-extensions==4.12.2
45-
# via mypy
4634
urllib3==2.5.0
4735
# via -r requirements.in
4836
xmltodict==0.14.2
4937
# via -r requirements-dev.in
50-
51-
# The following packages are considered to be unsafe in a requirements file:
52-
# setuptools

setup.cfg

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,8 @@ max-line-length=120
2121
[aliases]
2222
# Define setup.py command aliases here
2323

24-
[mypy]
25-
check_untyped_defs = true
26-
disallow_any_generics = true
27-
disallow_incomplete_defs = true
28-
disallow_untyped_defs = true
29-
no_implicit_optional = true
30-
warn_redundant_casts = true
31-
warn_unused_ignores = true
32-
ignore_missing_imports = true
24+
[tool.ty]
25+
# Ty configuration is now in pyproject.toml
3326

3427

3528
[coverage:run]

tests/test_dict2xml.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from _pytest.fixtures import FixtureRequest
1212
from _pytest.logging import LogCaptureFixture
1313
from _pytest.monkeypatch import MonkeyPatch
14-
from pytest_mock.plugin import MockerFixture
1514

1615

1716
class TestDict2xml:
@@ -808,8 +807,8 @@ def patched_get_unique_id(element: str) -> str:
808807
this_id = module.make_id(element) # This exercises line 52
809808
return ids[-1]
810809

811-
module.make_id = mock_make_id
812-
module.get_unique_id = patched_get_unique_id
810+
module.make_id = mock_make_id # type: ignore[assignment]
811+
module.get_unique_id = patched_get_unique_id # type: ignore[assignment]
813812

814813
try:
815814
result = dicttoxml.get_unique_id("test")
@@ -1025,7 +1024,7 @@ def mock_is_primitive(val: Any) -> bool:
10251024
return True
10261025
return original_is_primitive(val)
10271026

1028-
module.is_primitive_type = mock_is_primitive
1027+
module.is_primitive_type = mock_is_primitive # type: ignore[assignment]
10291028
try:
10301029
item = {"@val": {"test": "data"}}
10311030
result = dicttoxml.dict2xml_str(

0 commit comments

Comments
 (0)