I need to make sure that developers on my team are not directly subclassing a typing.Protocol instance. That is, although their classes should implement the interface of the Protocol, we don't want:
class MyClass(MyProtocol):
# inherits MyProtocol
which would coerce the class to be a subclass of the Protocol and, therefore, necessarily pass isinstance(MyClass(), MyProtocol) even if it does not implement any logic in the attributes and methods of the class.
Example of the problem:
class MyProtocol(Protocol):
def foo(self):
raise NotImplementedError("Don't subclass MyProtocol!")
class MyClass(MyProtocol):
pass
# MyClass now has foo since it inherits the Protocol...
assert hasattr(MyClass(), 'foo')
In other words, I would like a test of the form:
def does_not_subclass_protocol(obj, protocol):
# returns True if and only if obj does not have
# MyClass(MyProtocol)...
# syntax in class definition.