Skip to content

Commit 70bf1d6

Browse files
pkchJukkaL
authored andcommitted
Allow isinstance/issubclass with nested tuples (#2995)
Fix #2994
1 parent caa68d5 commit 70bf1d6

File tree

3 files changed

+27
-10
lines changed

3 files changed

+27
-10
lines changed

mypy/checker.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2726,12 +2726,7 @@ def flatten(t: Expression) -> List[Expression]:
27262726

27272727

27282728
def get_isinstance_type(expr: Expression, type_map: Dict[Expression, Type]) -> Type:
2729-
type = type_map[expr]
2730-
2731-
if isinstance(type, TupleType):
2732-
all_types = type.items
2733-
else:
2734-
all_types = [type]
2729+
all_types = [type_map[e] for e in flatten(expr)]
27352730

27362731
types = [] # type: List[Type]
27372732

test-data/unit/check-isinstance.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,22 @@ z = [a.y for b in y for a in b]
3131

3232
[builtins fixtures/list.pyi]
3333

34+
[case testIsinstanceNestedTuple]
35+
from typing import Union, List, Tuple, Dict
36+
def f(x: Union[int, str, List]) -> None:
37+
if isinstance(x, (str, (int,))):
38+
reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.str]'
39+
x[1] # E: Value of type "Union[int, str]" is not indexable
40+
else:
41+
reveal_type(x) # E: Revealed type is 'builtins.list[Any]'
42+
x[1]
43+
reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.list[Any]]'
44+
if isinstance(x, (str, (list,))):
45+
reveal_type(x) # E: Revealed type is 'Union[builtins.str, builtins.list[Any]]'
46+
x[1]
47+
reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.list[Any]]'
48+
[builtins fixtures/isinstancelist.pyi]
49+
3450
[case testClassAttributeInitialization-skip]
3551
class A:
3652
x = None # type: int

test-data/unit/fixtures/isinstancelist.pyi

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import builtinclass, Iterable, Iterator, Generic, TypeVar, List, Mapping, overload, Tuple
1+
from typing import builtinclass, Iterable, Iterator, TypeVar, List, Mapping, overload, Tuple, Set, Union
22

33
@builtinclass
44
class object:
@@ -11,7 +11,7 @@ class type:
1111
class tuple: pass
1212
class function: pass
1313

14-
def isinstance(x: object, t: type) -> bool: pass
14+
def isinstance(x: object, t: Union[type, Tuple]) -> bool: pass
1515

1616
@builtinclass
1717
class int:
@@ -27,18 +27,24 @@ T = TypeVar('T')
2727
KT = TypeVar('KT')
2828
VT = TypeVar('VT')
2929

30-
class list(Iterable[T], Generic[T]):
30+
class list(Iterable[T]):
3131
def __iter__(self) -> Iterator[T]: pass
3232
def __mul__(self, x: int) -> list[T]: pass
3333
def __setitem__(self, x: int, v: T) -> None: pass
3434
def __getitem__(self, x: int) -> T: pass
3535
def __add__(self, x: List[T]) -> T: pass
3636

37-
class dict(Iterable[KT], Mapping[KT, VT], Generic[KT, VT]):
37+
class dict(Iterable[KT], Mapping[KT, VT]):
3838
@overload
3939
def __init__(self, **kwargs: VT) -> None: pass
4040
@overload
4141
def __init__(self, arg: Iterable[Tuple[KT, VT]], **kwargs: VT) -> None: pass
4242
def __setitem__(self, k: KT, v: VT) -> None: pass
4343
def __iter__(self) -> Iterator[KT]: pass
4444
def update(self, a: Mapping[KT, VT]) -> None: pass
45+
46+
class set(Iterable[T]):
47+
def __iter__(self) -> Iterator[T]: pass
48+
def add(self, x: T) -> None: pass
49+
def discard(self, x: T) -> None: pass
50+
def update(self, x: Set[T]) -> None: pass

0 commit comments

Comments
 (0)