Search code examples
pythonpycharmpython-typingpython-3.12

Annotate decorator with ParamSpec correctly using new typing syntax (3.12)


I'm trying to use new type hints from Python 3.12, and suddenly PyCharm highlights some obscure problem about new usage of ParamSpec.

import functools
from dataclasses import dataclass
from typing import Callable
from typing import Concatenate


@dataclass
class Message:
    text: str


type CheckFunc[**P] = Callable[Concatenate[Message, P], None]


def check_is_command_not_answer[**P](func: CheckFunc[P]) -> CheckFunc[P]:
    @functools.wraps(func)
    def inner(message: Message, *args: P.args, **kwargs: P.kwargs) -> None:
        if message.text:
            ...
        else:
            return func(message, *args, **kwargs)

    return inner

On return inner PyCharm blames:

Expected type '(Message, ParamSpec("P")) -> None', got '(message: Message, ParamSpec("P"), ParamSpec("P")) -> None' instead

Here is the screenshot.

BTW, I'm using this decorator here and there, and the code works perfectly. Pyright doesn't complain for any issues here either.

I cannot spot the problem. Can you?


Solution

  • Your code has no problem. The problem is with PyCharm.

    Its support for Concatenate et al. is incomplete, as discussed in PY-51766. I'm unable to find a good existing issue for this bug, however.

    Put a type: ignore or noqa comment there and move on.