From 793a9b95cf4cbf2b572a7d75851e9f29d4fae521 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Sat, 21 May 2022 01:13:02 -0700 Subject: [PATCH 1/3] Improve Callable error for PEP 612 --- mypy/typeanal.py | 6 +++--- test-data/unit/semanal-errors.test | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 98e37bd0aa40..3a14f06633a0 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -944,9 +944,9 @@ def analyze_callable_type(self, t: UnboundType) -> Type: ) if maybe_ret is None: # Callable[?, RET] (where ? is something invalid) - # TODO(PEP612): change error to mention paramspec, once we actually have some - # support for it - self.fail('The first argument to Callable must be a list of types or "..."', t) + self.fail( + 'The first argument to Callable must be a ' + 'list of types, parameter specification, or "..."', t) return AnyType(TypeOfAny.from_error) ret = maybe_ret else: diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 14bc24f03a7b..721de3941a4c 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -867,7 +867,7 @@ x = None # type: Callable[int, str] y = None # type: Callable[int] z = None # type: Callable[int, int, int] [out] -main:2: error: The first argument to Callable must be a list of types or "..." +main:2: error: The first argument to Callable must be a list of types, parameter specification, or "..." main:3: error: Please use "Callable[[], ]" or "Callable" main:4: error: Please use "Callable[[], ]" or "Callable" From 5abcf0a6ef48614688503e6bd84f505dd46555af Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Sat, 21 May 2022 12:30:37 -0700 Subject: [PATCH 2/3] more errors --- mypy/typeanal.py | 9 +++++++++ test-data/unit/semanal-errors.test | 1 + 2 files changed, 10 insertions(+) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 3a14f06633a0..71356ae60c97 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -947,6 +947,10 @@ def analyze_callable_type(self, t: UnboundType) -> Type: self.fail( 'The first argument to Callable must be a ' 'list of types, parameter specification, or "..."', t) + self.note( + 'See https://mypy.readthedocs.io/en/stable/kinds_of_types.html#callable-types-and-lambdas', # noqa: E501 + t + ) return AnyType(TypeOfAny.from_error) ret = maybe_ret else: @@ -1180,6 +1184,11 @@ def anal_type(self, t: Type, nested: bool = True, *, allow_param_spec: bool = Fa and analyzed.flavor == ParamSpecFlavor.BARE): if analyzed.prefix.arg_types: self.fail('Invalid location for Concatenate', t) + self.note( + 'You can use Concatenate as the first argument to Callable, e.g., ' + "'Callable[{}, int]'".format(analyzed.name), + t + ) else: self.fail(f'Invalid location for ParamSpec "{analyzed.name}"', t) self.note( diff --git a/test-data/unit/semanal-errors.test b/test-data/unit/semanal-errors.test index 721de3941a4c..a1ff4ec1c3e7 100644 --- a/test-data/unit/semanal-errors.test +++ b/test-data/unit/semanal-errors.test @@ -868,6 +868,7 @@ y = None # type: Callable[int] z = None # type: Callable[int, int, int] [out] main:2: error: The first argument to Callable must be a list of types, parameter specification, or "..." +main:2: note: See https://mypy.readthedocs.io/en/stable/kinds_of_types.html#callable-types-and-lambdas main:3: error: Please use "Callable[[], ]" or "Callable" main:4: error: Please use "Callable[[], ]" or "Callable" From bd1cf23404b45b77ebb4d3e482b94f56678257e5 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Sat, 21 May 2022 12:32:20 -0700 Subject: [PATCH 3/3] fix test --- mypy/typeanal.py | 3 +-- test-data/unit/check-parameter-specification.test | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mypy/typeanal.py b/mypy/typeanal.py index 71356ae60c97..bd0f684653b2 100644 --- a/mypy/typeanal.py +++ b/mypy/typeanal.py @@ -1185,8 +1185,7 @@ def anal_type(self, t: Type, nested: bool = True, *, allow_param_spec: bool = Fa if analyzed.prefix.arg_types: self.fail('Invalid location for Concatenate', t) self.note( - 'You can use Concatenate as the first argument to Callable, e.g., ' - "'Callable[{}, int]'".format(analyzed.name), + 'You can use Concatenate as the first argument to Callable', t ) else: diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index 28b08aa7122f..4dae32978263 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -25,7 +25,8 @@ def foo1(x: Callable[P, int]) -> Callable[P, str]: ... def foo2(x: P) -> P: ... # E: Invalid location for ParamSpec "P" \ # N: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]' -def foo3(x: Concatenate[int, P]) -> int: ... # E: Invalid location for Concatenate +def foo3(x: Concatenate[int, P]) -> int: ... # E: Invalid location for Concatenate \ + # N: You can use Concatenate as the first argument to Callable def foo4(x: List[P]) -> None: ... # E: Invalid location for ParamSpec "P" \ # N: You can use ParamSpec as the first argument to Callable, e.g., 'Callable[P, int]'