Ketouem Ketouem - 7 months ago 46
Python Question

How can I use multiple inheritance with a metaclass?

I'm trying to register all the resources that I defined with

Flask-RESTFUL
using the registry pattern.

from flask_restful import Resource

class ResourceRegistry(type):

REGISTRY = {}

def __new__(cls, name, bases, attrs):
new_cls = type.__new__(cls, name, bases, attrs)
cls.REGISTRY[new_cls.__name__] = new_cls
return new_cls

@classmethod
def get_registry(cls):
return dict(cls.REGISTRY)


class BaseRegistered(object):
__metaclass__ = ResourceRegistry


class DefaultResource(BaseRegistered, Resource):

@classmethod
def get_resource_name(cls):
s = re.sub('(.)([A-Z][a-z]+)', r'\1-\2', cls.__name__)
return '/' + re.sub('([a-z0-9])([A-Z])', r'\1-\2', s).lower()


When the whole thing is launched I get the following:

TypeError: Error when calling the metaclass bases
metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases


I've tried with layers of proxy classes but the result is still the same. So is there a way to register my resources using this pattern ?

Answer

Your DefaultResource class seems to be inheriting from classes with two different metaclasses: BaseRegistered (with metaclass ResourceRegistry) and Resource (with Flask's MethodViewType metaclass).

This answer would suggest doing something like:

from flask.views import MethodViewType    

class CombinedType(ResourceRegistry, MethodViewType):
    pass

class BaseRegistered(object):
    __metaclass__ = Combinedtype

And then proceed as before.