Consider I define a protocol Frobbable. And further I have a valid implementation of the protocol, and a broken implementation which is missing the .frob() method:
from typing import Protocol
from abc import abstractmethod
class Frobbable(Protocol):
@abstractmethod
def frob(self) -> None:
raise NotImplementedError
def main(knob: Frobbable) -> None:
knob.frob()
class Knob:
def frob(self) -> None:
print("knob has been frobbed")
class BrokenKnob:
pass
main(Knob())
main(BrokenKnob())
Checking this program with mypy results in an error, as expected:
testprotocol.py:25:6: error: Argument 1 to "main" has incompatible type "BrokenKnob"; expected "Frobbable" [arg-type]
main(BrokenKnob())
^
Found 1 error in 1 file (checked 1 source file)
Unfortunately, it doesn't offer any information about why BrokenKnob is incompatible: in this case, it is missing .frob(). Without such information, correcting such an issue in a nontrivial program (with protocols with many methods, and many implementations) becomes a profoundly tedious chore.
Is there any way to get this information from mypy or any other tool without modifying the program? I know I can explicitly subclass Frobbable, but this rather defeats the purpose of using a Protocol.