Tales Pádua
Tales Pádua

Reputation: 1461

Cannot resolve conflicts with metaclasses of child classes

I need to have a static instance of a class of the same class and one solution I thought was using metaclasses.

I have the following word.py:

from .token import Token
from .tag import Tag

class Token:
    def __init__(self, tag_id):
        self.tag = tag_id

    def __str__(self):
        return str(self.tag)

class MetaWord(type):

    def __init__(cls, clsname, superclasses, attributedict):
        cls.and_ = cls('&&', Tag.AND)
        cls.or_ = cls("||", Tag.OR)
        cls.eq = cls("==", Tag.EQ)
        cls.ne = cls("!=", Tag.NE)     


class Word(Token, metaclass=MetaWord):

    def __init__(self, lexeme, tag):
        super(self.__class__, self).__init__(tag)
        self.lexeme = lexeme

and another file type.py file, with a Type class that inherits from Word:

from lexer.word import Word
from lexer.tag import Tag


class MetaType(type):
    def __init__(cls, clsname, superclasses, attributedict):
        cls.int_ = cls('int', Tag.BASIC, 4)
        cls.float_ = cls('float', Tag.BASIC, 8)
        cls.char_ = cls('char', Tag.BASIC, 1)
        cls.bool_ = cls('bool', Tag.BASIC, 1)


class Type(Word, metaclass=MetaType):
    def __init__(self, word, tag_id, w):
        super(self.__class__, self).__init__(word, tag_id)
        self.width = w

The problem I am having is that everytime I import Type it gives me the error:

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

I have read some topics on this issue, but haven't figured out how to fix the conflict between the metaclasses

Upvotes: 0

Views: 51

Answers (1)

Milkmanatee
Milkmanatee

Reputation: 66

If you want the code to work in the way you have it organized, you will have to make MetaType a subclass of MetaWord. When Python tries to instantiate your Type class it looks at the MRO and sees that Type has metaclass MetaType and base class Word, but class Word has metaclass MetaWord. This raises a conflict because there is no way for Python to resolve the fact that Type seems to have two metaclasses, MetaWord and MetaType, which are unrelated to each other.

The following code is a minimal reproduction of what I think your problem is:

class Meta1(type):
    pass

class Class1(metaclass=Meta1):
    pass

class Meta2(type):
    pass

class Class2(Class1, metaclass=Meta2):
    pass

This code will give the same sort of error as yours. Changing the definition of Meta2 to:

class Meta2(Meta1):
    pass

resolves the issue.

Upvotes: 2

Related Questions