Skip to content

Commit fbd0b91

Browse files
committed
Merge branch 'master' into issubclass
2 parents a260b79 + 73acdb8 commit fbd0b91

21 files changed

+136
-48
lines changed

mypy/checkexpr.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ def analyze_ref_expr(self, e: RefExpr, lvalue: bool = False) -> Type:
151151
result = type_object_type(node, self.named_type)
152152
elif isinstance(node, MypyFile):
153153
# Reference to a module object.
154-
result = self.named_type('builtins.module')
154+
result = self.named_type('types.ModuleType')
155155
elif isinstance(node, Decorator):
156156
result = self.analyze_var_ref(node.var, e)
157157
else:
@@ -178,6 +178,19 @@ def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type:
178178
e.callee.node.typeddict_type is not None:
179179
return self.check_typeddict_call(e.callee.node.typeddict_type,
180180
e.arg_kinds, e.arg_names, e.args, e)
181+
if isinstance(e.callee, NameExpr) and e.callee.name in ('isinstance', 'issubclass'):
182+
for typ in mypy.checker.flatten(e.args[1]):
183+
if isinstance(typ, NameExpr):
184+
try:
185+
node = self.chk.lookup_qualified(typ.name)
186+
except KeyError:
187+
# Undefined names should already be reported in semantic analysis.
188+
node = None
189+
if (isinstance(typ, IndexExpr)
190+
and isinstance(typ.analyzed, (TypeApplication, TypeAliasExpr))
191+
# node.kind == TYPE_ALIAS only for aliases like It = Iterable[int].
192+
or isinstance(typ, NameExpr) and node and node.kind == nodes.TYPE_ALIAS):
193+
self.msg.type_arguments_not_allowed(e)
181194
self.try_infer_partial_type(e)
182195
callee_type = self.accept(e.callee)
183196
if (self.chk.options.disallow_untyped_calls and

mypy/checkmember.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ def analyze_class_attribute_access(itype: Instance,
415415

416416
if isinstance(node.node, MypyFile):
417417
# Reference to a module object.
418-
return builtin_type('builtins.module')
418+
return builtin_type('types.ModuleType')
419419

420420
if is_decorated:
421421
# TODO: Return type of decorated function. This is quick hack to work around #998.

mypy/messages.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,9 @@ def typeddict_item_name_not_found(self,
881881
self.fail('\'{}\' is not a valid item name; expected one of {}'.format(
882882
item_name, format_item_name_list(typ.items.keys())), context)
883883

884+
def type_arguments_not_allowed(self, context: Context) -> None:
885+
self.fail('Parameterized generics cannot be used with class or instance checks', context)
886+
884887

885888
def capitalize(s: str) -> str:
886889
"""Capitalize the first character of a string."""

mypy/semanal.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@
113113
'typing.typevar': 'typing.TypeVar',
114114
}
115115

116+
# Rename objects placed in _importlib_modulespec due to circular imports
117+
module_rename_map = {
118+
'_importlib_modulespec.ModuleType': 'types.ModuleType',
119+
'_importlib_modulespec.ModuleSpec': 'importlib.machinery.ModuleSpec',
120+
'_importlib_modulespec.Loader': 'importlib.abc.Loader'
121+
}
122+
116123
# Hard coded type promotions (shared between all Python versions).
117124
# These add extra ad-hoc edges to the subtyping relation. For example,
118125
# int is considered a subtype of float, even though there is no
@@ -3445,6 +3452,8 @@ def visit_file(self, file: MypyFile, fnam: str, mod_id: str, options: Options) -
34453452

34463453
for d in defs:
34473454
d.accept(self)
3455+
if isinstance(d, ClassDef):
3456+
d.info._fullname = module_rename_map.get(d.info._fullname, d.info._fullname)
34483457

34493458
# Add implicit definition of literals/keywords to builtins, as we
34503459
# cannot define a variable with them explicitly.

mypy/server/deps.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,12 @@ def visit_tuple_type(self, typ: TupleType) -> List[str]:
207207
raise NotImplementedError
208208

209209
def visit_type_type(self, typ: TypeType) -> List[str]:
210-
raise NotImplementedError
210+
# TODO: replace with actual implementation
211+
return []
211212

212213
def visit_type_var(self, typ: TypeVarType) -> List[str]:
213-
raise NotImplementedError
214+
# TODO: replace with actual implementation
215+
return []
214216

215217
def visit_typeddict_type(self, typ: TypedDictType) -> List[str]:
216218
raise NotImplementedError

test-data/unit/check-ignore.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import b # type: ignore
4646
reveal_type(a.foo) # E: Revealed type is 'Any'
4747
reveal_type(b.foo) # E: Revealed type is 'builtins.int'
4848
a.bar()
49-
b.bar() # E: "module" has no attribute "bar"
49+
b.bar() # E: "ModuleType" has no attribute "bar"
5050

5151
[file b.py]
5252
foo = 3
@@ -76,7 +76,7 @@ class B(A):
7676
import m
7777
m.x = object # type: ignore
7878
m.f() # type: ignore
79-
m.y # E: "module" has no attribute "y"
79+
m.y # E: "ModuleType" has no attribute "y"
8080
[file m.py]
8181
[builtins fixtures/module.pyi]
8282

test-data/unit/check-incremental.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ const = 3
300300
[stale mod3]
301301
[builtins fixtures/module.pyi]
302302
[out2]
303-
tmp/mod1.py:3: error: "module" has no attribute "mod4"
303+
tmp/mod1.py:3: error: "ModuleType" has no attribute "mod4"
304304

305305
[case testIncrementalLongBrokenCascade]
306306
import mod1
@@ -335,7 +335,7 @@ const = 3
335335
[stale mod6]
336336
[builtins fixtures/module.pyi]
337337
[out2]
338-
tmp/mod1.py:3: error: "module" has no attribute "mod7"
338+
tmp/mod1.py:3: error: "ModuleType" has no attribute "mod7"
339339

340340
[case testIncrementalNestedBrokenCascade]
341341
import mod1
@@ -361,7 +361,7 @@ const = 3
361361
[stale mod2.mod3]
362362
[builtins fixtures/module.pyi]
363363
[out2]
364-
tmp/mod1.py:3: error: "module" has no attribute "mod4"
364+
tmp/mod1.py:3: error: "ModuleType" has no attribute "mod4"
365365

366366
[case testIncrementalNestedBrokenCascadeWithType1]
367367
import mod1, mod2.mod3.mod5

test-data/unit/check-isinstance.test

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,45 @@ def f(cls: Type[object]) -> None:
15311531

15321532
[builtins fixtures/isinstancelist.pyi]
15331533

1534+
[case testIsinstanceTypeArgs]
1535+
from typing import Iterable, TypeVar
1536+
x = 1
1537+
T = TypeVar('T')
1538+
1539+
isinstance(x, Iterable)
1540+
isinstance(x, Iterable[int]) # E: Parameterized generics cannot be used with class or instance checks
1541+
isinstance(x, Iterable[T]) # E: Parameterized generics cannot be used with class or instance checks
1542+
isinstance(x, (int, Iterable[int])) # E: Parameterized generics cannot be used with class or instance checks
1543+
isinstance(x, (int, (str, Iterable[int]))) # E: Parameterized generics cannot be used with class or instance checks
1544+
1545+
[builtins fixtures/isinstancelist.pyi]
1546+
1547+
[case testIsinstanceTypeArgsAliases]
1548+
from typing import Iterable, TypeVar
1549+
x = 1
1550+
T = TypeVar('T')
1551+
It = Iterable
1552+
It2 = Iterable[T]
1553+
1554+
isinstance(x, It[int]) # E: Parameterized generics cannot be used with class or instance checks
1555+
isinstance(x, It)
1556+
isinstance(x, It2[int]) # E: Parameterized generics cannot be used with class or instance checks
1557+
isinstance(x, It2) # E: Parameterized generics cannot be used with class or instance checks
1558+
1559+
[builtins fixtures/isinstance.pyi]
1560+
1561+
1562+
[case testIssubclassTypeArgs]
1563+
from typing import Iterable, TypeVar
1564+
x = int
1565+
T = TypeVar('T')
1566+
issubclass(x, Iterable)
1567+
issubclass(x, Iterable[int]) # E: Parameterized generics cannot be used with class or instance checks
1568+
issubclass(x, Iterable[T]) # E: Parameterized generics cannot be used with class or instance checks
1569+
issubclass(x, (int, Iterable[int])) # E: Parameterized generics cannot be used with class or instance checks
1570+
1571+
[builtins fixtures/isinstance.pyi]
1572+
15341573
[case testIsinstanceAndNarrowTypeVariable]
15351574
from typing import TypeVar
15361575

test-data/unit/check-modules.test

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,17 +153,18 @@ def f(c:str) -> None: pass
153153
[case testInvalidOperationsOnModules]
154154
import m
155155
import typing
156+
156157
class A: pass
157-
m() # E: "module" not callable
158-
a = m # type: A # E: Incompatible types in assignment (expression has type "module", variable has type "A")
159-
m + None # E: Unsupported left operand type for + ("module")
158+
m() # E: "ModuleType" not callable
159+
a = m # type: A # E: Incompatible types in assignment (expression has type "ModuleType", variable has type "A")
160+
m + None # E: Unsupported left operand type for + ("ModuleType")
160161
[file m.py]
161162
[builtins fixtures/module.pyi]
162163

163164
[case testNameDefinedInDifferentModule]
164165
import m, n
165166
import typing
166-
m.x # E: "module" has no attribute "x"
167+
m.x # E: "ModuleType" has no attribute "x"
167168
[file m.py]
168169
y = object()
169170
[file n.py]
@@ -329,7 +330,7 @@ import nonexistent
329330
[out]
330331
tmp/x.py:1: error: Cannot find module named 'nonexistent'
331332
tmp/x.py:1: note: (Perhaps setting MYPYPATH or using the "--ignore-missing-imports" flag would help)
332-
main:3: error: "module" has no attribute "z"
333+
main:3: error: "ModuleType" has no attribute "z"
333334

334335
[case testUnknownModuleImportedWithinFunction]
335336
def f():
@@ -647,7 +648,7 @@ def f(x: str) -> None: pass
647648
if object():
648649
import m
649650
else:
650-
m = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "module")
651+
m = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "ModuleType")
651652
[file m.py]
652653
[builtins fixtures/module.pyi]
653654
[out]
@@ -751,7 +752,7 @@ value = 3.2
751752
[case testSubmoduleImportFromDoesNotAddParents]
752753
from a import b
753754
reveal_type(b.value) # E: Revealed type is 'builtins.str'
754-
b.c.value # E: "module" has no attribute "c"
755+
b.c.value # E: "ModuleType" has no attribute "c"
755756
a.value # E: Name 'a' is not defined
756757

757758
[file a/__init__.py]
@@ -852,7 +853,7 @@ bar = parent.unrelated.ShouldNotLoad()
852853
[builtins fixtures/module.pyi]
853854
[out]
854855
tmp/parent/child.py:8: error: Revealed type is 'parent.common.SomeClass'
855-
tmp/parent/child.py:9: error: "module" has no attribute "unrelated"
856+
tmp/parent/child.py:9: error: "ModuleType" has no attribute "unrelated"
856857

857858
[case testSubmoduleMixingImportFromAndImport2]
858859
import parent.child
@@ -1406,3 +1407,12 @@ reveal_type(cb) # E: Revealed type is 'def (*Any, **Any) -> Any'
14061407
from typing import Callable, Any
14071408
AnyCallable = Callable[..., Any]
14081409
[out]
1410+
1411+
[case testRevealType]
1412+
import types
1413+
def f() -> types.ModuleType:
1414+
return types
1415+
reveal_type(f()) # E: Revealed type is 'types.ModuleType'
1416+
reveal_type(types) # E: Revealed type is 'types.ModuleType'
1417+
1418+
[builtins fixtures/module.pyi]

test-data/unit/cmdline.test

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,8 @@ x += '' # Error reported here
365365
a.py:2: error: Unsupported operand types for + ("int" and "str")
366366
main.py:3: error: Unsupported operand types for + ("int" and "str")
367367
main.py:6: error: Unsupported operand types for + ("int" and "str")
368-
main.py:7: error: "module" has no attribute "y"
369-
main.py:8: error: Unsupported operand types for + ("module" and "int")
368+
main.py:7: error: "ModuleType" has no attribute "y"
369+
main.py:8: error: Unsupported operand types for + ("ModuleType" and "int")
370370

371371
[case testConfigFollowImportsSilent]
372372
# cmd: mypy main.py
@@ -386,8 +386,8 @@ x += '' # No error reported
386386
[out]
387387
main.py:2: error: Unsupported operand types for + ("int" and "str")
388388
main.py:4: error: Unsupported operand types for + ("int" and "str")
389-
main.py:5: error: "module" has no attribute "y"
390-
main.py:6: error: Unsupported operand types for + ("module" and "int")
389+
main.py:5: error: "ModuleType" has no attribute "y"
390+
main.py:6: error: Unsupported operand types for + ("ModuleType" and "int")
391391

392392
[case testConfigFollowImportsSkip]
393393
# cmd: mypy main.py

test-data/unit/fine-grained.test

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def g(x: str) -> None: pass
6868
[builtins fixtures/fine_grained.pyi]
6969
[out]
7070
==
71-
main:3: error: "module" has no attribute "f"
71+
main:3: error: "ModuleType" has no attribute "f"
7272

7373
[case testTopLevelMissingModuleAttribute]
7474
import m
@@ -81,7 +81,7 @@ def g(x: int) -> None: pass
8181
[builtins fixtures/fine_grained.pyi]
8282
[out]
8383
==
84-
main:2: error: "module" has no attribute "f"
84+
main:2: error: "ModuleType" has no attribute "f"
8585

8686
[case testClassChangedIntoFunction]
8787
import m
@@ -241,7 +241,7 @@ class A: pass
241241
[builtins fixtures/fine_grained.pyi]
242242
[out]
243243
==
244-
main:3: error: "module" has no attribute "A"
244+
main:3: error: "ModuleType" has no attribute "A"
245245
==
246246

247247
[case testContinueToReportTypeCheckError]
@@ -281,10 +281,10 @@ class A: pass
281281
[builtins fixtures/fine_grained.pyi]
282282
[out]
283283
==
284-
main:3: error: "module" has no attribute "A"
285-
main:5: error: "module" has no attribute "B"
284+
main:3: error: "ModuleType" has no attribute "A"
285+
main:5: error: "ModuleType" has no attribute "B"
286286
==
287-
main:5: error: "module" has no attribute "B"
287+
main:5: error: "ModuleType" has no attribute "B"
288288

289289
[case testContinueToReportErrorAtTopLevel]
290290
import n
@@ -348,9 +348,9 @@ def g() -> None: pass
348348
[builtins fixtures/fine_grained.pyi]
349349
[out]
350350
main:3: error: Too few arguments for "f"
351-
main:5: error: "module" has no attribute "g"
351+
main:5: error: "ModuleType" has no attribute "g"
352352
==
353-
main:5: error: "module" has no attribute "g"
353+
main:5: error: "ModuleType" has no attribute "g"
354354
==
355355

356356
[case testKeepReportingErrorIfNoChanges]
@@ -361,9 +361,9 @@ def h() -> None:
361361
[file m.py.2]
362362
[builtins fixtures/fine_grained.pyi]
363363
[out]
364-
main:3: error: "module" has no attribute "g"
364+
main:3: error: "ModuleType" has no attribute "g"
365365
==
366-
main:3: error: "module" has no attribute "g"
366+
main:3: error: "ModuleType" has no attribute "g"
367367

368368
[case testFixErrorAndReintroduce]
369369
import m
@@ -375,10 +375,10 @@ def g() -> None: pass
375375
[file m.py.3]
376376
[builtins fixtures/fine_grained.pyi]
377377
[out]
378-
main:3: error: "module" has no attribute "g"
378+
main:3: error: "ModuleType" has no attribute "g"
379379
==
380380
==
381-
main:3: error: "module" has no attribute "g"
381+
main:3: error: "ModuleType" has no attribute "g"
382382

383383
[case testAddBaseClassMethodCausingInvalidOverride]
384384
import m

test-data/unit/fixtures/args.pyi

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,3 @@ class int:
2626
class str: pass
2727
class bool: pass
2828
class function: pass
29-
class module: pass
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
import typing
2+
3+
T = typing.TypeVar('T')
4+
class list(typing.Generic[T], typing.Sequence[T]): pass
5+
26
class object:
37
def __init__(self): pass
48
class type: pass
59
class function: pass
610
class int: pass
711
class str: pass
812
class dict: pass
9-
class list: pass
1013
class set: pass
1114
class tuple: pass
1215
class BaseException: pass
1316
class StopIteration(BaseException): pass
1417
class StopAsyncIteration(BaseException): pass
1518
def iter(obj: typing.Any) -> typing.Any: pass
1619
def next(obj: typing.Any) -> typing.Any: pass
20+
class ellipsis: ...

test-data/unit/fixtures/fine_grained.pyi

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
# TODO: Migrate to regular stubs once fine-grained incremental is robust
44
# enough to handle them.
55

6+
import types
7+
68
class Any: pass
79

810
class object:
@@ -21,4 +23,4 @@ class bytes: pass
2123
class tuple: pass
2224
class function: pass
2325
class ellipsis: pass
24-
class module: pass
26+
class list: pass

test-data/unit/fixtures/isinstance.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class tuple(Generic[T]): pass
1313
class function: pass
1414

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

1718
class int:
1819
def __add__(self, other: 'int') -> 'int': pass

0 commit comments

Comments
 (0)