Skip to content

Commit 747e04f

Browse files
refactor: leverage ty 0.0.33 declared-type preference to remove casts
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>
1 parent f8f8daf commit 747e04f

9 files changed

Lines changed: 781 additions & 785 deletions

File tree

AGENTS.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Follow these instructions in addition to any higher-level system or tool rules.
1515
- `commitizen/commands/` - subcommands such as `bump`, `commit`, `changelog`, `check`, etc.
1616
- `commitizen/config/` - configuration discovery and loading.
1717
- `commitizen/providers/` - version providers (e.g., `pep621`, `poetry`, `npm`, `uv`).
18-
- **Config sources**: `pyproject.toml` (project config, poe tasks, ruff, mypy), `.pre-commit-config.yaml` (hooks), `.github/workflows/` (CI).
18+
- **Config sources**: `pyproject.toml` (project config, poe tasks, ruff, ty), `.pre-commit-config.yaml` (hooks), `.github/workflows/` (CI).
1919

2020
## General Expectations
2121

@@ -34,7 +34,7 @@ uv sync --frozen --group base --group test --group linters
3434
### Local commands
3535

3636
- **Format**: `uv run poe format` (runs `ruff check --fix` then `ruff format`)
37-
- **Lint**: `uv run poe lint` (runs `ruff check` then `mypy`)
37+
- **Lint**: `uv run poe lint` (runs `ruff check` then `ty check`)
3838
- **Test**: `uv run poe test` (runs `pytest -n auto`)
3939
- **CI-equivalent**: `uv run poe ci` (commit check + pre-commit hooks via `prek` + test with coverage)
4040
- **Full local check**: `uv run poe all` (format + lint + check-commit + coverage)
@@ -50,7 +50,7 @@ Always run at least `uv run ruff check --fix . && uv run ruff format .` before p
5050
### Common CI failure patterns
5151

5252
- **"Format Python code...Failed"**: Run `uv run poe format` and commit the result.
53-
- **mypy `[arg-type]` on TypedDict**: Dynamically-constructed dicts (e.g., from `pytest.mark.parametrize`) passed to TypedDict-typed params need `# type: ignore[arg-type]`.
53+
- **ty `invalid-argument-type` on TypedDict**: Dynamically-constructed dicts (e.g., from `pytest.mark.parametrize`) passed to TypedDict-typed params need `# type: ignore # noqa: PGH003` or `cast()`.
5454
- **"pathspec 'vX.Y.Z' did not match"**: `.pre-commit-config.yaml` pins a tag of this repo. Rebase onto master to pick up the tag.
5555
- **`VersionProtocol` + `issubclass`**: This Protocol has non-method members (properties), so `issubclass()` raises `TypeError`. Use `hasattr` checks for runtime validation.
5656

commitizen/commands/bump.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def __call__(self) -> None:
263263
)
264264
)
265265

266-
rules = TagRules.from_settings(cast("Settings", self.bump_settings))
266+
rules = TagRules.from_settings(self.bump_settings)
267267
current_tag = rules.find_tag_for(git.get_tags(), current_version)
268268
current_tag_version = (
269269
current_tag.name if current_tag else rules.normalize_tag(current_version)
@@ -323,16 +323,14 @@ def __call__(self) -> None:
323323
try:
324324
Changelog(
325325
self.config,
326-
cast(
327-
"ChangelogArgs",
328-
{**changelog_args, "dry_run": True},
329-
),
326+
{**changelog_args, "dry_run": True},
330327
)()
331328
except DryRunExit:
332329
pass
333330

334331
changelog_cmd = Changelog(
335332
self.config,
333+
# TODO: remove cast once self.file_name is narrowed to str
336334
cast(
337335
"ChangelogArgs",
338336
{

commitizen/commands/changelog.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from difflib import SequenceMatcher
44
from operator import itemgetter
55
from pathlib import Path
6-
from typing import TYPE_CHECKING, Any, TypedDict, cast
6+
from typing import TYPE_CHECKING, Any, TypedDict
77

88
from commitizen import changelog, defaults, factory, git, out
99
from commitizen.changelog_formats import get_changelog_format
@@ -99,11 +99,10 @@ def __init__(self, config: BaseConfig, arguments: ChangelogArgs) -> None:
9999
self.change_type_map = (
100100
self.config.settings.get("change_type_map") or self.cz.change_type_map
101101
)
102-
self.change_type_order = cast(
103-
"list[str]",
102+
self.change_type_order: list[str] = (
104103
self.config.settings.get("change_type_order")
105104
or self.cz.change_type_order
106-
or defaults.CHANGE_TYPE_ORDER,
105+
or defaults.CHANGE_TYPE_ORDER
107106
)
108107
self.rev_range = arguments.get("rev_range")
109108
self.tag_rules = TagRules(

commitizen/version_schemes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ def get_version_scheme(settings: Settings, name: str | None = None) -> VersionSc
421421
(ep,) = metadata.entry_points(name=name, group=SCHEMES_ENTRYPOINT)
422422
except ValueError:
423423
raise VersionSchemeUnknown(f'Version scheme "{name}" unknown.')
424-
scheme = cast("VersionScheme", ep.load())
424+
scheme: VersionScheme = ep.load()
425425

426426
# `VersionProtocol` is a `@runtime_checkable` Protocol, but `issubclass()` is not
427427
# supported for Protocols with non-method members. We check an instance instead by

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ linters = [
118118
"types-termcolor>=0.1.1",
119119
"types-colorama>=0.4.15.20240311",
120120
"prek>=0.2.28",
121-
"ty>=0.0.29",
121+
"ty>=0.0.33",
122122
]
123123

124124
documentation = [

scripts/gen_cli_help_screenshots.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import subprocess
33
from itertools import chain
44
from pathlib import Path
5-
from typing import Any, cast
5+
from typing import Any
66

77
from rich.console import Console
88

@@ -14,8 +14,8 @@ def gen_cli_help_screenshots() -> None:
1414
images_root = Path(__file__).parent.parent / "docs" / "images" / "cli_help"
1515
images_root.mkdir(parents=True, exist_ok=True)
1616

17-
cli_data = cast("dict[str, Any]", data)
18-
commands_cfg = cast("list[dict[str, Any]]", cli_data["subcommands"]["commands"])
17+
cli_data: dict[str, Any] = data
18+
commands_cfg: list[dict[str, Any]] = cli_data["subcommands"]["commands"]
1919
cz_commands = (
2020
command["name"] if isinstance(command["name"], str) else command["name"][0]
2121
for command in commands_cfg

tests/commands/test_version_command.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
from commitizen.__version__ import __version__
99
from commitizen.config.base_config import BaseConfig
1010

11-
if TYPE_CHECKING:
12-
from commitizen.commands.version import VersionArgs
13-
1411

1512
def test_version_for_showing_project_version_error(config, capsys):
1613
# No version specified in config
@@ -170,7 +167,7 @@ def test_version_just_minor(config, capsys, version: str, expected_version: str)
170167
)
171168
def test_version_invalid_combinations(config, capsys, args: dict, expected_error: str):
172169
"""Test that certain flag combinations produce errors."""
173-
commands.Version(config, args)() # type: ignore[arg-type]
170+
commands.Version(config, args)() # type: ignore # noqa: PGH003
174171
captured = capsys.readouterr()
175172
assert not captured.out
176173
assert expected_error in captured.err

tests/test_changelog.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,11 +1171,13 @@ def test_generate_tree_from_commits(gitcommits, tags, merge_prereleases):
11711171
for release, expected_release in zip(tree, expected):
11721172
assert release["version"] == expected_release["version"]
11731173
assert release["date"] == expected_release["date"]
1174-
assert release["changes"].keys() == expected_release["changes"].keys()
1175-
for change_type in release["changes"]:
1176-
changes = release["changes"][change_type]
1177-
expected_changes = expected_release["changes"][change_type]
1178-
for change, expected_change in zip(changes, expected_changes):
1174+
changes = cast("dict[str, Any]", release["changes"])
1175+
expected_changes_map = cast("dict[str, Any]", expected_release["changes"])
1176+
assert changes.keys() == expected_changes_map.keys()
1177+
for change_type in changes:
1178+
change_list = changes[change_type]
1179+
expected_list = expected_changes_map[change_type]
1180+
for change, expected_change in zip(change_list, expected_list):
11791181
assert change["scope"] == expected_change["scope"]
11801182
assert change["breaking"] == expected_change["breaking"]
11811183
assert change["message"] == expected_change["message"]

0 commit comments

Comments
 (0)