From 3f1e9889a1c5b015ae229d13c5e7cfda7cccd020 Mon Sep 17 00:00:00 2001 From: Max Moroz Date: Tue, 14 Mar 2017 04:14:28 -0700 Subject: [PATCH 1/4] Allow isinstance/issubclass with nested tuples --- mypy/checker.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 307afe8568d5..f31d4c300e19 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -2693,12 +2693,7 @@ def flatten(t: Expression) -> List[Expression]: def get_isinstance_type(expr: Expression, type_map: Dict[Expression, Type]) -> Type: - type = type_map[expr] - - if isinstance(type, TupleType): - all_types = type.items - else: - all_types = [type] + all_types = [type_map[e] for e in flatten(expr)] types = [] # type: List[Type] From 308903fdcc28db66dfe00ed2cda4eed28cbb2292 Mon Sep 17 00:00:00 2001 From: Max Moroz Date: Tue, 14 Mar 2017 13:51:09 -0700 Subject: [PATCH 2/4] Add unit test --- test-data/unit/check-isinstance.test | 7 +++++++ test-data/unit/fixtures/isinstancelist.pyi | 10 ++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/test-data/unit/check-isinstance.test b/test-data/unit/check-isinstance.test index 9a1b787391a9..cea9b062ae7f 100644 --- a/test-data/unit/check-isinstance.test +++ b/test-data/unit/check-isinstance.test @@ -31,6 +31,13 @@ z = [a.y for b in y for a in b] [builtins fixtures/list.pyi] +[case testIsinstanceNestedTuple] +from typing import Union, List, Tuple +def f(x: Union[int, str, List, Tuple]) -> None: + if isinstance(x, (str, (int, tuple))): + x[1] # E: Value of type "Union[int, str, tuple]" is not indexable +[builtins fixtures/isinstancelist.pyi] + [case testClassAttributeInitialization-skip] class A: x = None # type: int diff --git a/test-data/unit/fixtures/isinstancelist.pyi b/test-data/unit/fixtures/isinstancelist.pyi index 4b3569875ab9..809d1e22d81d 100644 --- a/test-data/unit/fixtures/isinstancelist.pyi +++ b/test-data/unit/fixtures/isinstancelist.pyi @@ -1,4 +1,4 @@ -from typing import builtinclass, Iterable, Iterator, Generic, TypeVar, List, Mapping, overload, Tuple +from typing import builtinclass, Iterable, Iterator, Generic, TypeVar, List, Mapping, overload, Tuple, Set, Union @builtinclass class object: @@ -11,7 +11,7 @@ class type: class tuple: pass class function: pass -def isinstance(x: object, t: type) -> bool: pass +def isinstance(x: object, t: Union[type, Tuple]) -> bool: pass @builtinclass class int: @@ -42,3 +42,9 @@ class dict(Iterable[KT], Mapping[KT, VT], Generic[KT, VT]): def __setitem__(self, k: KT, v: VT) -> None: pass def __iter__(self) -> Iterator[KT]: pass def update(self, a: Mapping[KT, VT]) -> None: pass + +class set(Iterable[T], Generic[T]): + def __iter__(self) -> Iterator[T]: pass + def add(self, x: T) -> None: pass + def discard(self, x: T) -> None: pass + def update(self, x: Set[T]) -> None: pass From 19a190cc08007b6b4756ed59ccedc630e31b759f Mon Sep 17 00:00:00 2001 From: Max Moroz Date: Sat, 18 Mar 2017 12:33:14 -0700 Subject: [PATCH 3/4] Add a passing unit test, remove Generic from .pyi --- test-data/unit/check-isinstance.test | 6 +++++- test-data/unit/fixtures/isinstancelist.pyi | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/test-data/unit/check-isinstance.test b/test-data/unit/check-isinstance.test index cea9b062ae7f..0b2ceffb85e5 100644 --- a/test-data/unit/check-isinstance.test +++ b/test-data/unit/check-isinstance.test @@ -32,10 +32,14 @@ z = [a.y for b in y for a in b] [builtins fixtures/list.pyi] [case testIsinstanceNestedTuple] -from typing import Union, List, Tuple +from typing import Union, List, Tuple, Dict def f(x: Union[int, str, List, Tuple]) -> None: if isinstance(x, (str, (int, tuple))): x[1] # E: Value of type "Union[int, str, tuple]" is not indexable + else: + x[1] + if isinstance(x, (str, (list,))): + x[1] [builtins fixtures/isinstancelist.pyi] [case testClassAttributeInitialization-skip] diff --git a/test-data/unit/fixtures/isinstancelist.pyi b/test-data/unit/fixtures/isinstancelist.pyi index 809d1e22d81d..9096961b06ab 100644 --- a/test-data/unit/fixtures/isinstancelist.pyi +++ b/test-data/unit/fixtures/isinstancelist.pyi @@ -1,4 +1,4 @@ -from typing import builtinclass, Iterable, Iterator, Generic, TypeVar, List, Mapping, overload, Tuple, Set, Union +from typing import builtinclass, Iterable, Iterator, TypeVar, List, Mapping, overload, Tuple, Set, Union @builtinclass class object: @@ -27,14 +27,14 @@ T = TypeVar('T') KT = TypeVar('KT') VT = TypeVar('VT') -class list(Iterable[T], Generic[T]): +class list(Iterable[T]): def __iter__(self) -> Iterator[T]: pass def __mul__(self, x: int) -> list[T]: pass def __setitem__(self, x: int, v: T) -> None: pass def __getitem__(self, x: int) -> T: pass def __add__(self, x: List[T]) -> T: pass -class dict(Iterable[KT], Mapping[KT, VT], Generic[KT, VT]): +class dict(Iterable[KT], Mapping[KT, VT]): @overload def __init__(self, **kwargs: VT) -> None: pass @overload @@ -43,7 +43,7 @@ class dict(Iterable[KT], Mapping[KT, VT], Generic[KT, VT]): def __iter__(self) -> Iterator[KT]: pass def update(self, a: Mapping[KT, VT]) -> None: pass -class set(Iterable[T], Generic[T]): +class set(Iterable[T]): def __iter__(self) -> Iterator[T]: pass def add(self, x: T) -> None: pass def discard(self, x: T) -> None: pass From f69ed43b404a6bc6288f3d838a3d9470a86e532d Mon Sep 17 00:00:00 2001 From: Max Moroz Date: Sat, 18 Mar 2017 13:58:41 -0700 Subject: [PATCH 4/4] Add reveal_type to test; remove tuple from test --- test-data/unit/check-isinstance.test | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test-data/unit/check-isinstance.test b/test-data/unit/check-isinstance.test index 0b2ceffb85e5..43dbfd8321d1 100644 --- a/test-data/unit/check-isinstance.test +++ b/test-data/unit/check-isinstance.test @@ -33,13 +33,18 @@ z = [a.y for b in y for a in b] [case testIsinstanceNestedTuple] from typing import Union, List, Tuple, Dict -def f(x: Union[int, str, List, Tuple]) -> None: - if isinstance(x, (str, (int, tuple))): - x[1] # E: Value of type "Union[int, str, tuple]" is not indexable +def f(x: Union[int, str, List]) -> None: + if isinstance(x, (str, (int,))): + reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.str]' + x[1] # E: Value of type "Union[int, str]" is not indexable else: + reveal_type(x) # E: Revealed type is 'builtins.list[Any]' x[1] + reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.list[Any]]' if isinstance(x, (str, (list,))): + reveal_type(x) # E: Revealed type is 'Union[builtins.str, builtins.list[Any]]' x[1] + reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.list[Any]]' [builtins fixtures/isinstancelist.pyi] [case testClassAttributeInitialization-skip]