Skip to content

refactor: replace mypy with ty for static type checking#1932

Open
bearomorphism wants to merge 1 commit intomasterfrom
replace-mypy-with-ty
Open

refactor: replace mypy with ty for static type checking#1932
bearomorphism wants to merge 1 commit intomasterfrom
replace-mypy-with-ty

Conversation

@bearomorphism
Copy link
Copy Markdown
Collaborator

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?

  • Yes (please specify the tool below)

Code Changes

  • Add test cases to all the changes you introduce
  • Run uv run poe all locally to ensure this change passes linter check and tests
  • Manually test the changes:
    • Verify the feature/bug fix works as expected in real-world scenarios
    • Test edge cases and error conditions
    • Ensure backward compatibility is maintained
    • Document any manual testing steps performed
  • Update the documentation for the changes

Documentation Changes

  • Run uv run poe doc locally to ensure the documentation pages renders correctly
  • Check and fix any broken links (internal or external)

Expected Behavior

Steps to Test This Pull Request

Additional Context

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.99%. Comparing base (69884e0) to head (0a22b49).
⚠️ Report is 1 commits behind head on master.
✅ All tests successful. No failed tests found.

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.
📢 Have feedback on the report? Share it here.

@bearomorphism bearomorphism force-pushed the replace-mypy-with-ty branch 2 times, most recently from a50f9be to 643d2eb Compare April 12, 2026 14:03
- 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.
@bearomorphism bearomorphism requested a review from Copilot April 12, 2026 14:05
@bearomorphism bearomorphism changed the title build: replace mypy with ty for static type checking refactor: replace mypy with ty for static type checking Apr 12, 2026
@bearomorphism bearomorphism marked this pull request as ready for review April 12, 2026 14:06
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 mypy with ty in dependency groups and poe lint, and add [tool.ty] configuration.
  • Update codebase to align with ty typing 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.

Comment on lines +319 to 321
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)
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines 56 to 61
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)
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Changelog(
self.config,
{**changelog_args, "dry_run": True}, # type: ignore[typeddict-item]
{**changelog_args, "dry_run": True},
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
{**changelog_args, "dry_run": True},
cast(
"ChangelogArgs",
{**changelog_args, "dry_run": True},
),

Copilot uses AI. Check for mistakes.
Comment on lines 152 to 156
commands.Version(
config,
{
argument: True, # type: ignore[misc]
argument: True,
},
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants