8000 Potential false positives with `ParamSpec "P" is unbound` after upgrading from 1.14.1 to 1.15.0 · Issue #18745 · python/mypy · GitHub
[go: up one dir, main page]

Skip to content

Potential false positives with ParamSpec "P" is unbound after upgrading from 1.14.1 to 1.15.0 #18745

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

Closed
alichaudry opened this issue Feb 27, 2025 · 1 comment
Labels
bug mypy got something wrong

Comments

@alichaudry
Copy link

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

Playground link
Gist link

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
@alichaudry alichaudry added the bug mypy got something wrong label Feb 27, 2025
@A5rocks
Copy link
Collaborator
A5rocks commented Feb 28, 2025

If you enable --disallow-any-generics you will get errors about missing paramspecs or typevars. In this case for instance you have:

def check_auth(f: FlaskRestfulHTTPMethod) -> FlaskRestfulHTTPMethod:

and you should instead have

def check_auth(f: FlaskRestfulHTTPMethod[P]) -> FlaskRestfulHTTPMethod[P]:

I'm surprised --strict doesn't enable that.

@A5rocks A5rocks closed this as not planned Won't fix, can't repro, duplicate, stale Feb 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

No branches or pull requests

2 participants
0