From 657a5443932a469d02a30ccc5312f9f106b46f66 Mon Sep 17 00:00:00 2001 From: elazar Date: Wed, 17 May 2017 01:31:13 +0300 Subject: [PATCH 1/2] format type object as Type[A] and fix tests --- mypy/messages.py | 8 +------ test-data/unit/check-class-namedtuple.test | 2 +- test-data/unit/check-classes.test | 26 +++++++++++----------- test-data/unit/check-dynamic-typing.test | 2 +- test-data/unit/check-enum.test | 2 +- test-data/unit/check-functions.test | 4 ++-- test-data/unit/check-generics.test | 6 ++--- test-data/unit/check-modules.test | 2 +- test-data/unit/check-namedtuple.test | 4 ++-- test-data/unit/check-overloading.test | 2 +- test-data/unit/check-python2.test | 2 +- test-data/unit/check-typeddict.test | 2 +- test-data/unit/pythoneval.test | 2 +- 13 files changed, 29 insertions(+), 35 deletions(-) diff --git a/mypy/messages.py b/mypy/messages.py index f6cadf026788..05e48c58aca8 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -190,13 +190,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(func.items()[0].ret_type), verbosity) elif isinstance(func, CallableType): return_type = strip_quotes(self.format(func.ret_type)) if func.is_ellipsis_args: diff --git a/test-data/unit/check-class-namedtuple.test b/test-data/unit/check-class-namedtuple.test index 533025862167..7a81adb0a672 100644 --- a/test-data/unit/check-class-namedtuple.test +++ b/test-data/unit/check-class-namedtuple.test @@ -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 diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 1dd3353ec903..ae8a3c83166a 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -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 * @@ -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 * @@ -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] @@ -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] @@ -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] @@ -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] @@ -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__] @@ -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 @@ -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): @@ -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 @@ -3085,7 +3085,7 @@ 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 @@ -3093,7 +3093,7 @@ 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 @@ -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 diff --git a/test-data/unit/check-dynamic-typing.test b/test-data/unit/check-dynamic-typing.test index 70d6d32aa475..68a174e3cc81 100644 --- a/test-data/unit/check-dynamic-typing.test +++ b/test-data/unit/check-dynamic-typing.test @@ -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] diff --git a/test-data/unit/check-enum.test b/test-data/unit/check-enum.test index 59cd2f1722ae..011580effb35 100644 --- a/test-data/unit/check-enum.test +++ b/test-data/unit/check-enum.test @@ -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 diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index c978c0e83353..cbd8e3a762bd 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -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 @@ -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[T]] 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" diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test index cbef2f14fec2..f10e16066b63 100644 --- a/test-data/unit/check-generics.test +++ b/test-data/unit/check-generics.test @@ -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] @@ -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] @@ -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[T]], variable has type Callable[[], int]) -- Special cases diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index f78a5be68080..66050601d26f 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -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 diff --git a/test-data/unit/check-namedtuple.test b/test-data/unit/check-namedtuple.test index 87d2ce251b55..81aa3f6957e6 100644 --- a/test-data/unit/check-namedtuple.test +++ b/test-data/unit/check-namedtuple.test @@ -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] @@ -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 diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test index db47a5459bef..69289fae18c1 100644 --- a/test-data/unit/check-overloading.test +++ b/test-data/unit/check-overloading.test @@ -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: diff --git a/test-data/unit/check-python2.test b/test-data/unit/check-python2.test index 0e10d74233e2..b3b899b21560 100644 --- a/test-data/unit/check-python2.test +++ b/test-data/unit/check-python2.test @@ -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 diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test index 10e8dc5679c4..4714ec77f3dc 100644 --- a/test-data/unit/check-typeddict.test +++ b/test-data/unit/check-typeddict.test @@ -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] diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index 3bc0e873aab5..d7ff646519e4 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -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[_T]]; 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[] From 0bc5a3f63ae22814c334c7416bb7806dd0934fd9 Mon Sep 17 00:00:00 2001 From: elazar Date: Thu, 18 May 2017 22:48:49 +0300 Subject: [PATCH 2/2] erase typeobject --- mypy/messages.py | 3 ++- test-data/unit/check-functions.test | 2 +- test-data/unit/check-generics.test | 2 +- test-data/unit/pythoneval.test | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/mypy/messages.py b/mypy/messages.py index 05e48c58aca8..b15562b6268c 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -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, @@ -190,7 +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). - return self.format(TypeType(func.items()[0].ret_type), verbosity) + 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: diff --git a/test-data/unit/check-functions.test b/test-data/unit/check-functions.test index cbd8e3a762bd..ba078cc37c2b 100644 --- a/test-data/unit/check-functions.test +++ b/test-data/unit/check-functions.test @@ -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 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" diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test index f10e16066b63..cdb19b43cf46 100644 --- a/test-data/unit/check-generics.test +++ b/test-data/unit/check-generics.test @@ -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 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 diff --git a/test-data/unit/pythoneval.test b/test-data/unit/pythoneval.test index d7ff646519e4..92b9906f9b53 100644 --- a/test-data/unit/pythoneval.test +++ b/test-data/unit/pythoneval.test @@ -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 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[]