I have the following code to compare a base class' current (empty) implementation of required functions to its sub-classes, which must implement them in some different way in order to be considered acceptable at runtime. Without using a metaclass=ABCMeta
and implementing @abstractmethod
decorators on these base class methods, how do I go about doing this? For now, I'm writing the following __init_subclass__
hook on my ad-hoc, metaclass-less abstract base classes in multiple places in my project, but it feels wrong.
import inspect
class AbstractThing:
def __init__(self, topic: str, thing: Thing):
thing.subscriptions[topic] = self.on_message
thing.on_connected.append(self.on_connected)
thing.on_disconnected.append(self.on_disconnected)
def __init_subclass__(cls):
required_methods = ['on_connected', 'on_disconnected', 'on_message']
for f in required_methods:
func_source = inspect.getsourcelines(getattr(cls, f))
# if this class no longer inherits from `Object`, the method resolution order will have updated
parent_func_source = inspect.getsourcelines(getattr(cls.__mro__[-2], f))
if func_source == parent_func_source:
raise NotImplementedError(f"You need to override method '{f}' in your class {cls.__name__}")
def on_connected(self, config: dict):
pass
def on_disconnected(self):
pass
def on_message(self, msg: str):
pass
Is there a better way to do this? Bonus points if I can get typechecking errors in my editor while defining sub classes of this AbstractThing
.