refactor: replace mypy with ty for static type checking#1932
refactor: replace mypy with ty for static type checking#1932bearomorphism wants to merge 5 commits intomasterfrom
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1932 +/- ##
=======================================
Coverage 98.10% 98.11%
=======================================
Files 61 61
Lines 2748 2754 +6
=======================================
+ Hits 2696 2702 +6
Misses 52 52 ☔ View full report in Codecov by Sentry. |
643d2eb to
0a22b49
Compare
There was a problem hiding this comment.
Pull request overview
Switches the project’s static type checking from mypy to Astral’s ty, updates configuration accordingly, and adjusts code/tests to satisfy ty’s typing semantics.
Changes:
- Replace
mypywithtyin dependency groups andpoe lint, and add[tool.ty]configuration. - Update codebase to align with
tytyping rules (casts, TypedDict interactions, ignore directives). - Add/adjust tests to match new typing-related behavior (notably changelog hook behavior).
Reviewed changes
Copilot reviewed 25 out of 26 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| uv.lock | Removes mypy (and related deps) and adds ty to locked dependencies. |
| pyproject.toml | Replaces mypy config with ty config; updates poe lint to run ty check. |
| docs/contributing/contributing_tldr.md | Updates contributor instructions from mypy to ty. |
| commitizen/version_schemes.py | Adjusts typing notes/ignores and casts for scheme types. |
| commitizen/providers/uv_provider.py | Updates ignore directives for ty/ruff semantics around TOML indexing. |
| commitizen/providers/poetry_provider.py | Renames params and updates ignore directives for TOML indexing. |
| commitizen/providers/cargo_provider.py | Updates ignore directives for TOML indexing. |
| commitizen/providers/base_provider.py | Updates ignore directives for TOML indexing. |
| commitizen/git.py | Updates smart_open typing/ignores (currently incomplete for ruff rules). |
| commitizen/cz/customize/customize.py | Adjusts ignores and formatting around template substitution/rendering (introduces a typing issue). |
| commitizen/cz/conventional_commits/conventional_commits.py | Updates override-related ignore style for ty/ruff. |
| commitizen/config/toml_config.py | Updates ignore directives for TOML mutation/indexing. |
| commitizen/config/base_config.py | Updates ignore directive for path property return. |
| commitizen/commands/bump.py | Adds ChangelogArgs typing and casts for TypedDict compatibility. |
| commitizen/cli.py | Updates ignore directive for args.func(...) call. |
| commitizen/changelog.py | Makes hook processing robust to non-dict entries; tweaks incremental build guard. |
| commitizen/changelog_formats/init.py | Refactors changelog-format resolution logic for clearer typing. |
| scripts/gen_cli_help_screenshots.py | Adds casts to satisfy static typing when iterating CLI command config. |
| tests/test_cz_search_filter.py | Uses Path for TomlConfig.path to match type expectations. |
| tests/test_cz_conventional_commits.py | Adds casts / imports to satisfy ty for answer dict typing. |
| tests/test_conf.py | Adjusts read_cfg call argument type. |
| tests/test_cli.py | Passes None traceback to match commitizen_excepthook signature. |
| tests/test_changelog.py | Adds casts/imports and new test for skipping non-dict hook entries. |
| tests/commands/test_version_command.py | Removes mypy-specific ignore; now relies on ty behavior. |
| tests/commands/test_changelog_command.py | Updates ignore style for ruff PGH003. |
| tests/commands/test_bump_command.py | Updates ignore style for ruff PGH003. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
This one is ready for review |
Lee-W
left a comment
There was a problem hiding this comment.
I'm not 100% sure we want to migrate to ty now, given the limitations. but some fixed are valid though
- tests/test_cz_conventional_commits.py: use type annotations instead of cast() for answers dicts (avoids ty limitation with dict literal inference) - config/__init__.py: widen read_cfg to accept str | Path | None - tests/test_conf.py: revert str() wrapper now that read_cfg accepts Path - changelog.py: add comment explaining ty limitation requiring cast - version_schemes.py: add comment explaining ty limitation requiring cast Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Same boat, |
- tests/test_cz_conventional_commits.py: use type annotations instead of cast() for answers dicts (avoids ty limitation with dict literal inference) - config/__init__.py: widen read_cfg to accept str | Path | None - tests/test_conf.py: revert str() wrapper now that read_cfg accepts Path - changelog.py: add comment explaining ty limitation requiring cast - version_schemes.py: add comment explaining ty limitation requiring cast Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
f39e15e to
cd7c463
Compare
- Use Astral ty in linters, poe lint, and [tool.ty] instead of mypy. - Align typings, type ignores, and tests with ty; cover changelog hook list entries that are not dicts for patch coverage.
- Add type annotations to smart_open in git.py - Add type: ignore[attr-defined] for Template.substitute call - Cast dict to ChangelogArgs in bump.py - Cast dynamic key dict to VersionArgs in test_version_command.py Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- tests/test_cz_conventional_commits.py: use type annotations instead of cast() for answers dicts (avoids ty limitation with dict literal inference) - config/__init__.py: widen read_cfg to accept str | Path | None - tests/test_conf.py: revert str() wrapper now that read_cfg accepts Path - changelog.py: add comment explaining ty limitation requiring cast - version_schemes.py: add comment explaining ty limitation requiring cast Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
920e968 to
a61fd94
Compare
ty 0.0.33 prefers the declared type on annotated assignments when the RHS returns Any/Unknown, removing the need for cast() workarounds. - Bump ty minimum to >=0.0.33 - Replace cast() with type annotations where applicable Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
a61fd94 to
747e04f
Compare
|
upgraded Is it good enough? wdyt |
|
pr description updated |
Switch the linters group and poe lint from mypy to Astral ty, add [tool.ty] configuration, and adjust code and tests for ty semantics.
Made-with: Cursor, GitHub Copilot CLI
Description
Replace mypy with ty (Astral's Python type checker) for static type checking. ty is significantly faster and integrates well with the existing ruff toolchain.
Key changes
[tool.ty]configuration inpyproject.toml>=0.0.33to leverage declared-type preference (removes unnecessarycast()workarounds)cast()calls where ty 0.0.33 can infer types from annotated assignments# type: ignorecomments to use bare form (ty doesn't support mypy-specific error codes like[arg-type])Why each change is necessary
All changes in this PR are required for ty compatibility — no cosmetic-only changes:
pyproject.toml[tool.ty]config, bump to>=0.0.33commitizen/commands/bump.pycast()calls, add TODO on remainingcommitizen/commands/changelog.pycast()with annotated assignmentcommitizen/version_schemes.pycast()with annotated assignment, update commentscripts/gen_cli_help_screenshots.pycast()calls with annotated assignmentscommitizen/changelog_formats/__init__.pyname and X or Yto explicit if/else; renameformat→format_clsand/orpattern; avoids shadowing Python builtincommitizen/changelog.pyisinstance(msg, dict)guardcommitizen/cz/customize/customize.py# type: ignorefrom# pragma: no cover[no-any-return]error codecommitizen/providers/*.py# type: ignore[index]→# type: ignore # noqa: PGH003; renamepyproject→documentin poetry_provider to match parent classbase_provider.pycommitizen/cli.py,commitizen/git.py,commitizen/config/*.py,commitizen/cz/**# type: ignorecomments# type: ignore(no mypy-specific codes)tests/test_cli.py""→Noneincommitizen_excepthook()calls""is notTracebackType | Nonetests/test_cz_search_filter.pypath="not_exist.toml"→path=Path("not_exist.toml")Pathtests/test_changelog.pycast()forrelease["changes"]lookups, add test for non-dict skipisinstanceguard added for tytests/commands/test_version_command.py# type: ignore[arg-type]→ bare form, remove orphanedTYPE_CHECKINGdocs/contributing/contributing_tldr.mdAGENTS.mdChecklist
Was generative AI tooling used to co-author this PR?
Code Changes
uv run poe alllocally to ensure this change passes linter check and testsuv run ty checkpasses with zero diagnosticsuv run ruff checkpassesExpected Behavior
uv run poe lintrunsruff check+ty checkinstead ofruff check+mypyuv run ty checkreports zero diagnosticsSteps to Test This Pull Request
uv sync --group lintersuv run ty check— should report zero diagnosticsuv run ruff check— should passuv run poe test— all tests passAdditional Context
cast()workarounds where the RHS returnsAny/Unknownbut an annotation is present.VersionScheme), TypedDict construction from spread dicts, and union narrowing in loops.commitizen/commands/bump.pyfor a cast that can be removed onceself.file_nameis narrowed tostr(currentlystr | None).