Skip to content
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

Fix enum .value with tuple #15637

Open
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

A5rocks
Copy link
Contributor

@A5rocks A5rocks commented Jul 11, 2023

This makes .value not accidentally prune out one of its literals!

Alternatively (I just realized this now) we could just return the type without .last_known_value. I can switch to that if that's better. Anyways, I suspect this initial approach might be unpopular with mypy primer anyways!

Noticed this while looking at #14092!

Fixes #12523 (though this PR doesn't intend to do that...)

@github-actions

This comment has been minimized.

@A5rocks
Copy link
Contributor Author

A5rocks commented Jul 11, 2023

Yeah... As expected.

C().x = 4 # E: Cannot assign to final attribute "x"
C().x = 4 # E: Cannot assign to final attribute "x" \
# E: Incompatible types in assignment (expression has type "Literal[4]", variable has type "Literal[1]")
# TODO: this missing error is a sign of a bug!!
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I also wrote up #15640 while doing this (obviously).

I still need to make a minimized issue for this TODO.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

mypy/messages.py Outdated Show resolved Hide resolved
@A5rocks
Copy link
Contributor Author

A5rocks commented Jul 18, 2023

Turns out the error reporting fix I added fixes #12523!

@A5rocks
Copy link
Contributor Author

A5rocks commented Jul 18, 2023

Going through mypy primer:

  • most of the changes are fine, just more error reporting which is probably nicer (?)
    • this isn't always the case, but it's the case enough and I'm already using the best heuristic I can think of (i.e. whether both a literal and a non-literal are used)
  • steam.py gets an error because it tries to conditionally assign a final different values
    • I think this is expected.
  • pip and poetry get weird new inference errors
    • this is an existing problem I believe, I don't think this PR caused these. I can't think of how they're caused by anything I touched, other than comparing literals revealing these. last_known_value is probably forgotten somewhere?
    • I'm going to leave these alone for another PR (I may be horrible at scoping but even I'm not this bad), both of these can probably be fixed with just an explicit type

tl;dr all seems fine

@github-actions

This comment has been minimized.

@github-actions
Copy link
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

steam.py (https://github.com/Gobot1234/steam.py)
+ steam/_const.py:112: error: Incompatible types in assignment (expression has type "Literal['lxml-xml']", variable has type "Literal['html.parser']")  [assignment]
- steam/trade.py:194: error: Incompatible types in assignment (expression has type "tuple[str, str, str, str, str, str, str]", base class "Asset" defined the type as "tuple[str, str, str, str, str, str]")  [assignment]
+ steam/trade.py:194: error: Incompatible types in assignment (expression has type "tuple[Literal['name'], builtins.str, builtins.str, builtins.str, builtins.str, builtins.str, builtins.str]", base class "Asset" defined the type as "tuple[builtins.str, builtins.str, builtins.str, builtins.str, builtins.str, builtins.str]")  [assignment]

poetry (https://github.com/python-poetry/poetry)
+ tests/puzzle/test_solver.py:3463: error: Dict entry 0 has incompatible type "str": "Literal['0.1.0']"; expected "str": "Literal['repo'] | None"  [dict-item]
+ tests/puzzle/test_solver.py:3464: error: Dict entry 1 has incompatible type "str": "Literal["sys_platform == 'darwin'"]"; expected "str": "Literal['repo'] | None"  [dict-item]

comtypes (https://github.com/enthought/comtypes)
- comtypes/typeinfo.py:858: error: List item 0 has incompatible type "tuple[str, Module]"; expected "tuple[str, type[_CData]] | tuple[str, type[_CData], int]"  [list-item]
+ comtypes/typeinfo.py:858: error: List item 0 has incompatible type "tuple[Literal['guid'], Module]"; expected "tuple[builtins.str, type[_CData]] | tuple[builtins.str, type[_CData], int]"  [list-item]
- comtypes/typeinfo.py:891: error: List item 0 has incompatible type "tuple[str, Module]"; expected "tuple[str, type[_CData]] | tuple[str, type[_CData], int]"  [list-item]
+ comtypes/typeinfo.py:891: error: List item 0 has incompatible type "tuple[Literal['guid'], Module]"; expected "tuple[builtins.str, type[_CData]] | tuple[builtins.str, type[_CData], int]"  [list-item]

dragonchain (https://github.com/dragonchain/dragonchain)
- dragonchain/lib/database/redis_utest.py:217:35: error: Argument 2 to "zadd_sync" has incompatible type "str"; expected "Dict[str, int]"  [arg-type]
+ dragonchain/lib/database/redis_utest.py:217:35: error: Argument 2 to "zadd_sync" has incompatible type "Literal['banana']"; expected "Dict[builtins.str, int]"  [arg-type]

pip (https://github.com/pypa/pip)
+ src/pip/_internal/utils/deprecation.py:88: error: List item 1 has incompatible type "tuple[builtins.str | None, Literal['pip {} will enforce this behaviour change.'] | Literal['Since pip {}, this is no longer supported.']]"; expected "tuple[int | builtins.str | None, Literal['Discussion can be found at https://github.com/pypa/pip/issues/{}'] | Literal['You can use the flag --use-feature={} to test the upcoming behaviour.'] | None]"  [list-item]
+ src/pip/_internal/utils/deprecation.py:94: error: List item 2 has incompatible type "tuple[builtins.str | None, Literal['A possible replacement is {}.']]"; expected "tuple[int | builtins.str | None, Literal['Discussion can be found at https://github.com/pypa/pip/issues/{}'] | Literal['You can use the flag --use-feature={} to test the upcoming behaviour.'] | None]"  [list-item]

prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/server/database/configurations.py:234: error: Incompatible types in assignment (expression has type "str", target has type "dict[str, float | Any]")  [assignment]
+ src/prefect/server/database/configurations.py:234: error: Incompatible types in assignment (expression has type "Literal['named']", target has type "dict[builtins.str, float | Any]")  [assignment]
- src/prefect/server/database/query_components.py:213: error: Argument 2 to "where" of "Select" has incompatible type "Any | bool"; expected "ColumnElement[bool] | _HasClauseElement | SQLCoreOperations[bool] | ExpressionElementRole[bool] | Callable[[], ColumnElement[bool]] | LambdaElement"  [arg-type]
+ src/prefect/server/database/query_components.py:213: error: Argument 2 to "where" of "Select" has incompatible type "Any | Literal[True]"; expected "ColumnElement[builtins.bool] | _HasClauseElement | SQLCoreOperations[builtins.bool] | ExpressionElementRole[builtins.bool] | Callable[[], ColumnElement[builtins.bool]] | LambdaElement"  [arg-type]
- src/prefect/testing/utilities.py:186: error: Argument "sort" to "read_flow_runs" of "PrefectClient" has incompatible type "prefect.server.schemas.sorting.FlowRunSort"; expected "prefect.client.schemas.sorting.FlowRunSort"  [arg-type]
+ src/prefect/testing/utilities.py:186: error: Argument "sort" to "read_flow_runs" of "PrefectClient" has incompatible type "Literal[FlowRunSort.EXPECTED_START_TIME_ASC]"; expected "prefect.client.schemas.sorting.FlowRunSort"  [arg-type]

scikit-learn (https://github.com/scikit-learn/scikit-learn)
- sklearn/svm/tests/test_svm.py:596: error: List item 1 has incompatible type "tuple[type[NuSVC], str]"; expected "tuple[type[BaseSVC], str]"  [list-item]
+ sklearn/svm/tests/test_svm.py:596: error: List item 1 has incompatible type "tuple[type[NuSVC], Literal['specified nu is infeasible']]"; expected "tuple[type[BaseSVC], builtins.str]"  [list-item]
- sklearn/ensemble/tests/test_stacking.py:552: error: List item 1 has incompatible type "tuple[type[StackingRegressor], type[DummyRegressor], str, LinearRegression, Any, Any]"; expected "tuple[ABCMeta, type[BaseEstimator], str, BaseEstimator, Any, Any]"  [list-item]
+ sklearn/ensemble/tests/test_stacking.py:552: error: List item 1 has incompatible type "tuple[type[StackingRegressor], type[DummyRegressor], Literal['predict'], LinearRegression, Any, Any]"; expected "tuple[ABCMeta, type[BaseEstimator], builtins.str, BaseEstimator, Any, Any]"  [list-item]

apprise (https://github.com/caronc/apprise)
- apprise/plugins/NotifyMisskey.py:117: error: Incompatible types in assignment (expression has type "tuple[str, str]", variable has type "tuple[str]")  [assignment]
+ apprise/plugins/NotifyMisskey.py:117: error: Incompatible types in assignment (expression has type "tuple[Literal['{schema}://{token}@{host}'], Literal['{schema}://{token}@{host}:{port}']]", variable has type "tuple[builtins.str]")  [assignment]

streamlit (https://github.com/streamlit/streamlit)
- lib/tests/streamlit/elements/time_widgets_test.py:49:59: error: Argument "step" has incompatible type "Tuple[int, int]"; expected "Union[int, timedelta]"  [arg-type]
+ lib/tests/streamlit/elements/time_widgets_test.py:49:59: error: Argument "step" has incompatible type "Tuple[Literal[90], Literal[0]]"; expected "Union[builtins.int, timedelta]"  [arg-type]

discord.py (https://github.com/Rapptz/discord.py)
- discord/scheduled_event.py:491: error: Incompatible types in assignment (expression has type "int | int | int | int", target has type "str")  [assignment]
+ discord/scheduled_event.py:491: error: Incompatible types in assignment (expression has type "Literal[1] | Literal[2] | Literal[3] | Literal[4]", target has type "str")  [assignment]
- discord/scheduled_event.py:510: error: Incompatible types in assignment (expression has type "int | int | int", target has type "str")  [assignment]
+ discord/scheduled_event.py:510: error: Incompatible types in assignment (expression has type "Literal[1] | Literal[2] | Literal[3]", target has type "str")  [assignment]
- discord/guild.py:3161: error: Incompatible types in assignment (expression has type "int | int | int", target has type "str")  [assignment]
+ discord/guild.py:3161: error: Incompatible types in assignment (expression has type "Literal[1] | Literal[2] | Literal[3]", target has type "str")  [assignment]
- discord/app_commands/transformers.py:139: error: Incompatible types in assignment (expression has type "list[int | int | int | int | int | int | int | int | int | int | int]", target has type "str | int")  [assignment]
+ discord/app_commands/transformers.py:139: error: Incompatible types in assignment (expression has type "list[Literal[0] | Literal[1] | Literal[2] | Literal[3] | Literal[4] | Literal[5] | Literal[10] | Literal[11] | Literal[12] | Literal[13] | Literal[15]]", target has type "str | builtins.int")  [assignment]

@A5rocks A5rocks requested a review from ikonst July 18, 2023 08:36
@KotlinIsland
Copy link
Contributor

would really appreciate seeing this merged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Mypy inferring Union[str, str] when using enum.value inside dict.get
3 participants