Skip to content

Distinct formatting for type objects #3374

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions mypy/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

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

from mypy.erasetype import erase_type
from mypy.errors import Errors
from mypy.types import (
Type, CallableType, Instance, TypeVarType, TupleType, TypedDictType,
Expand Down Expand Up @@ -190,13 +191,7 @@ def format(self, typ: Type, verbosity: int = 0) -> str:
if func.is_type_obj():
# The type of a type object type can be derived from the
# return type (this always works).
itype = cast(Instance, func.items()[0].ret_type)
result = self.format(itype)
if verbosity >= 1:
# In some contexts we want to be explicit about the distinction
# between type X and the type of type object X.
result += ' (type object)'
return result
return self.format(TypeType(erase_type(func.items()[0].ret_type)), verbosity)
elif isinstance(func, CallableType):
return_type = strip_quotes(self.format(func.ret_type))
if func.is_ellipsis_args:
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-class-namedtuple.test
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class MyNamedTuple(NamedTuple):
a: int
b: str

MyNamedTuple.x # E: "MyNamedTuple" has no attribute "x"
MyNamedTuple.x # E: Type[MyNamedTuple] has no attribute "x"

[case testNewNamedTupleEmptyItems]
# flags: --python-version 3.6
Expand Down
26 changes: 13 additions & 13 deletions test-data/unit/check-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ b = A.x # type: B # E: Incompatible types in assignment (expression has type "A"
[case testAccessingUndefinedAttributeViaClass]
import typing
class A: pass
A.x # E: "A" has no attribute "x"
A.x # E: Type[A] has no attribute "x"

[case testAccessingUndefinedAttributeViaClassWithOverloadedInit]
from foo import *
Expand All @@ -525,7 +525,7 @@ class A:
def __init__(self): pass
@overload
def __init__(self, x): pass
A.x # E: "A" has no attribute "x"
A.x # E: Type[A] has no attribute "x"

[case testAccessMethodOfClassWithOverloadedInit]
from foo import *
Expand Down Expand Up @@ -812,7 +812,7 @@ class C:
cls(1) # E: Too many arguments for "C"
cls.bar()
cls.bar(1) # E: Too many arguments for "bar" of "C"
cls.bozo() # E: "C" has no attribute "bozo"
cls.bozo() # E: Type[C] has no attribute "bozo"
[builtins fixtures/classmethod.pyi]
[out]

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

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

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

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

[case testGenericClassWith__new__]
Expand Down Expand Up @@ -1813,7 +1813,7 @@ class B:
[case testClassVsInstanceDisambiguation]
class A: pass
def f(x: A) -> None: pass
f(A) # E: Argument 1 to "f" has incompatible type "A" (type object); expected "A"
f(A) # E: Argument 1 to "f" has incompatible type Type[A]; expected "A"
[out]

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

[case testMroSetAfterError]
class C(str, str):
Expand Down Expand Up @@ -2986,7 +2986,7 @@ class M:

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

A.x # E: "A" has no attribute "x"
A.x # E: Type[A] has no attribute "x"

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

[case testAnyMetaclass]
from typing import Any
M = None # type: Any
class A(metaclass=M):
y = 0
reveal_type(A.y) # E: Revealed type is 'builtins.int'
A.x # E: "A" has no attribute "x"
A.x # E: Type[A] has no attribute "x"

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

[case testAnyAsBaseOfMetaclass]
from typing import Any, Type
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-dynamic-typing.test
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ class A:
def __init__(self, a, b): pass
[out]
main:6: error: Too few arguments for "A"
main:7: error: Incompatible types in assignment (expression has type "A", variable has type Callable[[A], A])
main:7: error: Incompatible types in assignment (expression has type Type[A], variable has type Callable[[A], A])

[case testUsingImplicitTypeObjectWithIs]

Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-enum.test
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ main:17: error: Enum() with dict literal requires string literals
main:18: error: Unexpected arguments to Enum()
main:19: error: Unexpected arguments to Enum()
main:20: error: Unexpected arguments to Enum()
main:22: error: "W" has no attribute "c"
main:22: error: Type[W] has no attribute "c"

[case testFunctionalEnumFlag]
from enum import Flag, IntFlag
Expand Down
4 changes: 2 additions & 2 deletions test-data/unit/check-functions.test
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ class A: pass
t = None # type: type
a = None # type: A

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

Expand Down Expand Up @@ -1479,7 +1479,7 @@ L = Callable[[Arg(name='x', type=int)], int] # ok
# I have commented out the following test because I don't know how to expect the "defined here" note part of the error.
# M = Callable[[Arg(gnome='x', type=int)], int] E: Invalid type alias E: Unexpected keyword argument "gnome" for "Arg"
N = Callable[[Arg(name=None, type=int)], int] # ok
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
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
P = Callable[[mypy_extensions.VarArg(int)], int] # ok
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"
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"
Expand Down
6 changes: 3 additions & 3 deletions test-data/unit/check-generics.test
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ A[int, str, int]() # E: Type application has too many types (2 expected)
a = None # type: A
class A: pass
a[A]() # E: Value of type "A" is not indexable
A[A]() # E: The type "A" is not generic and not indexable
A[A]() # E: The type Type[A] is not generic and not indexable
[out]

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

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


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


-- Special cases
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-modules.test
Original file line number Diff line number Diff line change
Expand Up @@ -915,7 +915,7 @@ class z: pass
[out]
main:2: error: Incompatible import of "x" (imported name has type "str", local name has type "int")
main:2: error: Incompatible import of "y" (imported name has type Callable[[], str], local name has type Callable[[], int])
main:2: error: Incompatible import of "z" (imported name has type "z" (type object), local name has type "z" (type object))
main:2: error: Incompatible import of "z" (imported name has type Type[b.z], local name has type Type[a.z])

-- Misc

Expand Down
4 changes: 2 additions & 2 deletions test-data/unit/check-namedtuple.test
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ a = (1,) # E: Incompatible types in assignment (expression has type "Tuple[int]
[case testNamedTupleMissingClassAttribute]
import collections
MyNamedTuple = collections.namedtuple('MyNamedTuple', ['spam', 'eggs'])
MyNamedTuple.x # E: "MyNamedTuple" has no attribute "x"
MyNamedTuple.x # E: Type[MyNamedTuple] has no attribute "x"


[case testNamedTupleEmptyItems]
Expand Down Expand Up @@ -420,7 +420,7 @@ class C:
A = NamedTuple('A', [('x', int)])
def g(self):
A = NamedTuple('A', [('y', int)])
C.A # E: "C" has no attribute "A"
C.A # E: Type[C] has no attribute "A"

[case testNamedTupleInFunction]
from typing import NamedTuple
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-overloading.test
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ from foo import *
from typing import overload
t, a = None, None # type: (type, A)

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

class A:
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-python2.test
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ class A(object):
__metaclass__ = M
y = 0
reveal_type(A.y) # E: Revealed type is 'builtins.int'
A.x # E: "A" has no attribute "x"
A.x # E: Type[A] has no attribute "x"

[case testAnyAsBaseOfMetaclass]
from typing import Any, Type
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/check-typeddict.test
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ class C:
A = TypedDict('A', {'x': int})
def g(self):
A = TypedDict('A', {'y': int})
C.A # E: "C" has no attribute "A"
C.A # E: Type[C] has no attribute "A"
[builtins fixtures/dict.pyi]

[case testTypedDictInFunction]
Expand Down
2 changes: 1 addition & 1 deletion test-data/unit/pythoneval.test
Original file line number Diff line number Diff line change
Expand Up @@ -1096,7 +1096,7 @@ class MyDDict(t.DefaultDict[int,T], t.Generic[T]):
MyDDict(dict)['0']
MyDDict(dict)[0]
[out]
_program.py:6: error: Argument 1 to "defaultdict" has incompatible type List[_T]; expected Callable[[], str]
_program.py:6: error: Argument 1 to "defaultdict" has incompatible type Type[List[Any]]; expected Callable[[], str]
_program.py:9: error: Invalid index type "str" for defaultdict[int, str]; expected type "int"
_program.py:9: error: Incompatible types in assignment (expression has type "int", target has type "str")
_program.py:19: error: Dict entry 0 has incompatible type "str": List[<nothing>]
Expand Down