Skip to content
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

ParamSpec must not raise errors on valid attr access #13472

Merged
merged 3 commits into from
Aug 21, 2022
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
5 changes: 5 additions & 0 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
35 changes: 35 additions & 0 deletions test-data/unit/check-parameter-specification.test
Original file line number Diff line number Diff line change
Expand Up @@ -1127,3 +1127,38 @@ 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How hard would it be to make this say something like "ParamSpec has no attribute 'typo'" instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite hard :)

Right now checkmember is not involved at all, this is semanal-level check.
We can change the error message (special case it for ParamSpec), but I don't think this is a good idea.

**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

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]