From b99c89f1d5034d0681854b66d5b6ee2624c54cdf Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sun, 21 Aug 2022 19:04:55 +0300 Subject: [PATCH 1/3] `ParamSpec` must not raise errors on valid attr access --- mypy/semanal.py | 5 ++++ .../unit/check-parameter-specification.test | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/mypy/semanal.py b/mypy/semanal.py index 71f588a144a0..dfc249f96daf 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -5107,6 +5107,11 @@ def lookup_qualified( if isinstance(typ, AnyType): # Allow access through Var with Any type without error. return self.implicit_symbol(sym, name, parts[i:], typ) + # This might be something like valid `P.args` or invalid `P.__bound__` access. + # Important note that `ParamSpecExpr` is also ignored in other places. + # See https://github.com/python/mypy/pull/13468 + if isinstance(node, ParamSpecExpr) and part in ('args', 'kwargs'): + return None # Lookup through invalid node, such as variable or function nextsym = None if not nextsym or nextsym.module_hidden: diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index bac23f31c289..00e7a8489f19 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -1127,3 +1127,28 @@ def func(callback: Callable[P1, str]) -> Callable[P1, str]: return "foo" return inner [builtins fixtures/paramspec.pyi] + +[case testParamSpecTestPropAccess] +from typing import Callable +from typing_extensions import ParamSpec + +P1 = ParamSpec("P1") + +def func1(callback: Callable[P1, str]) -> Callable[P1, str]: + def inner( + *args: P1.typo, # E: Use "P1.args" for variadic "*" parameter \ + # E: Name "P1.typo" is not defined + **kwargs: P1.kwargs, + ) -> str: + return "foo" + return inner + +def func2(callback: Callable[P1, str]) -> Callable[P1, str]: + def inner( + *args: P1.args, + **kwargs: P1.__bound__, # E: Use "P1.kwargs" for variadic "**" parameter \ + # E: Name "P1.__bound__" is not defined + ) -> str: + return "foo" + return inner +[builtins fixtures/paramspec.pyi] From 671ce5f1ac961275e2e87d2aaac0e804289c0fca Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sun, 21 Aug 2022 19:06:58 +0300 Subject: [PATCH 2/3] black --- mypy/semanal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index dfc249f96daf..5ee372c43bd1 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -5110,7 +5110,7 @@ def lookup_qualified( # This might be something like valid `P.args` or invalid `P.__bound__` access. # Important note that `ParamSpecExpr` is also ignored in other places. # See https://github.com/python/mypy/pull/13468 - if isinstance(node, ParamSpecExpr) and part in ('args', 'kwargs'): + if isinstance(node, ParamSpecExpr) and part in ("args", "kwargs"): return None # Lookup through invalid node, such as variable or function nextsym = None From 025552c6954c1e2efac50746b8ae801a078b2522 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Sun, 21 Aug 2022 19:19:35 +0300 Subject: [PATCH 3/3] Add one more test --- test-data/unit/check-parameter-specification.test | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test index 00e7a8489f19..a561acba693c 100644 --- a/test-data/unit/check-parameter-specification.test +++ b/test-data/unit/check-parameter-specification.test @@ -1151,4 +1151,14 @@ def func2(callback: Callable[P1, str]) -> Callable[P1, str]: ) -> str: return "foo" return inner + +def func3(callback: Callable[P1, str]) -> Callable[P1, str]: + def inner( + *args: P1.__bound__, # E: Use "P1.args" for variadic "*" parameter \ + # E: Name "P1.__bound__" is not defined + **kwargs: P1.invalid, # E: Use "P1.kwargs" for variadic "**" parameter \ + # E: Name "P1.invalid" is not defined + ) -> str: + return "foo" + return inner [builtins fixtures/paramspec.pyi]