Description
Bug Report
After upgrading to mypy 1.15.0 from mypy 1.14.1, I am now experiencing hundreds of new ParamSpec "P" is unbound
errors. I imagine quite a few of these are valid, and for my use-case, I'm going to just swap how I'm (incorrectly) using ParamSpec (*args: P.args, **kwargs: P.kwargs
, where P is not bound to the function in many of these cases) with a separate appropriate version (*args: object, **kwargs: object
; I don't want to use Any
and turn off type-checking entirely). However, I am running into cases where I think P
is bound, and yet still throwing a MyPy exception.
From what I can tell, the PR which added this update may have missed my specific use-case. @sterliakov, as the author of this PR, any thoughts on my specific example? Also, would love to hear your thoughts on switching out unbound *args: P.args
to *args: object
instead of *args: Any
. Thanks!
Example and playground gist below.
To Reproduce
from collections.abc import Callable
from functools import wraps
from typing import ParamSpec, TypeAlias
from flask import Response
from flask_login import current_user
P = ParamSpec("P")
FlaskRestfulHTTPMethodResponse: TypeAlias = tuple[Response | dict, int]
FlaskRestfulHTTPMethod: TypeAlias = Callable[P, FlaskRestfulHTTPMethodResponse]
def check_auth(f: FlaskRestfulHTTPMethod) -> FlaskRestfulHTTPMethod:
@wraps(f)
def wrapper(*args: P.args, **kwargs: P.kwargs) -> FlaskRestfulHTTPMethodResponse:
if not current_user.is_authenticated:
return {"message": "Unauthorized"}, 401
return f(*args, **kwargs)
return wrapper
Expected Behavior
Should pass the mypy checker (as it does in mypy 1.14.1).
Actual Behavior
ParamSpec "P" is unbound [valid-type]
Your Environment
- Mypy version used: 1.15.0
- Mypy command-line flags: N/A
- Mypy configuration options from
mypy.ini
(and other config files):strict = True
- Python version used: 3.11.4