Skip to content

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

Closed

Description

@JonathanPlasse

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

Activity

  1. erictraut commented on Oct 30, 2022

    @erictraut

    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.

  2. hauntsaninja commented on Oct 31, 2022

    @hauntsaninja
    Collaborator

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

  3. ilevkivskyi commented on Aug 16, 2023

    @ilevkivskyi
    Member

    Yeah, the error message is still not very good:

    ParamSpec must have "*args" typed as "P.args" and "**kwargs" typed as "P.kwargs" 
    
  4. 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[/+] on Nov 13, 2023
  5. added a commit that references this issue on Jan 2, 2025
    025642b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions