Description
-
Are you reporting a bug, or opening a feature request?
bug -
Please insert below the code you are checking with mypy, or a mock-up repro if the source is private. We would appreciate if you try to simplify your case to a minimal repro.
from typing import Protocol
class P(Protocol):
def foo(self) -> int: ...
class A(P): # mypy does not flag this
pass
class B:
pass
test: P = A() # mypy does not flag this
test = B() # mypy flags this
print(A().foo() + 5) # both error at runtime
print(B().foo() + 5)
-
What is the actual behavior/output?
A().foo() + 5
crashes at runtime withTypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
B
is correctly type checked and rejected. -
What is the behavior/output you expect?
According to https://mypy.readthedocs.io/en/latest/protocols.html#defining-subprotocols-and-subclassing-protocols, "Explicitly including a protocol as a base class ... forces mypy to verify that your class implementation is actually compatible with the protocol."
I would expect extending a Protocol to be similar to implementing an interface in Java.
In this particular example, mypy should ideally detect thatA
does not fill in the stub method fromP
, like it does forB
. Alternatively, if that is not possible, perhaps extending a protocol should not be allowed. -
What are the versions of mypy and Python you are using? Do you see the same issue after installing mypy from Git master?
Python 3.8.0
mypy 0.750+dev.d9dea5f3ad30bb449e4167b3e8476684ded0482e -
What are the mypy flags you are using? (For example --strict-optional)
mypy --strict test.py