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

Bad error message for arguments between ParamSpec P.args and P.kwargs #13966

Open
JonathanPlasse opened this issue Oct 30, 2022 · 3 comments
Open
Labels
bug mypy got something wrong topic-error-reporting How we report errors topic-paramspec PEP 612, ParamSpec, Concatenate topic-usability

Comments

@JonathanPlasse
Copy link

Bug Report

ParamSpec P.args and P.kwargs are not defined when using explicit keyword argument.

To Reproduce

This code would be used to type anyio.run().

Link to mypy-play

from typing import ParamSpec, Awaitable, TypeVar, Callable, Any

P = ParamSpec("P")
T_Retval = TypeVar("T_Retval")

def run(
    func: Callable[P, Awaitable[T_Retval]],
    *args: P.args,
    backend: str = "asyncio",
    backend_options: dict[str, Any] | None = None,
    **kwargs: P.kwargs,
) -> T_Retval:
    pass

but it works without explicit keyword arguments.

from typing import ParamSpec, Awaitable, TypeVar, Callable, Any

P = ParamSpec("P")
T_Retval = TypeVar("T_Retval")

def run(
    func: Callable[P, Awaitable[T_Retval]],
    *args: P.args,
    **kwargs: P.kwargs,
) -> T_Retval:
    pass

Expected Behavior

It should be able to type and recognize that run() passes the rest of the arguments to the function a().

async def a(b: str, c: int) -> None:
    pass

run(a, "", c=0)

Actual Behavior

main.py:10: error: Name "P.args" is not defined
main.py:13: error: Name "P.kwargs" is not defined

Your Environment

  • Mypy version used: 0.981
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: 3.10
@JonathanPlasse JonathanPlasse added the bug mypy got something wrong label Oct 30, 2022
@AlexWaygood AlexWaygood added the topic-paramspec PEP 612, ParamSpec, Concatenate label Oct 30, 2022
@erictraut
Copy link

erictraut commented Oct 30, 2022

With ParamSpec, you are not allowed to define parameters between *args and **kwargs. PEP 612 is very clear on this point:

Placing keyword-only parameters between the *args and **kwargs is forbidden.

Mypy's error message in this case should probably be improved to indicate as such.

If you move the parameters backend and backend_options before *args, it will type check without errors. That assumes you want backend and backend_options to be positional + keyword parameters and not keyword-only parameters. There's no way to combine ParamSpec with keyword-only parameters because of the constraint I mentioned above.

@hauntsaninja
Copy link
Collaborator

hauntsaninja commented Oct 31, 2022

mypy 0.990 will have a less atrocious error message here (but definitely could still be made more helpful)

@ilevkivskyi
Copy link
Member

Yeah, the error message is still not very good:

ParamSpec must have "*args" typed as "P.args" and "**kwargs" typed as "P.kwargs" 

@ilevkivskyi ilevkivskyi changed the title ParamSpec P.args and P.kwargs are not defined when using explicit keyword argument Bad error message for arguments between ParamSpec P.args and P.kwargs Nov 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-error-reporting How we report errors topic-paramspec PEP 612, ParamSpec, Concatenate topic-usability
Projects
None yet
Development

No branches or pull requests

5 participants