I have inherited a legacy project that has a Superclass which offers hooks for custom behaviors by invoking override functions in the subclasses. The superclass defines the attribute as None
, and invokes the methods when the value is not None. It seems to be loosely based on ideas form zope.interface and protocols.
For example, a simplified version of the code is:
class Super:
hook_bar: Optional[Callable] = None
def foo(self) -> List:
data = []
if self.hook_bar is not None:
data = self.hook_bar()
return data
class Sub(Super):
def hook_bar(self)->List:
return hook_bar
I can’t seem to figure out how to type Super.hook_bar
with a signature, which I’d like to do so I can ensure a consistent use of the interface with mypy.
I’ve tried a dozen techniques used for tangential concepts, but the only thing I’ve found that works with mypy is to define and unset the method – then have mypy ignore the unset:
class Super:
def hook_bar(self)->List:
return hook_bar
hook_bar = None # type: ignore
If I use Protocol to write classes that support the function and then inherit from that (as in the file-like mypy examples), I still need to ignore the = None
on the superclass. I’ve been able to use typing.Protocol
to define optional Callable+returns in method arguments, but that doesn’t seem to work as a classmethod.
Is there a better way to handle this?