Skip to content

Commit 3334b8e

Browse files
committed
Apply CR comments
1 parent 1776e90 commit 3334b8e

File tree

3 files changed

+90
-60
lines changed

3 files changed

+90
-60
lines changed

mypy/checker.py

+20-38
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import sys
77

88
from typing import (
9-
Dict, Set, List, cast, Tuple, TypeVar, Union, Optional, NamedTuple, Iterator, MutableMapping
9+
Dict, Set, List, cast, Tuple, TypeVar, Union, Optional, NamedTuple, Iterator
1010
)
1111

1212
from mypy.errors import Errors, report_internal_error
@@ -2616,18 +2616,18 @@ def or_conditional_maps(m1: TypeMap, m2: TypeMap) -> TypeMap:
26162616
return result
26172617

26182618

2619-
def convert_to_types(m: MutableMapping[Expression, Type]) -> None:
2620-
for k in m:
2621-
x = m[k]
2622-
if isinstance(x, UnionType):
2623-
m[k] = UnionType([TypeType(t) for t in x.items])
2624-
elif isinstance(x, Instance):
2625-
m[k] = TypeType(m[k])
2619+
def convert_to_typetype(type_map: TypeMap) -> TypeMap:
2620+
converted_type_map: TypeMap = {}
2621+
for expr, typ in type_map.items():
2622+
if isinstance(typ, UnionType):
2623+
converted_type_map[expr] = UnionType([TypeType(t) for t in typ.items])
2624+
elif isinstance(typ, Instance):
2625+
converted_type_map[expr] = TypeType(typ)
26262626
else:
26272627
# TODO: verify this is ok
26282628
# unknown object, don't know how to convert
2629-
m.clear()
2630-
return
2629+
return {}
2630+
return converted_type_map
26312631

26322632

26332633
def find_isinstance_check(node: Expression,
@@ -2659,17 +2659,23 @@ def find_isinstance_check(node: Expression,
26592659
expr = node.args[0]
26602660
if expr.literal == LITERAL_TYPE:
26612661
vartype = type_map[expr]
2662-
type = get_issubclass_type(node.args[1], type_map)
2662+
type = get_isinstance_type(node.args[1], type_map)
26632663
if isinstance(vartype, UnionType):
2664-
vartype = UnionType([t.item for t in vartype.items]) # type: ignore
2664+
union_list = []
2665+
for t in vartype.items:
2666+
if isinstance(t, TypeType):
2667+
union_list.append(t.item)
2668+
else:
2669+
# this an error; should be caught earlier, so we should never be here
2670+
return {}, {}
2671+
vartype = UnionType(union_list)
26652672
elif isinstance(vartype, TypeType):
26662673
vartype = vartype.item
26672674
else:
26682675
# TODO: verify this is ok
26692676
return {}, {} # unknown type
26702677
yes_map, no_map = conditional_type_map(expr, vartype, type)
2671-
convert_to_types(yes_map)
2672-
convert_to_types(no_map)
2678+
yes_map, no_map = map(convert_to_typetype, (yes_map, no_map))
26732679
return yes_map, no_map
26742680
elif refers_to_fullname(node.callee, 'builtins.callable'):
26752681
expr = node.args[0]
@@ -2777,30 +2783,6 @@ def get_isinstance_type(expr: Expression, type_map: Dict[Expression, Type]) -> L
27772783
return types
27782784

27792785

2780-
def get_issubclass_type(expr: Expression, type_map: Dict[Expression, Type]) -> Type:
2781-
all_types = [type_map[e] for e in flatten(expr)]
2782-
2783-
types = [] # type: List[Type]
2784-
2785-
for type in all_types:
2786-
if isinstance(type, FunctionLike):
2787-
if type.is_type_obj():
2788-
# Type variables may be present -- erase them, which is the best
2789-
# we can do (outside disallowing them here).
2790-
type = erase_typevars(type.items()[0].ret_type)
2791-
types.append(type)
2792-
elif isinstance(type, TypeType):
2793-
types.append(type.item)
2794-
else: # we didn't see an actual type, but rather a variable whose value is unknown to us
2795-
return None
2796-
2797-
assert len(types) != 0
2798-
if len(types) == 1:
2799-
return types[0]
2800-
else:
2801-
return UnionType(types)
2802-
2803-
28042786
def expand_func(defn: FuncItem, map: Dict[TypeVarId, Type]) -> FuncItem:
28052787
visitor = TypeTransformVisitor(map)
28062788
ret = defn.accept(visitor)

test-data/unit/check-isinstance.test

+69-21
Original file line numberDiff line numberDiff line change
@@ -1412,9 +1412,41 @@ def f(x: Union[int, A], a: Type[A]) -> None:
14121412

14131413
[builtins fixtures/isinstancelist.pyi]
14141414

1415+
14151416
[case testIssubclass]
14161417
from typing import Type, ClassVar
14171418

1419+
class Goblin:
1420+
aggressive: bool = True
1421+
level: int
1422+
1423+
class GoblinAmbusher(Goblin):
1424+
job: ClassVar[str] = 'Ranger'
1425+
1426+
1427+
def test_issubclass(cls: Type[Goblin]) -> None:
1428+
if issubclass(cls, GoblinAmbusher):
1429+
cls.aggressive
1430+
cls.level
1431+
cls.job
1432+
ga = cls()
1433+
ga.level = 15
1434+
ga.job
1435+
ga.job = "Warrior" # E: Cannot assign to class variable "job" via instance
1436+
else:
1437+
cls.aggressive
1438+
cls.level
1439+
cls.job # E: Type[Goblin] has no attribute "job"
1440+
g = cls()
1441+
g.level = 15
1442+
g.job # E: "Goblin" has no attribute "job"
1443+
1444+
1445+
[builtins fixtures/isinstancelist.pyi]
1446+
1447+
1448+
[case testIssubclassDeepHierarchy]
1449+
from typing import Type, ClassVar
14181450

14191451
class Mob:
14201452
pass
@@ -1426,11 +1458,7 @@ class Goblin(Mob):
14261458
class GoblinAmbusher(Goblin):
14271459
job: ClassVar[str] = 'Ranger'
14281460

1429-
class GoblinDigger(Goblin):
1430-
job: ClassVar[str] = 'Thief'
1431-
1432-
1433-
def test_issubclass1(cls: Type[Mob]) -> None:
1461+
def test_issubclass(cls: Type[Mob]) -> None:
14341462
if issubclass(cls, Goblin):
14351463
cls.aggressive
14361464
cls.level
@@ -1471,6 +1499,27 @@ def test_issubclass1(cls: Type[Mob]) -> None:
14711499
ga.job
14721500
ga.job = "Warrior" # E: Cannot assign to class variable "job" via instance
14731501

1502+
[builtins fixtures/isinstancelist.pyi]
1503+
1504+
1505+
[case testIssubclassTuple]
1506+
from typing import Type, ClassVar
1507+
1508+
class Mob:
1509+
pass
1510+
1511+
class Goblin(Mob):
1512+
aggressive: bool = True
1513+
level: int
1514+
1515+
class GoblinAmbusher(Goblin):
1516+
job: ClassVar[str] = 'Ranger'
1517+
1518+
class GoblinDigger(Goblin):
1519+
job: ClassVar[str] = 'Thief'
1520+
1521+
1522+
def test_issubclass(cls: Type[Mob]) -> None:
14741523
if issubclass(cls, (Goblin, GoblinAmbusher)):
14751524
cls.aggressive
14761525
cls.level
@@ -1512,23 +1561,22 @@ def test_issubclass1(cls: Type[Mob]) -> None:
15121561
g.job
15131562
g.job = "Warrior" # E: Cannot assign to class variable "job" via instance
15141563

1564+
[builtins fixtures/isinstancelist.pyi]
15151565

1516-
def test_issubclass2(cls: Type[Goblin]) -> None:
1517-
if issubclass(cls, GoblinAmbusher):
1518-
cls.aggressive
1519-
cls.level
1520-
cls.job
1521-
ga = cls()
1522-
ga.level = 15
1523-
ga.job
1524-
ga.job = "Warrior" # E: Cannot assign to class variable "job" via instance
1566+
1567+
[case testIssubclassBuiltins]
1568+
from typing import List, Type
1569+
1570+
class MyList(List): pass
1571+
class MyIntList(List[int]): pass
1572+
1573+
def f(cls: Type):
1574+
if issubclass(cls, MyList):
1575+
cls()[0]
15251576
else:
1526-
cls.aggressive
1527-
cls.level
1528-
cls.job # E: Type[Goblin] has no attribute "job"
1529-
g = cls()
1530-
g.level = 15
1531-
g.job # E: "Goblin" has no attribute "job"
1577+
cls()[0] # E:
15321578

1579+
if issubclass(cls, MyIntList):
1580+
cls()[0] + 1
15331581

1534-
[builtins fixtures/isinstancelist.pyi]
1582+
[builtins fixtures/isinstancelist.pyi]

typeshed

Submodule typeshed updated 54 files

0 commit comments

Comments
 (0)