Skip to content

Commit fa44143

Browse files
authored
Fix TypedDict.get("missing_key") with string literal (#9906)
Previously this would throw an error, however according to PEP 589 .get() should be allowed for arbitrary expressions with type str, while only [] throws an error.
1 parent bd47eb7 commit fa44143

File tree

4 files changed

+12
-16
lines changed

4 files changed

+12
-16
lines changed

mypy/plugins/default.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,7 @@ def typed_dict_get_callback(ctx: MethodContext) -> Type:
237237
for key in keys:
238238
value_type = get_proper_type(ctx.type.items.get(key))
239239
if value_type is None:
240-
ctx.api.msg.typeddict_key_not_found(ctx.type, key, ctx.context)
241-
return AnyType(TypeOfAny.from_error)
240+
return ctx.default_return_type
242241

243242
if len(ctx.arg_types) == 1:
244243
output_types.append(value_type)

test-data/unit/check-literal.test

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2227,7 +2227,7 @@ d[c_key] # E: TypedDict "Outer" has no key 'c'
22272227

22282228
reveal_type(d.get(a_key, u)) # N: Revealed type is 'Union[builtins.int, __main__.Unrelated]'
22292229
reveal_type(d.get(b_key, u)) # N: Revealed type is 'Union[builtins.str, __main__.Unrelated]'
2230-
d.get(c_key, u) # E: TypedDict "Outer" has no key 'c'
2230+
reveal_type(d.get(c_key, u)) # N: Revealed type is 'builtins.object'
22312231

22322232
reveal_type(d.pop(a_key)) # E: Key 'a' of TypedDict "Outer" cannot be deleted \
22332233
# N: Revealed type is 'builtins.int'
@@ -2271,11 +2271,11 @@ reveal_type(a[int_key_good]) # N: Revealed type is 'builtins.int'
22712271
reveal_type(b[int_key_good]) # N: Revealed type is 'builtins.int'
22722272
reveal_type(c[str_key_good]) # N: Revealed type is 'builtins.int'
22732273
reveal_type(c.get(str_key_good, u)) # N: Revealed type is 'Union[builtins.int, __main__.Unrelated]'
2274+
reveal_type(c.get(str_key_bad, u)) # N: Revealed type is 'builtins.object'
22742275

22752276
a[int_key_bad] # E: Tuple index out of range
22762277
b[int_key_bad] # E: Tuple index out of range
22772278
c[str_key_bad] # E: TypedDict "MyDict" has no key 'missing'
2278-
c.get(str_key_bad, u) # E: TypedDict "MyDict" has no key 'missing'
22792279
[builtins fixtures/dict.pyi]
22802280
[typing fixtures/typing-typeddict.pyi]
22812281
[out]
@@ -2342,12 +2342,12 @@ reveal_type(test.get(good_keys, 3)) # N: Revealed type is 'Union[_
23422342
reveal_type(test.pop(optional_keys)) # N: Revealed type is 'Union[__main__.D, __main__.E]'
23432343
reveal_type(test.pop(optional_keys, 3)) # N: Revealed type is 'Union[__main__.D, __main__.E, Literal[3]?]'
23442344
reveal_type(test.setdefault(good_keys, AAndB())) # N: Revealed type is 'Union[__main__.A, __main__.B]'
2345+
reveal_type(test.get(bad_keys)) # N: Revealed type is 'builtins.object*'
2346+
reveal_type(test.get(bad_keys, 3)) # N: Revealed type is 'builtins.object'
23452347
del test[optional_keys]
23462348

23472349

23482350
test[bad_keys] # E: TypedDict "Test" has no key 'bad'
2349-
test.get(bad_keys) # E: TypedDict "Test" has no key 'bad'
2350-
test.get(bad_keys, 3) # E: TypedDict "Test" has no key 'bad'
23512351
test.pop(good_keys) # E: Key 'a' of TypedDict "Test" cannot be deleted \
23522352
# E: Key 'b' of TypedDict "Test" cannot be deleted
23532353
test.pop(bad_keys) # E: Key 'a' of TypedDict "Test" cannot be deleted \
@@ -2436,14 +2436,12 @@ good_keys: Literal['b', 'c']
24362436

24372437
x[bad_keys] # E: TypedDict "D1" has no key 'd' \
24382438
# E: TypedDict "D2" has no key 'a'
2439-
x.get(bad_keys) # E: TypedDict "D1" has no key 'd' \
2440-
# E: TypedDict "D2" has no key 'a'
2441-
x.get(bad_keys, 3) # E: TypedDict "D1" has no key 'd' \
2442-
# E: TypedDict "D2" has no key 'a'
24432439

24442440
reveal_type(x[good_keys]) # N: Revealed type is 'Union[__main__.B, __main__.C]'
24452441
reveal_type(x.get(good_keys)) # N: Revealed type is 'Union[__main__.B, __main__.C]'
24462442
reveal_type(x.get(good_keys, 3)) # N: Revealed type is 'Union[__main__.B, Literal[3]?, __main__.C]'
2443+
reveal_type(x.get(bad_keys)) # N: Revealed type is 'builtins.object*'
2444+
reveal_type(x.get(bad_keys, 3)) # N: Revealed type is 'builtins.object'
24472445

24482446
[builtins fixtures/dict.pyi]
24492447
[typing fixtures/typing-typeddict.pyi]

test-data/unit/check-typeddict.test

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -969,8 +969,8 @@ d.get('x', 1, 2) # E: No overload variant of "get" of "Mapping" matches argument
969969
# N: Possible overload variants: \
970970
# N: def get(self, k: str) -> object \
971971
# N: def [V] get(self, k: str, default: Union[int, V]) -> object
972-
x = d.get('z') # E: TypedDict "D" has no key 'z'
973-
reveal_type(x) # N: Revealed type is 'Any'
972+
x = d.get('z')
973+
reveal_type(x) # N: Revealed type is 'builtins.object*'
974974
s = ''
975975
y = d.get(s)
976976
reveal_type(y) # N: Revealed type is 'builtins.object*'
@@ -1689,8 +1689,7 @@ td: Union[TDA, TDB]
16891689

16901690
reveal_type(td.get('a')) # N: Revealed type is 'builtins.int'
16911691
reveal_type(td.get('b')) # N: Revealed type is 'Union[builtins.str, builtins.int]'
1692-
reveal_type(td.get('c')) # E: TypedDict "TDA" has no key 'c' \
1693-
# N: Revealed type is 'Union[Any, builtins.int]'
1692+
reveal_type(td.get('c')) # N: Revealed type is 'builtins.object*'
16941693

16951694
reveal_type(td['a']) # N: Revealed type is 'builtins.int'
16961695
reveal_type(td['b']) # N: Revealed type is 'Union[builtins.str, builtins.int]'

test-data/unit/pythoneval.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,14 +1074,14 @@ D = TypedDict('D', {'x': int, 'y': str})
10741074
d: D
10751075
reveal_type(d.get('x'))
10761076
reveal_type(d.get('y'))
1077-
d.get('z')
1077+
reveal_type(d.get('z'))
10781078
d.get()
10791079
s = ''
10801080
reveal_type(d.get(s))
10811081
[out]
10821082
_testTypedDictGet.py:7: note: Revealed type is 'builtins.int'
10831083
_testTypedDictGet.py:8: note: Revealed type is 'builtins.str'
1084-
_testTypedDictGet.py:9: error: TypedDict "D" has no key 'z'
1084+
_testTypedDictGet.py:9: note: Revealed type is 'builtins.object*'
10851085
_testTypedDictGet.py:10: error: All overload variants of "get" of "Mapping" require at least one argument
10861086
_testTypedDictGet.py:10: note: Possible overload variants:
10871087
_testTypedDictGet.py:10: note: def get(self, key: str) -> object

0 commit comments

Comments
 (0)