From 595a414695c969a37ed63a23672fa34eaa576e01 Mon Sep 17 00:00:00 2001 From: Jingchen Ye <97littleleaf11@gmail.com> Date: Thu, 11 Nov 2021 18:16:22 +0800 Subject: [PATCH 1/4] Use format_type --- mypy/message_registry.py | 3 ++ mypy/semanal_typeargs.py | 20 ++++--- test-data/unit/check-bound.test | 6 +-- test-data/unit/check-classes.test | 4 +- test-data/unit/check-errorcodes.test | 2 +- test-data/unit/check-namedtuple.test | 2 +- test-data/unit/check-newsemanal.test | 78 ++++++++++++++-------------- test-data/unit/check-typeddict.test | 2 +- test-data/unit/fine-grained.test | 2 +- 9 files changed, 63 insertions(+), 56 deletions(-) diff --git a/mypy/message_registry.py b/mypy/message_registry.py index de439b172e0c..b6005744b25f 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -149,6 +149,9 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": # TypeVar INCOMPATIBLE_TYPEVAR_VALUE: Final = 'Value of type variable "{}" of {} cannot be {}' CANNOT_USE_TYPEVAR_AS_EXPRESSION: Final = 'Type variable "{}.{}" cannot be used as an expression' +INVALID_TYPEVAR_AS_TYPEARG: Final = 'Type variable "{}" not valid as type argument value for "{}"' +INVALID_TYPEVAR_ARG_BOUND: Final = 'Type argument {} of "{}" must be a subtype of {}' +INVALID_TYPEVAR_ARG_VALUE: Final = 'Invalid type argument value for "{}"' # Super TOO_MANY_ARGS_FOR_SUPER: Final = 'Too many arguments for "super"' diff --git a/mypy/semanal_typeargs.py b/mypy/semanal_typeargs.py index 58edeef98407..d86434e62a19 100644 --- a/mypy/semanal_typeargs.py +++ b/mypy/semanal_typeargs.py @@ -19,6 +19,7 @@ from mypy.options import Options from mypy.errorcodes import ErrorCode from mypy import message_registry, errorcodes as codes +from mypy.messages import format_type class TypeArgumentAnalyzer(MixedTraverserVisitor): @@ -73,17 +74,19 @@ def visit_instance(self, t: Instance) -> None: if isinstance(arg, TypeVarType): arg_values = arg.values if not arg_values: - self.fail('Type variable "{}" not valid as type ' - 'argument value for "{}"'.format( - arg.name, info.name), t, code=codes.TYPE_VAR) + self.fail( + message_registry.INVALID_TYPEVAR_AS_TYPEARG.format( + arg.name, info.name), + t, code=codes.TYPE_VAR) continue else: arg_values = [arg] self.check_type_var_values(info, arg_values, tvar.name, tvar.values, i + 1, t) if not is_subtype(arg, tvar.upper_bound): - self.fail('Type argument "{}" of "{}" must be ' - 'a subtype of "{}"'.format( - arg, info.name, tvar.upper_bound), t, code=codes.TYPE_VAR) + self.fail( + message_registry.INVALID_TYPEVAR_ARG_BOUND.format( + format_type(arg), info.name, format_type(tvar.upper_bound)), + t, code=codes.TYPE_VAR) super().visit_instance(t) def check_type_var_values(self, type: TypeInfo, actuals: List[Type], arg_name: str, @@ -93,8 +96,9 @@ def check_type_var_values(self, type: TypeInfo, actuals: List[Type], arg_name: s not any(is_same_type(actual, value) for value in valids)): if len(actuals) > 1 or not isinstance(actual, Instance): - self.fail('Invalid type argument value for "{}"'.format( - type.name), context, code=codes.TYPE_VAR) + self.fail( + message_registry.INVALID_TYPEVAR_ARG_VALUE.format(type.name), + context, code=codes.TYPE_VAR) else: class_name = '"{}"'.format(type.name) actual_type_name = '"{}"'.format(actual.type.name) diff --git a/test-data/unit/check-bound.test b/test-data/unit/check-bound.test index a137132ebc67..bf13ef874579 100644 --- a/test-data/unit/check-bound.test +++ b/test-data/unit/check-bound.test @@ -39,7 +39,7 @@ class G(Generic[T]): v = None # type: G[A] w = None # type: G[B] -x = None # type: G[str] # E: Type argument "builtins.str" of "G" must be a subtype of "__main__.A" +x = None # type: G[str] # E: Type argument "str" of "G" must be a subtype of "A" y = G('a') # E: Value of type variable "T" of "G" cannot be "str" z = G(A()) z = G(B()) @@ -93,9 +93,9 @@ TA = TypeVar('TA', bound=A) class C(Generic[TA]): pass class D0(C[TA], Generic[TA]): pass -class D1(C[T], Generic[T]): pass # E: Type argument "T`1" of "C" must be a subtype of "__main__.A" +class D1(C[T], Generic[T]): pass # E: Type argument "T" of "C" must be a subtype of "A" class D2(C[A]): pass -class D3(C[str]): pass # E: Type argument "builtins.str" of "C" must be a subtype of "__main__.A" +class D3(C[str]): pass # E: Type argument "str" of "C" must be a subtype of "A" -- Using information from upper bounds diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 070fdaff27c0..55649f3c6032 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -5500,8 +5500,8 @@ A = G x: A[B[int]] # E B = G [out] -main:8:4: error: Type argument "__main__.G[builtins.int]" of "G" must be a subtype of "builtins.str" -main:8:6: error: Type argument "builtins.int" of "G" must be a subtype of "builtins.str" +main:8:4: error: Type argument "G[int]" of "G" must be a subtype of "str" +main:8:6: error: Type argument "int" of "G" must be a subtype of "str" [case testExtremeForwardReferencing] from typing import TypeVar, Generic diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 96c7d8d65dc6..e7973924bf39 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -440,7 +440,7 @@ class D(Generic[S]): pass class E(Generic[S, T]): pass x: C[object] # E: Value of type variable "T" of "C" cannot be "object" [type-var] -y: D[int] # E: Type argument "builtins.int" of "D" must be a subtype of "builtins.str" [type-var] +y: D[int] # E: Type argument "int" of "D" must be a subtype of "str" [type-var] z: D[int, int] # E: "D" expects 1 type argument, but 2 given [type-arg] def h(a: TT, s: S) -> None: diff --git a/test-data/unit/check-namedtuple.test b/test-data/unit/check-namedtuple.test index 4d21794c74d2..1e531109d5ca 100644 --- a/test-data/unit/check-namedtuple.test +++ b/test-data/unit/check-namedtuple.test @@ -576,7 +576,7 @@ T = TypeVar('T', bound='M') class G(Generic[T]): x: T -yb: G[int] # E: Type argument "builtins.int" of "G" must be a subtype of "Tuple[builtins.int, fallback=__main__.M]" +yb: G[int] # E: Type argument "int" of "G" must be a subtype of "M" yg: G[M] reveal_type(G[M]().x.x) # N: Revealed type is "builtins.int" reveal_type(G[M]().x[0]) # N: Revealed type is "builtins.int" diff --git a/test-data/unit/check-newsemanal.test b/test-data/unit/check-newsemanal.test index 285d2aa1a3e0..4e0729d355d5 100644 --- a/test-data/unit/check-newsemanal.test +++ b/test-data/unit/check-newsemanal.test @@ -763,7 +763,7 @@ class D(C[TY], Generic[TY]): pass class Y(Defer): pass class Defer: ... -x: D[int] # E: Type argument "builtins.int" of "D" must be a subtype of "__main__.Y" +x: D[int] # E: Type argument "int" of "D" must be a subtype of "Y" y: D[Y] [case testNewAnalyzerTypeVarForwardReferenceErrors] @@ -1639,7 +1639,7 @@ class C(Generic[T]): pass class D(B): pass -x: C[D] # E: Type argument "__main__.D" of "C" must be a subtype of "__main__.E" +x: C[D] # E: Type argument "D" of "C" must be a subtype of "E" y: C[F] class B: pass @@ -1678,14 +1678,14 @@ class A(C[str]): # E [out] main:2: note: In module imported here: tmp/a.py: note: In function "f": -tmp/a.py:6: error: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" -tmp/a.py:7: error: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +tmp/a.py:6: error: Type argument "str" of "C" must be a subtype of "int" +tmp/a.py:7: error: Type argument "str" of "C" must be a subtype of "int" tmp/a.py: note: In class "A": -tmp/a.py:8: error: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" -tmp/a.py:9: error: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +tmp/a.py:8: error: Type argument "str" of "C" must be a subtype of "int" +tmp/a.py:9: error: Type argument "str" of "C" must be a subtype of "int" tmp/a.py: note: In member "g" of class "A": -tmp/a.py:10: error: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" -tmp/a.py:11: error: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +tmp/a.py:10: error: Type argument "str" of "C" must be a subtype of "int" +tmp/a.py:11: error: Type argument "str" of "C" must be a subtype of "int" [case testNewAnalyzerTypeArgBoundCheckDifferentNodes] from typing import TypeVar, Generic, NamedTuple, NewType, Union, Any, cast, overload @@ -1695,45 +1695,45 @@ T = TypeVar('T', bound=int) class C(Generic[T]): pass class C2(Generic[T]): pass -A = C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" \ +A = C[str] # E: Type argument "str" of "C" must be a subtype of "int" \ # E: Value of type variable "T" of "C" cannot be "str" -B = Union[C[str], int] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" -S = TypeVar('S', bound=C[str]) # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" -U = TypeVar('U', C[str], str) # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +B = Union[C[str], int] # E: Type argument "str" of "C" must be a subtype of "int" +S = TypeVar('S', bound=C[str]) # E: Type argument "str" of "C" must be a subtype of "int" +U = TypeVar('U', C[str], str) # E: Type argument "str" of "C" must be a subtype of "int" N = NamedTuple('N', [ - ('x', C[str])]) # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" + ('x', C[str])]) # E: Type argument "str" of "C" must be a subtype of "int" class N2(NamedTuple): - x: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" + x: C[str] # E: Type argument "str" of "C" must be a subtype of "int" class TD(TypedDict): - x: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" + x: C[str] # E: Type argument "str" of "C" must be a subtype of "int" class TD2(TD): - y: C2[str] # E: Type argument "builtins.str" of "C2" must be a subtype of "builtins.int" + y: C2[str] # E: Type argument "str" of "C2" must be a subtype of "int" NT = NewType('NT', - C[str]) # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" + C[str]) # E: Type argument "str" of "C" must be a subtype of "int" class D( - C[str]): # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" + C[str]): # E: Type argument "str" of "C" must be a subtype of "int" pass -TD3 = TypedDict('TD3', {'x': C[str]}) # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +TD3 = TypedDict('TD3', {'x': C[str]}) # E: Type argument "str" of "C" must be a subtype of "int" a: Any -for i in a: # type: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +for i in a: # type: C[str] # E: Type argument "str" of "C" must be a subtype of "int" pass -with a as w: # type: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +with a as w: # type: C[str] # E: Type argument "str" of "C" must be a subtype of "int" pass -cast(C[str], a) # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +cast(C[str], a) # E: Type argument "str" of "C" must be a subtype of "int" C[str]() # E: Value of type variable "T" of "C" cannot be "str" def f(s: S, y: U) -> None: pass # No error here @overload -def g(x: C[str]) -> int: ... # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +def g(x: C[str]) -> int: ... # E: Type argument "str" of "C" must be a subtype of "int" @overload def g(x: int) -> int: ... -def g(x: Union[C[str], int]) -> int: # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" - y: C[object] # E: Type argument "builtins.object" of "C" must be a subtype of "builtins.int" +def g(x: Union[C[str], int]) -> int: # E: Type argument "str" of "C" must be a subtype of "int" + y: C[object] # E: Type argument "object" of "C" must be a subtype of "int" return 0 [builtins fixtures/tuple.pyi] @@ -1745,7 +1745,7 @@ import a from typing import TypeVar, Generic x: C[None] -y: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +y: C[str] # E: Type argument "str" of "C" must be a subtype of "int" z: C[int] T = TypeVar('T', bound=int) @@ -1755,8 +1755,8 @@ class C(Generic[T]): [file a.py] from b import C -x: C[None] # E: Type argument "None" of "C" must be a subtype of "builtins.int" -y: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +x: C[None] # E: Type argument "None" of "C" must be a subtype of "int" +y: C[str] # E: Type argument "str" of "C" must be a subtype of "int" z: C[int] [file mypy.ini] @@ -1774,7 +1774,7 @@ import a from typing import TypeVar, Generic x: C[None] -y: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +y: C[str] # E: Type argument "str" of "C" must be a subtype of "int" z: C[int] T = TypeVar('T', bound=int) @@ -1784,8 +1784,8 @@ class C(Generic[T]): [file a.py] from b import C -x: C[None] # E: Type argument "None" of "C" must be a subtype of "builtins.int" -y: C[str] # E: Type argument "builtins.str" of "C" must be a subtype of "builtins.int" +x: C[None] # E: Type argument "None" of "C" must be a subtype of "int" +y: C[str] # E: Type argument "str" of "C" must be a subtype of "int" z: C[int] [file pyproject.toml] @@ -1993,16 +1993,16 @@ S = TypeVar('S', bound=Tuple[G[A], ...]) class GG(Generic[S]): pass g: GG[Tuple[G[B], G[C]]] \ - # E: Type argument "Tuple[__main__.G[__main__.B], __main__.G[__main__.C]]" of "GG" must be a subtype of "builtins.tuple[__main__.G[__main__.A]]" \ - # E: Type argument "__main__.B" of "G" must be a subtype of "__main__.A" \ - # E: Type argument "__main__.C" of "G" must be a subtype of "__main__.A" + # E: Type argument "Tuple[G[B], G[C]]" of "GG" must be a subtype of "Tuple[G[A], ...]" \ + # E: Type argument "B" of "G" must be a subtype of "A" \ + # E: Type argument "C" of "G" must be a subtype of "A" T = TypeVar('T', bound=A, covariant=True) class G(Generic[T]): pass -t: Tuple[G[B], G[C]] # E: Type argument "__main__.B" of "G" must be a subtype of "__main__.A" \ - # E: Type argument "__main__.C" of "G" must be a subtype of "__main__.A" +t: Tuple[G[B], G[C]] # E: Type argument "B" of "G" must be a subtype of "A" \ + # E: Type argument "C" of "G" must be a subtype of "A" reveal_type(t.__iter__) # N: Revealed type is "def () -> typing.Iterator[builtins.object*]" [builtins fixtures/tuple.pyi] @@ -2201,7 +2201,7 @@ class B(Generic[T]): x: T class C: ... -x: B[int] # E: Type argument "builtins.int" of "B" must be a subtype of "__main__.B[Any]" +x: B[int] # E: Type argument "int" of "B" must be a subtype of "B[Any]" y: B[B[Any]] reveal_type(y.x) # N: Revealed type is "__main__.B*[Any]" @@ -2226,7 +2226,7 @@ x: B[int] y: B[B[Any]] reveal_type(y.x) [out] -tmp/b.py:8: error: Type argument "builtins.int" of "B" must be a subtype of "b.B[Any]" +tmp/b.py:8: error: Type argument "int" of "B" must be a subtype of "B[Any]" tmp/b.py:10: note: Revealed type is "b.B*[Any]" tmp/a.py:5: error: Cannot redefine "T" as a type variable tmp/a.py:5: error: Invalid assignment target @@ -2255,7 +2255,7 @@ x: B[int] y: B[B[Any]] reveal_type(y.x) [out] -tmp/b.py:9: error: Type argument "builtins.int" of "B" must be a subtype of "b.B[Any]" +tmp/b.py:9: error: Type argument "int" of "B" must be a subtype of "B[Any]" tmp/b.py:11: note: Revealed type is "b.B*[Any]" tmp/a.py:5: error: Cannot redefine "T" as a type variable tmp/a.py:5: error: Invalid assignment target diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test index 5fa5514796a0..b8662752e403 100644 --- a/test-data/unit/check-typeddict.test +++ b/test-data/unit/check-typeddict.test @@ -1468,7 +1468,7 @@ T = TypeVar('T', bound='M') class G(Generic[T]): x: T -yb: G[int] # E: Type argument "builtins.int" of "G" must be a subtype of "TypedDict('__main__.M', {'x': builtins.int})" +yb: G[int] # E: Type argument "int" of "G" must be a subtype of "M" yg: G[M] z: int = G[M]().x['x'] diff --git a/test-data/unit/fine-grained.test b/test-data/unit/fine-grained.test index 8d41595fa04a..b528fc84bdbb 100644 --- a/test-data/unit/fine-grained.test +++ b/test-data/unit/fine-grained.test @@ -4922,7 +4922,7 @@ class D(Generic[T]): pass [out] == -a.py:3: error: Type argument "c.A" of "D" must be a subtype of "c.B" +a.py:3: error: Type argument "A" of "D" must be a subtype of "B" [case testTypeVarValuesRuntime] from mod import I, S, D From 3d83ff8de0fd62d93bb086f09587469626616498 Mon Sep 17 00:00:00 2001 From: Jingchen Ye <97littleleaf11@gmail.com> Date: Thu, 11 Nov 2021 18:24:07 +0800 Subject: [PATCH 2/4] Remove builtins. from error messages of invalid signature --- mypy/messages.py | 5 +++-- test-data/unit/check-classes.test | 12 ++++++------ test-data/unit/check-modules.test | 6 +++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/mypy/messages.py b/mypy/messages.py index 6ee02d0ce321..e3b12f49d980 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -1151,11 +1151,12 @@ def yield_from_invalid_operand_type(self, expr: Type, context: Context) -> Type: return AnyType(TypeOfAny.from_error) def invalid_signature(self, func_type: Type, context: Context) -> None: - self.fail('Invalid signature "{}"'.format(func_type), context) + self.fail('Invalid signature {}'.format(format_type(func_type)), context) def invalid_signature_for_special_method( self, func_type: Type, context: Context, method_name: str) -> None: - self.fail('Invalid signature "{}" for "{}"'.format(func_type, method_name), context) + self.fail('Invalid signature {} for "{}"'.format(format_type(func_type), method_name), + context) def reveal_type(self, typ: Type, context: Context) -> None: self.note('Revealed type is "{}"'.format(typ), context) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 55649f3c6032..cb89962dfbb8 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -2024,8 +2024,8 @@ class B: class C: def __radd__(self, other, oops) -> int: ... [out] -tmp/foo.pyi:3: error: Invalid signature "def (foo.B) -> foo.A" -tmp/foo.pyi:5: error: Invalid signature "def (foo.C, Any, Any) -> builtins.int" +tmp/foo.pyi:3: error: Invalid signature "def (B) -> A" +tmp/foo.pyi:5: error: Invalid signature "def (C, Any, Any) -> int" [case testReverseOperatorOrderingCase1] class A: @@ -2627,8 +2627,8 @@ class C: class D: def __getattribute__(self, x: str) -> None: pass [out] -main:4: error: Invalid signature "def (__main__.B, __main__.A) -> __main__.B" for "__getattribute__" -main:6: error: Invalid signature "def (__main__.C, builtins.str, builtins.str) -> __main__.C" for "__getattribute__" +main:4: error: Invalid signature "def (B, A) -> B" for "__getattribute__" +main:6: error: Invalid signature "def (C, str, str) -> C" for "__getattribute__" [case testGetattr] @@ -2704,8 +2704,8 @@ class C: class D: def __getattr__(self, x: str) -> None: pass [out] -main:4: error: Invalid signature "def (__main__.B, __main__.A) -> __main__.B" for "__getattr__" -main:6: error: Invalid signature "def (__main__.C, builtins.str, builtins.str) -> __main__.C" for "__getattr__" +main:4: error: Invalid signature "def (B, A) -> B" for "__getattr__" +main:6: error: Invalid signature "def (C, str, str) -> C" for "__getattr__" [case testSetattr] from typing import Union, Any diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index 79960d22d9a3..799f2c5d0847 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -2000,7 +2000,7 @@ reveal_type(has_getattr.any_attribute) def __getattr__(x: int, y: str) -> str: ... [out] -tmp/has_getattr.pyi:1: error: Invalid signature "def (builtins.int, builtins.str) -> builtins.str" for "__getattr__" +tmp/has_getattr.pyi:1: error: Invalid signature "def (int, str) -> str" for "__getattr__" main:3: note: Revealed type is "builtins.str" [builtins fixtures/module.pyi] @@ -2141,7 +2141,7 @@ def make_getattr_bad() -> Callable[[], int]: ... __getattr__ = make_getattr_bad() [out] -tmp/non_stub.py:4: error: Invalid signature "def () -> builtins.int" for "__getattr__" +tmp/non_stub.py:4: error: Invalid signature "def () -> int" for "__getattr__" main:3: note: Revealed type is "builtins.int" [case testModuleLevelGetattrImportedGood] @@ -2167,7 +2167,7 @@ from has_getattr import __getattr__ def __getattr__() -> int: ... [out] -tmp/has_getattr.py:1: error: Invalid signature "def () -> builtins.int" for "__getattr__" +tmp/has_getattr.py:1: error: Invalid signature "def () -> int" for "__getattr__" main:3: note: Revealed type is "builtins.int" [builtins fixtures/module.pyi] From ef932023cdc2865eb66c64ab220d4fbf8ed5a04a Mon Sep 17 00:00:00 2001 From: Jingchen Ye <97littleleaf11@gmail.com> Date: Thu, 11 Nov 2021 19:05:42 +0800 Subject: [PATCH 3/4] Update test cases --- test-data/unit/check-classes.test | 20 ++++++++++---------- test-data/unit/check-modules.test | 8 ++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index cb89962dfbb8..953dc4d7afc8 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -2024,8 +2024,8 @@ class B: class C: def __radd__(self, other, oops) -> int: ... [out] -tmp/foo.pyi:3: error: Invalid signature "def (B) -> A" -tmp/foo.pyi:5: error: Invalid signature "def (C, Any, Any) -> int" +tmp/foo.pyi:3: error: Invalid signature "Callable[[B], A]" +tmp/foo.pyi:5: error: Invalid signature "Callable[[C, Any, Any], int]" [case testReverseOperatorOrderingCase1] class A: @@ -2627,8 +2627,8 @@ class C: class D: def __getattribute__(self, x: str) -> None: pass [out] -main:4: error: Invalid signature "def (B, A) -> B" for "__getattribute__" -main:6: error: Invalid signature "def (C, str, str) -> C" for "__getattribute__" +main:4: error: Invalid signature "Callable[[B, A], B]" for "__getattribute__" +main:6: error: Invalid signature "Callable[[C, str, str], C]" for "__getattribute__" [case testGetattr] @@ -2704,8 +2704,8 @@ class C: class D: def __getattr__(self, x: str) -> None: pass [out] -main:4: error: Invalid signature "def (B, A) -> B" for "__getattr__" -main:6: error: Invalid signature "def (C, str, str) -> C" for "__getattr__" +main:4: error: Invalid signature "Callable[[B, A], B]" for "__getattr__" +main:6: error: Invalid signature "Callable[[C, str, str], C]" for "__getattr__" [case testSetattr] from typing import Union, Any @@ -2729,7 +2729,7 @@ c = C() c.fail = 4 # E: Incompatible types in assignment (expression has type "int", variable has type "str") class D: - __setattr__ = 'hello' # E: Invalid signature "builtins.str" for "__setattr__" + __setattr__ = 'hello' # E: Invalid signature "str" for "__setattr__" d = D() d.crash = 4 # E: "D" has no attribute "crash" @@ -2754,12 +2754,12 @@ s.fail = 'fail' # E: Incompatible types in assignment (expression has type "str from typing import Any class Test: - def __setattr__() -> None: ... # E: Method must have at least one argument # E: Invalid signature "def ()" for "__setattr__" + def __setattr__() -> None: ... # E: Method must have at least one argument # E: Invalid signature "Callable[[], None]" for "__setattr__" t = Test() t.crash = 'test' # E: "Test" has no attribute "crash" class A: - def __setattr__(self): ... # E: Invalid signature "def (__main__.A) -> Any" for "__setattr__" + def __setattr__(self): ... # E: Invalid signature "Callable[[A], Any]" for "__setattr__" a = A() a.test = 4 # E: "A" has no attribute "test" @@ -2769,7 +2769,7 @@ b = B() b.integer = 5 class C: - def __setattr__(self, name: int, value: int) -> None: ... # E: Invalid signature "def (__main__.C, builtins.int, builtins.int)" for "__setattr__" + def __setattr__(self, name: int, value: int) -> None: ... # E: Invalid signature "Callable[[C, int, int], None]" for "__setattr__" c = C() c.check = 13 diff --git a/test-data/unit/check-modules.test b/test-data/unit/check-modules.test index 799f2c5d0847..1ae31d99c25b 100644 --- a/test-data/unit/check-modules.test +++ b/test-data/unit/check-modules.test @@ -2000,7 +2000,7 @@ reveal_type(has_getattr.any_attribute) def __getattr__(x: int, y: str) -> str: ... [out] -tmp/has_getattr.pyi:1: error: Invalid signature "def (int, str) -> str" for "__getattr__" +tmp/has_getattr.pyi:1: error: Invalid signature "Callable[[int, str], str]" for "__getattr__" main:3: note: Revealed type is "builtins.str" [builtins fixtures/module.pyi] @@ -2014,7 +2014,7 @@ reveal_type(has_getattr.any_attribute) __getattr__ = 3 [out] -tmp/has_getattr.pyi:1: error: Invalid signature "builtins.int" for "__getattr__" +tmp/has_getattr.pyi:1: error: Invalid signature "int" for "__getattr__" main:3: note: Revealed type is "Any" [builtins fixtures/module.pyi] @@ -2141,7 +2141,7 @@ def make_getattr_bad() -> Callable[[], int]: ... __getattr__ = make_getattr_bad() [out] -tmp/non_stub.py:4: error: Invalid signature "def () -> int" for "__getattr__" +tmp/non_stub.py:4: error: Invalid signature "Callable[[], int]" for "__getattr__" main:3: note: Revealed type is "builtins.int" [case testModuleLevelGetattrImportedGood] @@ -2167,7 +2167,7 @@ from has_getattr import __getattr__ def __getattr__() -> int: ... [out] -tmp/has_getattr.py:1: error: Invalid signature "def () -> int" for "__getattr__" +tmp/has_getattr.py:1: error: Invalid signature "Callable[[], int]" for "__getattr__" main:3: note: Revealed type is "builtins.int" [builtins fixtures/module.pyi] From b7e18a0b930abc601173817e0c30f29674365b6c Mon Sep 17 00:00:00 2001 From: Jingchen Ye <97littleleaf11@gmail.com> Date: Thu, 11 Nov 2021 20:55:19 +0800 Subject: [PATCH 4/4] Update for CHECK_ALWAYS_TRUE --- mypy/checker.py | 26 +++++++++++--------------- mypy/message_registry.py | 2 +- test-data/unit/check-errorcodes.test | 12 ++++++------ 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 95789831fd6f..36751bbc9b15 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -4229,31 +4229,27 @@ def _check_for_truthy_type(self, t: Type, expr: Expression) -> None: return def format_expr_type() -> str: + typ = format_type(t) if isinstance(expr, MemberExpr): - return f'Member "{expr.name}" has type "{t}"' + return f'Member "{expr.name}" has type {typ}' elif isinstance(expr, RefExpr) and expr.fullname: - return f'"{expr.fullname}" has type "{t}"' + return f'"{expr.fullname}" has type {typ}' elif isinstance(expr, CallExpr): if isinstance(expr.callee, MemberExpr): - return f'"{expr.callee.name}" returns "{t}"' + return f'"{expr.callee.name}" returns {typ}' elif isinstance(expr.callee, RefExpr) and expr.callee.fullname: - return f'"{expr.callee.fullname}" returns "{t}"' - return f'Call returns "{t}"' + return f'"{expr.callee.fullname}" returns {typ}' + return f'Call returns {typ}' else: - return f'Expression has type "{t}"' + return f'Expression has type {typ}' if isinstance(t, FunctionLike): - self.fail(message_registry.FUNCTION_ALWAYS_TRUE.format(t), expr) + self.fail(message_registry.FUNCTION_ALWAYS_TRUE.format(format_type(t)), expr) elif isinstance(t, UnionType): - self.fail( - message_registry.TYPE_ALWAYS_TRUE_UNIONTYPE.format(format_expr_type()), - expr, - ) + self.fail(message_registry.TYPE_ALWAYS_TRUE_UNIONTYPE.format(format_expr_type()), + expr) else: - self.fail( - message_registry.TYPE_ALWAYS_TRUE.format(format_expr_type()), - expr, - ) + self.fail(message_registry.TYPE_ALWAYS_TRUE.format(format_expr_type()), expr) def find_type_equals_check(self, node: ComparisonExpr, expr_indices: List[int] ) -> Tuple[TypeMap, TypeMap]: diff --git a/mypy/message_registry.py b/mypy/message_registry.py index b6005744b25f..9ddb1604ca27 100644 --- a/mypy/message_registry.py +++ b/mypy/message_registry.py @@ -131,7 +131,7 @@ def format(self, *args: object, **kwargs: object) -> "ErrorMessage": code=codes.TRUTHY_BOOL, ) FUNCTION_ALWAYS_TRUE: Final = ErrorMessage( - 'Function "{}" could always be true in boolean context', + 'Function {} could always be true in boolean context', code=codes.TRUTHY_BOOL, ) NOT_CALLABLE: Final = '{} not callable' diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index e7973924bf39..46a8792f5c75 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -854,7 +854,7 @@ class Foo: pass foo = Foo() -if foo: # E: "__main__.foo" has type "__main__.Foo" which does not implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool] +if foo: # E: "__main__.foo" has type "Foo" which does not implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool] pass zero = 0 @@ -880,18 +880,18 @@ if not good_union: pass bad_union: Union[Foo, object] = Foo() -if bad_union: # E: "__main__.bad_union" has type "Union[__main__.Foo, builtins.object]" of which no members implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool] +if bad_union: # E: "__main__.bad_union" has type "Union[Foo, object]" of which no members implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool] pass -if not bad_union: # E: "__main__.bad_union" has type "builtins.object" which does not implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool] +if not bad_union: # E: "__main__.bad_union" has type "object" which does not implement __bool__ or __len__ so it could always be true in boolean context [truthy-bool] pass def f(): pass -if f: # E: Function "def () -> Any" could always be true in boolean context [truthy-bool] +if f: # E: Function "Callable[[], Any]" could always be true in boolean context [truthy-bool] pass -if not f: # E: Function "def () -> Any" could always be true in boolean context [truthy-bool] +if not f: # E: Function "Callable[[], Any]" could always be true in boolean context [truthy-bool] pass -conditional_result = 'foo' if f else 'bar' # E: Function "def () -> Any" could always be true in boolean context [truthy-bool] +conditional_result = 'foo' if f else 'bar' # E: Function "Callable[[], Any]" could always be true in boolean context [truthy-bool] lst: List[int] = [] if lst: