I'm creating a module with a function that works as a factory of the implemented classes. It works registering the classes with the help of a metaclass (a pattern I have just copied from here).
_registry = {}
def register_class(cls):
_registry[cls.__name__] = cls
class Meta(type):
def __new__(meta, name, bases, class_dict):
cls = type.__new__(meta, name, bases, class_dict)
register_class(cls)
return cls
def factory(name):
return _registry[name]()
This works so far.
Now a particularity I have is that I'm implementing classes that share a lot of functionality, therefore I define an abstract base class that implements most of the shared logic, and a large number of derived classes that refine certain particularities. The problem is that this leads to a metaclass conflict, as the metaclass of the the derived classes is both ABCmeta and Meta:
from abc import ABC, abstractmethod
_registry = {}
def register_class(cls):
_registry[cls.__name__] = cls
class Meta(type):
def __new__(meta, name, bases, class_dict):
cls = type.__new__(meta, name, bases, class_dict)
register_class(cls)
return cls
def factory(name):
return _registry[name]()
class Base(ABC):
pass
class Derived1(Base, metaclass=Meta):
pass
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
How can I work around this conflict?
Baseinherited fromABC, I think it works to just haveMetainherit fromABCMeta(making use ofsuper()appropriately. Alternately, did you consider just using a decorator to do the registration? Obviously it's an extra line per class, but that replaces ametaclass=argument, and I think it's arguably more explicit.