python - Triple inheritance causes metaclass conflict... Sometimes -
looks stumbled upon metaclass hell when didn't wanted it.
i'm writing app in qt4 using pyside. want separate event-driven part ui definition, generated qt designer files. hence create "controller" classes, ease life multiple-inherit them anyways. example:
class basecontroller(qobject): def setupevents(self, parent): self.window = parent class maincontroller(basecontroller): pass class mainwindow(qmainwindow, ui_mainwindow, maincontroller): def __init__(self, parent=none): super(mainwindow, self).__init__(parent) self.setupui(self) self.setupevents(self)
this works expected. has inheritance (qdialog
, ui_dialog
, basecontroller
). when subclass basecontroller
, try inherit said subclass (in place of basecontroller
), receive error:
typeerror: error when calling metaclass bases metaclass conflict: metaclass of derived class must (non-strict) subclass of metaclasses of bases
clarification: both qmainwindow
, qdialog
inherit qobject
. basecontroller
must inherit because of qt event system peculiarities. ui_ classes inherit simple python object class. searched solutions, of them involve cases of intentionally using metaclasses. must doing terribly wrong.
edit: description may clearer adding graphs.
working example:
qobject | \___________________ | object | qmainwindow | basecontroller | /---ui_mainwindow | | | maincontroller mainwindow-----------------/
another working example:
qobject | \___________________ | object | qdialog | basecontroller | /---ui_otherwindow | | | | otherwindow----------------/
not working example:
qobject | \___________________ | object | qdialog | basecontroller | /---ui_otherwindow | | | othercontroller otherwindow----------------/
the error message indicates have 2 conflicting metaclasses somewhere in hierarchy. need examine each of classes , qt classes figure out conflict is.
here's simple example code sets same situation:
class metaa(type): pass class metab(type): pass class a: __metaclass__ = metaa class b: __metaclass__ = metab
we can't subclass both of classes directly, because python wouldn't know metaclass use:
>>> class broken(a, b): pass ... traceback (most recent call last): file "<stdin>", line 1, in <module> typeerror: error when calling metaclass bases metaclass conflict: metaclass of derived class must (non-strict) subclass of metaclasses of bases
what error trying tell need resolve conflict between 2 metaclasses introducing third metaclass subclass of metaclasses base classes.
i'm not sure that's clearer error message itself, basically, fix doing this:
class metaab(metaa, metab): pass class fixed(a, b): __metaclass__ = metaab
this code compiles , runs correctly. of course, in real situation, conflict-resolving metaclass have decide of parent metaclass behaviors adopt, you'll have figure out application's requirements.
bear in mind inherited class gets one of 2 metaclass.__init__
methods, work, in lot of cases, going have add __init__
calls both in way helps them along.
Comments
Post a Comment