Search code examples
pythonpython-3.xpycharmpython-typing

Python Protocol using keyword-only arguments requires implementation to have different signature


I'm on python 3.10. I'm using PyCharm's default type checker and MyPy. Here is the protocol I defined:

class OnSubscribeFunc(Protocol):
    def __call__(self, instrument: str, *, x: int) -> AsyncGenerator:
        ...

When create a method that implements it like this:

class A:
    async def subscribe(self, instrument: str, *, x: int):
        yield ...
a: OnSubscribeFunc = A().subscribe  # this apparently is where it gets it wrong

I get this warning: Expected type 'OnSubscribeFunc', got '(instrument: str, Any, x: int) -> AsyncGenerator' instead

If I remove the * from my implementation however, the warning disappears. I would expect it to be the other way around because not having the * allows the implementation to have non-keyword-only arguments which might not be what I'm aiming for with my protocol.

So for comparison - this implementation gives no warning:

class A:
    async def subscribe(self, instrument: str, x: int):
        yield ...

This does not make any sense to me, why does it behave like this and is this expected or is it a bug in my type checker?


Solution

  • This is a known bug of PyCharm. Mypy and Pyright both accept your code as it is.

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