Fix mypy 2.4 errors and enable warn_unused_ignores - #1768
Merged
Merged
Conversation
mypy 2.4 switched to its new Ruff-based native parser by default. That
parser rejects third-party codes such as "ty:unresolved-attribute" inside
"# type: ignore[...]" comments, reporting the whole comment as an invalid
"type: ignore" [syntax] error and therefore no longer suppressing the
original diagnostic either.
Split each combined comment into separate mypy and ty pragmas:
# type: ignore[attr-defined] # ty: ignore[unresolved-attribute]
The mypy pragma must come first for mypy to recognize it, and ty still
needs its own rule code. This form is accepted by mypy's native and
legacy parsers as well as by ty.
Also bump the ruff pre-commit hook to v0.16.10.
The combined "type: ignore[code, ty:rule]" comments made mypy's legacy parser flag every ty code as unused, which is why warn_unused_ignores was disabled. With those split into separate mypy and ty pragmas it can be turned back on. Verified against Python 3.11-3.15 on linux, darwin, and win32 so that ignores needed only on some platforms or versions are kept: - Remove 18 ignores that are unused in every configuration, keeping the "ty: ignore" half where ty still needs it. - Narrow the AnsiDecoder.decode monkey patch ignore to [method-assign]. - Mark the NoConsoleScreenBufferError fallback ignore as [no-redef, unused-ignore] since the redefinition only exists on win32. - Guard Cmd2HelpFormatter._set_color() with a positive version check instead of an early return so mypy skips it on Python < 3.14 rather than reporting the rest of the method as unreachable. - Annotate Cmd._initial_termios_settings as list[Any] | None and add an explicit platform check to the termios restore code. Previously mypy inferred the attribute as always None on win32 and only avoided checking that POSIX-only code because it looked unreachable.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1768 +/- ##
==========================================
- Coverage 99.66% 99.66% -0.01%
==========================================
Files 23 23
Lines 5974 5973 -1
==========================================
- Hits 5954 5953 -1
Misses 20 20
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
mypy 2.4.0 switched to its new Ruff-based native parser by default. That parser rejects third-party codes such as
ty:unresolved-attributeinside# type: ignore[...]comments, so every combined mypy/ty ignore incmd2/produced anInvalid "type: ignore" comment [syntax]error and stopped suppressing the diagnostic it was there for (75 errors in total). Running with--no-native-parserproduced no errors, so nothing else in 2.4 affects cmd2.Commit 1: Split combined ignore comments
The 43 combined comments are now two separate pragmas:
This form works with mypy's native and legacy parsers and with ty. The mypy pragma has to come first, and ty still needs its own rule code. This also bumps the ruff pre-commit hook to v0.16.10.
Commit 2: Enable
warn_unused_ignoresand remove stale ignoreswarn_unused_ignoreswas turned off because mypy's legacy parser reported everyty:code as unused. With the comments split it can be turned back on. That exposed 25 stale or platform-specific ignores. I checked each one with Python 3.11–3.15 on linux, darwin, and win32 so that ignores needed only on some platforms or versions are kept:# ty: ignore[...]half stays.AnsiDecoder.decodemonkey-patch ignore, fromassignmenttomethod-assign.NoConsoleScreenBufferError: now[no-redef, unused-ignore], because the redefinition only exists on win32.Cmd2HelpFormatter._set_color(): usesif sys.version_info >= (3, 14):instead of an early return. mypy skips version-guarded blocks instead of reporting the rest of the method as unreachable on older Pythons. Behavior is unchanged.Cmd._initial_termios_settings: annotated aslist[Any] | None, with an explicitnot sys.platform.startswith("win")check added to the two termios restore conditions. mypy had inferred the attribute as alwaysNoneon win32, so it never checked that POSIX-only code there. The new check changes nothing at runtime: the attribute is alwaysNoneon Windows, and the termios tests already skip on Windows.Testing
make check,make test, andmake docs-testpass.warn_unused_ignores = truefor Python 3.11, 3.12, 3.13, 3.14, and 3.15, each on linux, darwin, and win32. The 3.11–3.14 runs used environments built like the TypeCheck workflow's (--no-default-groups --group validate).ty: ignorecomments with--warn unused-ignore-comment.