-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Fix TypedDict.get("missing_key") with string literal #9906
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2227,7 +2227,7 @@ d[c_key] # E: TypedDict "Outer" has no key 'c' | |
|
||
reveal_type(d.get(a_key, u)) # N: Revealed type is 'Union[builtins.int, __main__.Unrelated]' | ||
reveal_type(d.get(b_key, u)) # N: Revealed type is 'Union[builtins.str, __main__.Unrelated]' | ||
d.get(c_key, u) # E: TypedDict "Outer" has no key 'c' | ||
reveal_type(d.get(c_key, u)) # N: Revealed type is 'builtins.object' | ||
|
||
reveal_type(d.pop(a_key)) # E: Key 'a' of TypedDict "Outer" cannot be deleted \ | ||
# N: Revealed type is 'builtins.int' | ||
|
@@ -2271,11 +2271,11 @@ reveal_type(a[int_key_good]) # N: Revealed type is 'builtins.int' | |
reveal_type(b[int_key_good]) # N: Revealed type is 'builtins.int' | ||
reveal_type(c[str_key_good]) # N: Revealed type is 'builtins.int' | ||
reveal_type(c.get(str_key_good, u)) # N: Revealed type is 'Union[builtins.int, __main__.Unrelated]' | ||
reveal_type(c.get(str_key_bad, u)) # N: Revealed type is 'builtins.object' | ||
|
||
a[int_key_bad] # E: Tuple index out of range | ||
b[int_key_bad] # E: Tuple index out of range | ||
c[str_key_bad] # E: TypedDict "MyDict" has no key 'missing' | ||
c.get(str_key_bad, u) # E: TypedDict "MyDict" has no key 'missing' | ||
[builtins fixtures/dict.pyi] | ||
[typing fixtures/typing-typeddict.pyi] | ||
[out] | ||
|
@@ -2342,12 +2342,12 @@ reveal_type(test.get(good_keys, 3)) # N: Revealed type is 'Union[_ | |
reveal_type(test.pop(optional_keys)) # N: Revealed type is 'Union[__main__.D, __main__.E]' | ||
reveal_type(test.pop(optional_keys, 3)) # N: Revealed type is 'Union[__main__.D, __main__.E, Literal[3]?]' | ||
reveal_type(test.setdefault(good_keys, AAndB())) # N: Revealed type is 'Union[__main__.A, __main__.B]' | ||
reveal_type(test.get(bad_keys)) # N: Revealed type is 'builtins.object*' | ||
reveal_type(test.get(bad_keys, 3)) # N: Revealed type is 'builtins.object' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be great if a maintainer could have a look at this. Therefor I just placed the needed asterisks by trial and error. This might or might not be wrong. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The asterisk means that it's an inferred type; I think it can be safely ignored. I'm not sure why mypy infers There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to PEP 589 "The static type of d.get(e) should be object if the string value of e cannot be determined statically". As far as I can tell PEP 589 doesn't say anything about Also something else not related to my code seems to convert There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The default doesn't change anything, since we can't infer the type of the value from the default (the value type could be an arbitrary union type, for example). Since typed dicts are heterogeneous, we can't predict the type of arbitrary keys. In this case the only possible precise type is A union that includes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the correction! |
||
del test[optional_keys] | ||
|
||
|
||
test[bad_keys] # E: TypedDict "Test" has no key 'bad' | ||
test.get(bad_keys) # E: TypedDict "Test" has no key 'bad' | ||
test.get(bad_keys, 3) # E: TypedDict "Test" has no key 'bad' | ||
test.pop(good_keys) # E: Key 'a' of TypedDict "Test" cannot be deleted \ | ||
# E: Key 'b' of TypedDict "Test" cannot be deleted | ||
test.pop(bad_keys) # E: Key 'a' of TypedDict "Test" cannot be deleted \ | ||
|
@@ -2436,14 +2436,12 @@ good_keys: Literal['b', 'c'] | |
|
||
x[bad_keys] # E: TypedDict "D1" has no key 'd' \ | ||
# E: TypedDict "D2" has no key 'a' | ||
x.get(bad_keys) # E: TypedDict "D1" has no key 'd' \ | ||
# E: TypedDict "D2" has no key 'a' | ||
x.get(bad_keys, 3) # E: TypedDict "D1" has no key 'd' \ | ||
# E: TypedDict "D2" has no key 'a' | ||
|
||
reveal_type(x[good_keys]) # N: Revealed type is 'Union[__main__.B, __main__.C]' | ||
reveal_type(x.get(good_keys)) # N: Revealed type is 'Union[__main__.B, __main__.C]' | ||
reveal_type(x.get(good_keys, 3)) # N: Revealed type is 'Union[__main__.B, Literal[3]?, __main__.C]' | ||
reveal_type(x.get(bad_keys)) # N: Revealed type is 'builtins.object*' | ||
reveal_type(x.get(bad_keys, 3)) # N: Revealed type is 'builtins.object' | ||
|
||
[builtins fixtures/dict.pyi] | ||
[typing fixtures/typing-typeddict.pyi] | ||
|
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.
Shouldn't this infer
Unrelated
, or at least a Union of something withUnrelated
?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.
Like in the other discussion, the type here would be
Union[builtins.object, Unrelated]
, which mypy simplifies tobuiltins.object