Skip to content

Commit 01efd35

Browse files
Add type inference for dict.keys membership
Also for containership checks on `typing.KeysView.` This is to bring the following cases into alignment: from typing import KeysView key: str | None d: dict[str, int] kv: KeysView[str] if key in d: # type of 'key' is inferred to be 'str' ... if key in d.keys(): # type of 'key' should be inferred to be 'str' ... if key in kv: # type of 'key' should be inferred to be 'str' ... Before this change only the first `if` would narrow the type of `key`. I've just added a test under `test-data/unit/pythoneval.test` as `test-data/unit/fixtures/dict.pyi` doesn't include `dict.keys`, and adding it requires importing `dict_keys` from `_collections_abc` in those stubs, which then requires adding `_collections_abc.pyi` stubs, which would have to be complete since e.g. `testGenericAliasCollectionsABCReveal` expects most of the types in those stubs to be defined (this is the same approach as 7678f28). GH: issue #13360
1 parent 3aaa7a7 commit 01efd35

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

mypy/checker.py

+2
Original file line numberDiff line numberDiff line change
@@ -6297,6 +6297,8 @@ def builtin_item_type(tp: Type) -> Optional[Type]:
62976297
"builtins.dict",
62986298
"builtins.set",
62996299
"builtins.frozenset",
6300+
"_collections_abc.dict_keys",
6301+
"typing.KeysView",
63006302
]:
63016303
if not tp.args:
63026304
# TODO: fix tuple in lib-stub/builtins.pyi (it should be generic).

test-data/unit/pythoneval.test

+24
Original file line numberDiff line numberDiff line change
@@ -1636,3 +1636,27 @@ foo("")
16361636
foo(list(""))
16371637
foo(list((list(""), "")))
16381638
[out]
1639+
1640+
[case testNarrowTypeForDictKeys]
1641+
# flags: --strict-optional
1642+
from typing import Dict, KeysView, Optional
1643+
1644+
d: Dict[str, int]
1645+
key: Optional[str]
1646+
if key in d.keys():
1647+
reveal_type(key)
1648+
else:
1649+
reveal_type(key)
1650+
1651+
kv: KeysView[str]
1652+
k: Optional[str]
1653+
if k in kv:
1654+
reveal_type(k)
1655+
else:
1656+
reveal_type(k)
1657+
1658+
[out]
1659+
_testNarrowTypeForDictKeys.py:7: note: Revealed type is "builtins.str"
1660+
_testNarrowTypeForDictKeys.py:9: note: Revealed type is "Union[builtins.str, None]"
1661+
_testNarrowTypeForDictKeys.py:14: note: Revealed type is "builtins.str"
1662+
_testNarrowTypeForDictKeys.py:16: note: Revealed type is "Union[builtins.str, None]"

0 commit comments

Comments
 (0)