Skip to content

Commit 3cd62e1

Browse files
elazargilevkivskyi
authored andcommitted
Distinct formatting for type objects (#3374)
* format type object as Type[A] and fix tests * erase typeobject
1 parent 3f2668d commit 3cd62e1

13 files changed

+30
-35
lines changed

mypy/messages.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from typing import cast, List, Dict, Any, Sequence, Iterable, Tuple
1010

11+
from mypy.erasetype import erase_type
1112
from mypy.errors import Errors
1213
from mypy.types import (
1314
Type, CallableType, Instance, TypeVarType, TupleType, TypedDictType,
@@ -190,13 +191,7 @@ def format(self, typ: Type, verbosity: int = 0) -> str:
190191
if func.is_type_obj():
191192
# The type of a type object type can be derived from the
192193
# return type (this always works).
193-
itype = cast(Instance, func.items()[0].ret_type)
194-
result = self.format(itype)
195-
if verbosity >= 1:
196-
# In some contexts we want to be explicit about the distinction
197-
# between type X and the type of type object X.
198-
result += ' (type object)'
199-
return result
194+
return self.format(TypeType(erase_type(func.items()[0].ret_type)), verbosity)
200195
elif isinstance(func, CallableType):
201196
return_type = strip_quotes(self.format(func.ret_type))
202197
if func.is_ellipsis_args:

test-data/unit/check-class-namedtuple.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ class MyNamedTuple(NamedTuple):
221221
a: int
222222
b: str
223223

224-
MyNamedTuple.x # E: "MyNamedTuple" has no attribute "x"
224+
MyNamedTuple.x # E: Type[MyNamedTuple] has no attribute "x"
225225

226226
[case testNewNamedTupleEmptyItems]
227227
# flags: --python-version 3.6

test-data/unit/check-classes.test

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ b = A.x # type: B # E: Incompatible types in assignment (expression has type "A"
514514
[case testAccessingUndefinedAttributeViaClass]
515515
import typing
516516
class A: pass
517-
A.x # E: "A" has no attribute "x"
517+
A.x # E: Type[A] has no attribute "x"
518518

519519
[case testAccessingUndefinedAttributeViaClassWithOverloadedInit]
520520
from foo import *
@@ -525,7 +525,7 @@ class A:
525525
def __init__(self): pass
526526
@overload
527527
def __init__(self, x): pass
528-
A.x # E: "A" has no attribute "x"
528+
A.x # E: Type[A] has no attribute "x"
529529

530530
[case testAccessMethodOfClassWithOverloadedInit]
531531
from foo import *
@@ -812,7 +812,7 @@ class C:
812812
cls(1) # E: Too many arguments for "C"
813813
cls.bar()
814814
cls.bar(1) # E: Too many arguments for "bar" of "C"
815-
cls.bozo() # E: "C" has no attribute "bozo"
815+
cls.bozo() # E: Type[C] has no attribute "bozo"
816816
[builtins fixtures/classmethod.pyi]
817817
[out]
818818

@@ -823,7 +823,7 @@ class C:
823823
def foo(cls) -> None: pass
824824
C.foo()
825825
C.foo(1) # E: Too many arguments for "foo" of "C"
826-
C.bozo() # E: "C" has no attribute "bozo"
826+
C.bozo() # E: Type[C] has no attribute "bozo"
827827
[builtins fixtures/classmethod.pyi]
828828

829829
[case testClassMethodCalledOnInstance]
@@ -833,7 +833,7 @@ class C:
833833
def foo(cls) -> None: pass
834834
C().foo()
835835
C().foo(1) # E: Too many arguments for "foo" of "C"
836-
C.bozo() # E: "C" has no attribute "bozo"
836+
C.bozo() # E: Type[C] has no attribute "bozo"
837837
[builtins fixtures/classmethod.pyi]
838838

839839
[case testClassMethodMayCallAbstractMethod]
@@ -1722,7 +1722,7 @@ class C:
17221722
def f(x: type) -> None: pass
17231723
def g(x: int) -> None: pass
17241724
f(C)
1725-
g(C) # E: Argument 1 to "g" has incompatible type "C"; expected "int"
1725+
g(C) # E: Argument 1 to "g" has incompatible type Type[C]; expected "int"
17261726
[builtins fixtures/__new__.pyi]
17271727

17281728
[case testClassWith__new__AndCompatibilityWithType2]
@@ -1733,7 +1733,7 @@ class C:
17331733
def f(x: type) -> None: pass
17341734
def g(x: int) -> None: pass
17351735
f(C)
1736-
g(C) # E: Argument 1 to "g" has incompatible type "C"; expected "int"
1736+
g(C) # E: Argument 1 to "g" has incompatible type Type[C]; expected "int"
17371737
[builtins fixtures/__new__.pyi]
17381738

17391739
[case testGenericClassWith__new__]
@@ -1813,7 +1813,7 @@ class B:
18131813
[case testClassVsInstanceDisambiguation]
18141814
class A: pass
18151815
def f(x: A) -> None: pass
1816-
f(A) # E: Argument 1 to "f" has incompatible type "A" (type object); expected "A"
1816+
f(A) # E: Argument 1 to "f" has incompatible type Type[A]; expected "A"
18171817
[out]
18181818

18191819
-- TODO
@@ -2621,7 +2621,7 @@ int.__eq__(3, 4)
26212621
[builtins fixtures/args.pyi]
26222622
[out]
26232623
main:33: error: Too few arguments for "__eq__" of "int"
2624-
main:33: error: Unsupported operand types for == ("int" and "int")
2624+
main:33: error: Unsupported operand types for == ("int" and Type[int])
26252625

26262626
[case testMroSetAfterError]
26272627
class C(str, str):
@@ -2986,7 +2986,7 @@ class M:
29862986

29872987
class A(metaclass=M): pass # E: Metaclasses not inheriting from 'type' are not supported
29882988

2989-
A.x # E: "A" has no attribute "x"
2989+
A.x # E: Type[A] has no attribute "x"
29902990

29912991
[case testMetaclassTypeReveal]
29922992
from typing import Type
@@ -3085,15 +3085,15 @@ from missing import M
30853085
class A(metaclass=M):
30863086
y = 0
30873087
reveal_type(A.y) # E: Revealed type is 'builtins.int'
3088-
A.x # E: "A" has no attribute "x"
3088+
A.x # E: Type[A] has no attribute "x"
30893089

30903090
[case testAnyMetaclass]
30913091
from typing import Any
30923092
M = None # type: Any
30933093
class A(metaclass=M):
30943094
y = 0
30953095
reveal_type(A.y) # E: Revealed type is 'builtins.int'
3096-
A.x # E: "A" has no attribute "x"
3096+
A.x # E: Type[A] has no attribute "x"
30973097

30983098
[case testInvalidVariableAsMetaclass]
30993099
from typing import Any
@@ -3104,7 +3104,7 @@ class A(metaclass=M): # E: Invalid metaclass 'M'
31043104
class B(metaclass=MM): # E: Invalid metaclass 'MM'
31053105
y = 0
31063106
reveal_type(A.y) # E: Revealed type is 'builtins.int'
3107-
A.x # E: "A" has no attribute "x"
3107+
A.x # E: Type[A] has no attribute "x"
31083108

31093109
[case testAnyAsBaseOfMetaclass]
31103110
from typing import Any, Type

test-data/unit/check-dynamic-typing.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ class A:
485485
def __init__(self, a, b): pass
486486
[out]
487487
main:6: error: Too few arguments for "A"
488-
main:7: error: Incompatible types in assignment (expression has type "A", variable has type Callable[[A], A])
488+
main:7: error: Incompatible types in assignment (expression has type Type[A], variable has type Callable[[A], A])
489489

490490
[case testUsingImplicitTypeObjectWithIs]
491491

test-data/unit/check-enum.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ main:17: error: Enum() with dict literal requires string literals
325325
main:18: error: Unexpected arguments to Enum()
326326
main:19: error: Unexpected arguments to Enum()
327327
main:20: error: Unexpected arguments to Enum()
328-
main:22: error: "W" has no attribute "c"
328+
main:22: error: Type[W] has no attribute "c"
329329

330330
[case testFunctionalEnumFlag]
331331
from enum import Flag, IntFlag

test-data/unit/check-functions.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ class A: pass
254254
t = None # type: type
255255
a = None # type: A
256256

257-
a = A # E: Incompatible types in assignment (expression has type "A" (type object), variable has type "A")
257+
a = A # E: Incompatible types in assignment (expression has type Type[A], variable has type "A")
258258
t = f # E: Incompatible types in assignment (expression has type Callable[[], None], variable has type "type")
259259
t = A
260260

@@ -1479,7 +1479,7 @@ L = Callable[[Arg(name='x', type=int)], int] # ok
14791479
# I have commented out the following test because I don't know how to expect the "defined here" note part of the error.
14801480
# M = Callable[[Arg(gnome='x', type=int)], int] E: Invalid type alias E: Unexpected keyword argument "gnome" for "Arg"
14811481
N = Callable[[Arg(name=None, type=int)], int] # ok
1482-
O = Callable[[List[Arg(int)]], int] # E: Invalid type alias # E: Value of type "int" is not indexable # E: Type expected within [...] # E: The type List[T] is not generic and not indexable
1482+
O = Callable[[List[Arg(int)]], int] # E: Invalid type alias # E: Value of type "int" is not indexable # E: Type expected within [...] # E: The type Type[List[Any]] is not generic and not indexable
14831483
P = Callable[[mypy_extensions.VarArg(int)], int] # ok
14841484
Q = Callable[[Arg(int, type=int)], int] # E: Invalid type alias # E: Value of type "int" is not indexable # E: "Arg" gets multiple values for keyword argument "type"
14851485
R = Callable[[Arg(int, 'x', name='y')], int] # E: Invalid type alias # E: Value of type "int" is not indexable # E: "Arg" gets multiple values for keyword argument "name"

test-data/unit/check-generics.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ A[int, str, int]() # E: Type application has too many types (2 expected)
449449
a = None # type: A
450450
class A: pass
451451
a[A]() # E: Value of type "A" is not indexable
452-
A[A]() # E: The type "A" is not generic and not indexable
452+
A[A]() # E: The type Type[A] is not generic and not indexable
453453
[out]
454454

455455
[case testTypeApplicationArgTypes]
@@ -505,7 +505,7 @@ Alias[int]("a") # E: Argument 1 to "Node" has incompatible type "str"; expected
505505
[out]
506506

507507
[case testTypeApplicationCrash]
508-
type[int] # this was crashing, see #2302 (comment) # E: The type "type" is not generic and not indexable
508+
type[int] # this was crashing, see #2302 (comment) # E: The type Type[type] is not generic and not indexable
509509
[out]
510510

511511

@@ -1505,7 +1505,7 @@ T = TypeVar('T')
15051505
class C(Generic[T]):
15061506
def __init__(self) -> None: pass
15071507
x = C # type: Callable[[], C[int]]
1508-
y = C # type: Callable[[], int] # E: Incompatible types in assignment (expression has type C[T], variable has type Callable[[], int])
1508+
y = C # type: Callable[[], int] # E: Incompatible types in assignment (expression has type Type[C[Any]], variable has type Callable[[], int])
15091509

15101510

15111511
-- Special cases

test-data/unit/check-modules.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,7 @@ class z: pass
915915
[out]
916916
main:2: error: Incompatible import of "x" (imported name has type "str", local name has type "int")
917917
main:2: error: Incompatible import of "y" (imported name has type Callable[[], str], local name has type Callable[[], int])
918-
main:2: error: Incompatible import of "z" (imported name has type "z" (type object), local name has type "z" (type object))
918+
main:2: error: Incompatible import of "z" (imported name has type Type[b.z], local name has type Type[a.z])
919919

920920
-- Misc
921921

test-data/unit/check-namedtuple.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ a = (1,) # E: Incompatible types in assignment (expression has type "Tuple[int]
221221
[case testNamedTupleMissingClassAttribute]
222222
import collections
223223
MyNamedTuple = collections.namedtuple('MyNamedTuple', ['spam', 'eggs'])
224-
MyNamedTuple.x # E: "MyNamedTuple" has no attribute "x"
224+
MyNamedTuple.x # E: Type[MyNamedTuple] has no attribute "x"
225225

226226

227227
[case testNamedTupleEmptyItems]
@@ -420,7 +420,7 @@ class C:
420420
A = NamedTuple('A', [('x', int)])
421421
def g(self):
422422
A = NamedTuple('A', [('y', int)])
423-
C.A # E: "C" has no attribute "A"
423+
C.A # E: Type[C] has no attribute "A"
424424

425425
[case testNamedTupleInFunction]
426426
from typing import NamedTuple

test-data/unit/check-overloading.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ from foo import *
447447
from typing import overload
448448
t, a = None, None # type: (type, A)
449449

450-
a = A # E: Incompatible types in assignment (expression has type "A" (type object), variable has type "A")
450+
a = A # E: Incompatible types in assignment (expression has type Type[A], variable has type "A")
451451
t = A
452452

453453
class A:

test-data/unit/check-python2.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ class A(object):
291291
__metaclass__ = M
292292
y = 0
293293
reveal_type(A.y) # E: Revealed type is 'builtins.int'
294-
A.x # E: "A" has no attribute "x"
294+
A.x # E: Type[A] has no attribute "x"
295295

296296
[case testAnyAsBaseOfMetaclass]
297297
from typing import Any, Type

test-data/unit/check-typeddict.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ class C:
639639
A = TypedDict('A', {'x': int})
640640
def g(self):
641641
A = TypedDict('A', {'y': int})
642-
C.A # E: "C" has no attribute "A"
642+
C.A # E: Type[C] has no attribute "A"
643643
[builtins fixtures/dict.pyi]
644644

645645
[case testTypedDictInFunction]

test-data/unit/pythoneval.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1096,7 +1096,7 @@ class MyDDict(t.DefaultDict[int,T], t.Generic[T]):
10961096
MyDDict(dict)['0']
10971097
MyDDict(dict)[0]
10981098
[out]
1099-
_program.py:6: error: Argument 1 to "defaultdict" has incompatible type List[_T]; expected Callable[[], str]
1099+
_program.py:6: error: Argument 1 to "defaultdict" has incompatible type Type[List[Any]]; expected Callable[[], str]
11001100
_program.py:9: error: Invalid index type "str" for defaultdict[int, str]; expected type "int"
11011101
_program.py:9: error: Incompatible types in assignment (expression has type "int", target has type "str")
11021102
_program.py:19: error: Dict entry 0 has incompatible type "str": List[<nothing>]

0 commit comments

Comments
 (0)