agronholm / typeguard

Run-time type checker for Python
Other
1.5k stars 112 forks source link

"argument is not compatible with the protocol" when inheriting from `Protocol` #457

Closed bersbersbers closed 3 months ago

bersbersbers commented 4 months ago

Things to check first

Typeguard version

4.2.1

Python version

3.12.1

What happened?

Typeguard reports incompatibilities between a the values of a type variable and its type (I hope that makes sense). The value of type_argument is Class, which is a type derived from Base, so it should be compatible with type[Base].

How can we reproduce the bug?

bug.py

from typing import Protocol, runtime_checkable

from typeguard import typechecked

@runtime_checkable
class Base(Protocol):
    number: int

class Class(Base):
    number: int

@typechecked
def bug(type_argument: type[Base]) -> None:
    print(type_argument)

# mypy and pyright say this is OK:
type_argument: type[Base] = Class

# typeguard says this is not ok:
bug(Class)
mypy bug.py
pyright bug.py
python bug.py
typeguard.TypeCheckError: argument "type_argument" (class __main__.Class) is not compatible with the Base protocol
agronholm commented 3 months ago

There is a bug, but issubclass(Class, Base) wouldn't work at run time anyway because it can only check method members.

TypeError: Protocols with non-method members don't support issubclass()