refactor: replace mypy with ty for static type checking#1932
refactor: replace mypy with ty for static type checking#1932bearomorphism wants to merge 1 commit intomasterfrom
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1932 +/- ##
=======================================
Coverage 97.99% 97.99%
=======================================
Files 60 60
Lines 2691 2696 +5
=======================================
+ Hits 2637 2642 +5
Misses 54 54 ☔ View full report in Codecov by Sentry. |
a50f9be to
643d2eb
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.
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.
| def smart_open(*args, **kwargs): # noqa: ANN201 | ||
| """Open a file with the EOL style determined from Git.""" | ||
| return open(*args, newline=EOLType.for_open(), **kwargs) |
There was a problem hiding this comment.
smart_open lacks parameter type annotations; the # noqa: ANN201 only suppresses the missing return annotation, but ruff is configured to enforce argument annotations (ANN001/ANN2). Add a typed signature (or explicitly ignore the relevant ANN codes) so poe lint passes.
| message_template = Template(self.custom_settings.get("message_template", "")) | ||
| if getattr(Template, "substitute", None): | ||
| return message_template.substitute(**answers) # type: ignore[attr-defined,no-any-return] # pragma: no cover # TODO: check if we can fix this | ||
| return message_template.substitute( | ||
| **answers | ||
| ) # pragma: no cover # TODO: check if we can fix this | ||
| return message_template.render(**answers) |
There was a problem hiding this comment.
This branch calls message_template.substitute(...) but under TYPE_CHECKING the Template type is jinja2.Template, which doesn't define substitute. This will fail static type checking (and was previously suppressed). Consider narrowing the type (e.g., separate string.Template vs jinja2.Template) or reintroducing a targeted type: ignore[attr-defined] for this call.
| Changelog( | ||
| self.config, | ||
| {**changelog_args, "dry_run": True}, # type: ignore[typeddict-item] | ||
| {**changelog_args, "dry_run": True}, |
There was a problem hiding this comment.
Changelog expects a ChangelogArgs TypedDict, but here a plain dict created via unpacking is passed without a cast. This was previously suppressed with a type: ignore and may now fail ty check. Cast the argument to ChangelogArgs (as is already done for the later Changelog instantiation) to keep the type checker happy and make intent explicit.
| {**changelog_args, "dry_run": True}, | |
| cast( | |
| "ChangelogArgs", | |
| {**changelog_args, "dry_run": True}, | |
| ), |
| commands.Version( | ||
| config, | ||
| { | ||
| argument: True, # type: ignore[misc] | ||
| argument: True, | ||
| }, |
There was a problem hiding this comment.
commands.Version expects VersionArgs (a TypedDict), but {argument: True} uses a dynamic key so the literal is inferred as a plain dict[str, bool] by type checkers. This used to be suppressed with a type: ignore; consider casting to VersionArgs (or branching on argument to build a literal with a static key) to avoid ty type errors.
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
Description
Checklist
Was generative AI tooling used to co-author this PR?
Code Changes
uv run poe alllocally to ensure this change passes linter check and testsDocumentation Changes
uv run poe doclocally to ensure the documentation pages renders correctlyExpected Behavior
Steps to Test This Pull Request
Additional Context