-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
fixed Incorrect type of enum in 'if' clause #20234 #20248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
Diff from mypy_primer, showing the effect of this PR on open source code: psycopg (https://github.com/psycopg/psycopg)
+ tests/pq/test_pgconn.py:508: error: Non-overlapping equality check (left operand type: "Literal[ConnStatus.STARTED, ConnStatus.MADE]", right operand type: "Literal[ConnStatus.OK]") [comparison-overlap]
prefect (https://github.com/PrefectHQ/prefect)
+ src/prefect/flows.py:3103: error: Redundant cast to "str" [redundant-cast]
+ src/prefect/flows.py:3116: error: Redundant cast to "str" [redundant-cast]
core (https://github.com/home-assistant/core)
- homeassistant/components/shelly/event.py:305: error: Argument 1 to "_trigger_event" of "EventEntity" has incompatible type "Any | None"; expected "str" [arg-type]
pytest (https://github.com/pytest-dev/pytest)
+ src/_pytest/config/argparsing.py:247: error: Statement is unreachable [unreachable]
steam.py (https://github.com/Gobot1234/steam.py)
- steam/ext/csgo/state.py:180: error: Argument "slot" to "Sticker" has incompatible type "int | None"; expected "Literal[0, 1, 2, 3, 4, 5] | None" [arg-type]
+ steam/ext/csgo/state.py:180: error: Argument "slot" to "Sticker" has incompatible type "int"; expected "Literal[0, 1, 2, 3, 4, 5] | None" [arg-type]
discord.py (https://github.com/Rapptz/discord.py)
+ discord/app_commands/models.py:900: error: Unused "type: ignore" comment [unused-ignore]
+ discord/threads.py:286: error: Unused "type: ignore" comment [unused-ignore]
xarray (https://github.com/pydata/xarray)
+ xarray/backends/writers.py:841: error: Unused "type: ignore" comment [unused-ignore]
|
| if isinstance(get_proper_type(iterable_type), TupleType): | ||
| # Check if this is an enum instance that can be narrowed | ||
| tuple_type = get_proper_type(iterable_type) | ||
| for i, item_type in enumerate(tuple_type.items): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| for i, item_type in enumerate(tuple_type.items): | |
| for item_type in tuple_type.items: |
| for i, item_type in enumerate(tuple_type.items): | ||
| if isinstance(item_type, Instance): | ||
|
|
||
| if item_type.type.is_enum: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
combine with the previous if statement (line 6601)
| literal_types = [] | ||
| if isinstance(get_proper_type(iterable_type), TupleType): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| literal_types = [] | |
| if isinstance(get_proper_type(iterable_type), TupleType): | |
| if isinstance(get_proper_type(iterable_type), TupleType): | |
| literal_types = [] |
|
Please don't use an LLM to generate the description or responses! We're fine with extremely short or curt text (I've made so many PRs where the description was just a "fixes [link]"...), and making it longer just wastes time. Additionally, could you add test cases to the tests? Mypy has an extensive unit test suite. (I know you mentioned them in the PR description, but really they belong as a test case) |
|
Thanks for the info, i thought the LLM prompt was so detailed, i'll add a shorter PR next time and fix the tests:) |
Fixes #20234 --- Correct Enum Literal Narrowing for
inOperator with TuplesProblem
When using the
inoperator with tuples containing enum members, mypyfailed to narrow the left-hand side to the correct enum literal type.
Before this fix:
Mypy treated the tuple contents as regular
Instancetypes and did notextract the literal enum values, so narrowing never happened.
Solution
Enhanced
comparison_type_narrowing_helperto detect tuples containingenum literals and correctly narrow the type based on the enum values
inside the tuple.
Key Points:
LiteralType.last_known_value.Unionof enumliterals, and applies narrowing on the true branch of the
inexpression.
Implementation Details
File:
mypy/checker.pyFunction:
comparison_type_narrowing_helperAdded enum-specific logic immediately after the existing
None-removalnarrowing for the
inoperator:Union[Literal[Enum.X], Literal[Enum.Y], ...]\inandnot inTests & Behavior
Correctly handled:
python if op in (Op.A,): reveal_type(op) # Literal[Op.A]python if op in (Op.A, Op.B): reveal_type(op) # Literal[Op.A] | Literal[Op.B]not inExample