mypy
mypy copied to clipboard
Adding a field to a callback protocol changes the checks performed by mypy
I noticed something really weird about callback protocols. Consider the following example:
from typing import TypeVar, Protocol
T = TypeVar("T")
class MyCallable(Protocol[T]):
__name__: str
def __call__(
self,
__arg: T,
) -> T: ...
def decorator(x: MyCallable[T]) -> MyCallable[T]:
return x
@decorator
def func(arg: T) -> T:
return arg
x = func(1)
It works fine with mypy 1.10.0 (although it fails to check with pyright 1.1.360: https://github.com/microsoft/pyright/issues/7782).
However, adding a __name__: str field to the protocol changes the checks performed by mypy. The example becomes:
from typing import TypeVar, Protocol
T = TypeVar("T")
class MyCallable(Protocol[T]):
__name__: str
def __call__(
self,
__arg: T,
) -> T: ...
def decorator(x: MyCallable[T]) -> MyCallable[T]:
return x
@decorator
def func(arg: T) -> T:
return arg
x = func(1)
And it fails with:
test.py:25: error: Need type annotation for "x" [var-annotated]
test.py:25: error: Argument 1 to "__call__" of "MyCallable" has incompatible type "int"; expected Never [arg-type]