mypy doesn't complain when class doesn't implement protocol

Viewed 319

I have the following code. Class A contains a function f. Class B inherits from A and overrides this function. I also have protocol SupportsG which acts as a structural supertype to all classes implementing a function g. I have class B explicitly inherit this protocol:

from typing import Protocol

class SupportsG(Protocol):
  def g(self) -> str: ...

class A:
  def f(self) -> str:
    return ""

class B(A, SupportsG):
  def f(self) -> str:
    return "test"

if __name__ == "__main__":
  b = B()  

My expectation here is that mypy would throw an error, because class B doesn't implement function g. However, if I run mypy --strict I get no errors.

What is the gap in my understanding here?

2 Answers
def test(x: SupportsG):
  pass  # whatever

a = A()
b = B()

test(a)  # mypy should complain
test(b)  # mypy should complain

class C:
  def g(self) -> str:
    return ""

c = C()
test(c)  # should be fine

You don't need to inherit your class from SupportsG.

Btw, one purpose for Protocol is also to define custom function interfaces with kwargs, which is not possible with Callable, like:

def func(a, *, b) -> str:
  pass

class Func(Protocol):
  def __call__(self, a, *, b) -> str: ...

def test(f: Func):
  pass

test(func)  # ok!

Protocol is for use in structural typing to define input types, not in inheritance.

You should be using ABC instead of Protocol; it does exactly what you want.

Related