-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Alternate method of handling dict.get default value #13224
Conversation
This comment has been minimized.
This comment has been minimized.
Diff from mypy_primer, showing the effect of this PR on open source code: prefect (https://github.com/PrefectHQ/prefect)
+ src/prefect/locking/memory.py:194: note: def get(self, Never, None, /) -> None
+ src/prefect/locking/memory.py:205: note: def get(self, Never, None, /) -> None
+ src/prefect/records/memory.py:176: note: def get(self, Never, None, /) -> None
steam.py (https://github.com/Gobot1234/steam.py)
+ steam/ext/commands/utils.py:43: note: @overload
+ steam/ext/commands/utils.py:43: note: def get(self, str, None, /) -> _VT | None
streamlit (https://github.com/streamlit/streamlit)
+ lib/streamlit/runtime/state/session_state.py: note: In member "get_id_from_key" of class "KeyIdMapper":
+ lib/streamlit/runtime/state/session_state.py:314:9: error: Returning Any from function declared to return "str" [no-any-return]
operator (https://github.com/canonical/operator)
- ops/_private/harness.py:1193: error: Argument 2 to "get" of "dict" has incompatible type "None"; expected "Mapping[str, str]" [arg-type]
+ ops/_private/harness.py:1193: error: Incompatible return value type (got "dict[str, str] | None", expected "Mapping[str, str]") [return-value]
beartype (https://github.com/beartype/beartype)
+ beartype/_check/error/errcause.py:551: error: Incompatible types in assignment (expression has type "Callable[[ViolationCause], ViolationCause] | None", variable has type "Callable[[ViolationCause], ViolationCause]") [assignment]
+ beartype/_check/error/errcause.py:552: error: Unused "type: ignore" comment [unused-ignore]
mypy (https://github.com/python/mypy)
+ mypy/partially_defined.py:510: error: Never apply isinstance() to unexpanded types; use mypy.types.get_proper_type() first [misc]
+ mypy/partially_defined.py:510: note: If you pass on the original type after the check, always use its unexpanded version
|
prefect and stream.py are no actual change. operator and beartype are both changing an existing error from an argument error to a return type error. I dug into the streamlit error. It's something hinky. This produces a new error with this change: from typing import Any
def get_id_from_key(key_id_mapping: dict[str, str], default: Any) -> str:
return key_id_mapping.get("key", default) But this version: from typing import Any
def get_id_from_key(key_id_mapping: dict[str, str], default: Any) -> str:
result = key_id_mapping.get("key", default)
return result Which assigns the return value to a variable before returning, causes mypy to generate |
Okay, what's going on there is that with the call in the return position, mypy uses the context of the return type being str while checking the overloads. overload 1 is discard as non-matching. Overload two is The new overload in this MR get The difference between here and assigning to result first is that in that case, mypy doesn't have the context to infer So that's all probably fine and sensible. |
Short version of the mypy diff is that I think this is similar to the streamlit error in that mypy uses context. For streamlit, it matched Any to the context of str normally, and here it's matching 'None' to the context of 'object' and skipping the union. We don't reach that with this MR applied - we match None to None first and don't reach the final branch of the overload. In a normal context, that's fine, and we'll match the union of Type and None down to object a little later, but the mypy plugin is checking before that happens in this case. |
Testing to see what this looks like compared to #13222
I also updated
typing.Mapping.get()
overloads to match dict. This may be disruptive. It was attempted in #10501 but backed out, so let's see if it's still a problem while we're here.