Skip to content

Commit 5fd5a93

Browse files
squash! Add type inference for dict.keys membership
Move tests under `test-data/unit/pythoneval.test` this is to avoid me having to add test stubs handling `dict.keys` which was rather difficult because: * The implementation requires me importing `dict_keys` from `_collections_abc` in `test-data/unit/fixtures/dict.pyi` * Since there aren't any stubs for this, a large number of tests would start failing, e.g. $ pytest -q mypy/test/testcheck.py::TypeCheckSuite::check-incremental.test::testIncrementalWithDifferentKindsOfNestedTypesWithinMethod F [100%] ========================================================================== FAILURES =========================================================================== _________________________________________________ testIncrementalWithDifferentKindsOfNestedTypesWithinMethod __________________________________________________ data: /home/mjh/src/mypy/test-data/unit/check-incremental.test:5662: /home/mjh/src/mypy/mypy/test/testcheck.py:80: in run_case self.run_case_once(testcase, ops, step) /home/mjh/src/mypy/mypy/test/testcheck.py:174: in run_case_once assert_string_arrays_equal(output, a, msg.format(testcase.file, testcase.line)) E AssertionError: Unexpected type checker output in incremental, run 2 (/home/mjh/src/mypy/test-data/unit/check-incremental.test, line 5662) -------------------------------------------------------------------- Captured stderr call --------------------------------------------------------------------- Expected: tmp/a.py:2: error: "object" has no attribute "xyz" (diff) Actual: tmp/a.py:2: error: Module has no attribute "xyz" (diff) Alignment of first line difference: E: tmp/a.py:2: error: "object" has no attribute "xyz" A: tmp/a.py:2: error: Module has no attribute "xyz" ^ =================================================================== short test summary info =================================================================== FAILED mypy/test/testcheck.py::TypeCheckSuite::check-incremental.test::testIncrementalWithDifferentKindsOfNestedTypesWithinMethod 1 failed in 0.33s * If I _were_ to add `test-data/unit/lib-stub/_collections_abc.pyi` then tests importing from `collections.abc` start failing, e.g. ____________________________________________________________ testGenericAliasCollectionsABCReveal _____________________________________________________________ data: /home/mjh/src/mypy/test-data/unit/check-generic-alias.test:147: /home/mjh/src/mypy/mypy/test/testcheck.py:82: in run_case self.run_case_once(testcase) /home/mjh/src/mypy/mypy/test/testcheck.py:174: in run_case_once assert_string_arrays_equal(output, a, msg.format(testcase.file, testcase.line)) E AssertionError: Unexpected type checker output (/home/mjh/src/mypy/test-data/unit/check-generic-alias.test, line 147) -------------------------------------------------------------------- Captured stderr call --------------------------------------------------------------------- Expected: Actual: main:6: error: Name "collections.abc.AsyncIterable" is not defined (diff) main:7: error: Name "collections.abc.AsyncIterator" is not defined (diff) main:8: error: Name "collections.abc.AsyncGenerator" is not defined (diff) main:12: error: Name "collections.abc.Reversible" is not defined (diff) main:13: error: Name "collections.abc.Container" is not defined (diff) main:14: error: Name "collections.abc.Collection" is not defined (diff) main:16: error: Name "collections.abc.Set" is not defined (diff) main:17: error: Name "collections.abc.MutableSet" is not defined (diff) main:19: error: Name "collections.abc.MutableMapping" is not defined (diff) main:21: error: Name "collections.abc.MutableSequence" is not defined (diff) main:22: error: Name "collections.abc.ByteString" is not defined (diff) main:23: error: Name "collections.abc.MappingView" is not defined (diff) main:24: error: Name "collections.abc.KeysView" is not defined (diff) main:25: error: Name "collections.abc.ItemsView" is not defined (diff) main:26: error: Name "collections.abc.ValuesView" is not defined (diff)
1 parent b5050c0 commit 5fd5a93

File tree

3 files changed

+12
-15
lines changed

3 files changed

+12
-15
lines changed

test-data/unit/check-isinstance.test

-13
Original file line numberDiff line numberDiff line change
@@ -2065,19 +2065,6 @@ def f() -> None:
20652065
[builtins fixtures/dict.pyi]
20662066
[out]
20672067

2068-
[case testNarrowTypeAfterInDictKeys]
2069-
# flags: --strict-optional
2070-
from typing import Dict, Optional
2071-
2072-
def f() -> None:
2073-
d: Dict[str, str] = {}
2074-
key: Optional[str]
2075-
if key in d.keys():
2076-
reveal_type(key) # N: Revealed type is "builtins.str"
2077-
else:
2078-
reveal_type(key) # N: Revealed type is "Union[builtins.str, None]"
2079-
[builtins fixtures/dict.pyi]
2080-
20812068
[case testIsinstanceWidensWithAnyArg]
20822069
from typing import Any
20832070
class A: ...

test-data/unit/fixtures/dict.pyi

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Builtins stub used in dictionary-related test cases.
22

3-
from _collections_abc import dict_keys
43
from typing import (
54
TypeVar, Generic, Iterable, Iterator, Mapping, Tuple, overload, Optional, Union, Sequence
65
)
@@ -31,7 +30,6 @@ class dict(Mapping[KT, VT]):
3130
@overload
3231
def get(self, k: KT, default: Union[KT, T]) -> Union[VT, T]: pass
3332
def __len__(self) -> int: ...
34-
def keys(self) -> dict_keys[KT, VT]: ...
3533

3634
class int: # for convenience
3735
def __add__(self, x: Union[int, complex]) -> int: pass

test-data/unit/pythoneval.test

+12
Original file line numberDiff line numberDiff line change
@@ -1612,3 +1612,15 @@ class Foo(Enum):
16121612
_testEnumValueWithPlaceholderNodeType.py:5: error: Incompatible types in assignment (expression has type "object", variable has type "Foo")
16131613
_testEnumValueWithPlaceholderNodeType.py:6: error: Incompatible types in assignment (expression has type "object", variable has type "Foo")
16141614
_testEnumValueWithPlaceholderNodeType.py:6: error: Name "Missing" is not defined
1615+
1616+
[case testNarrowTypeAfterInDictKeys]
1617+
# flags: --strict-optional
1618+
from typing import Dict, Optional
1619+
1620+
def f() -> None:
1621+
d: Dict[str, str] = {}
1622+
key: Optional[str]
1623+
if key in d.keys():
1624+
reveal_type(key) # N: Revealed type is "builtins.str"
1625+
else:
1626+
reveal_type(key) # N: Revealed type is "Union[builtins.str, None]"

0 commit comments

Comments
 (0)