Index: src/zope/interface/interface.py =================================================================== --- src/zope/interface/interface.py (revision 121495) +++ src/zope/interface/interface.py (working copy) @@ -433,6 +433,22 @@ # #implements(IInterface) + def __new__(cls, name, bases=(), attrs=None, __doc__=None, + __module__=None): + # Resolve metaclass in the same way as ``type`` + for base in bases: + meta = type(base) + if issubclass(cls, meta): + continue + if issubclass(meta, cls): + cls = meta + continue + raise TypeError( + "Error when calling the metaclass bases\n " + "metaclass conflict: the metaclass of a derived class must be " + "a (non-strict) subclass of the metaclasses of all its bases") + return object.__new__(cls) + def __init__(self, name, bases=(), attrs=None, __doc__=None, __module__=None): Index: src/zope/interface/tests/test_interface.py =================================================================== --- src/zope/interface/tests/test_interface.py (revision 121495) +++ src/zope/interface/tests/test_interface.py (working copy) @@ -413,7 +413,33 @@ True """ +def test_subclassing_interfaceclass(): + """ +As ``InterfaceClass`` does not derive from ``type`` the normal python rules +for determining the metaclass of a class from it's bases are not applied and +the. In order to support specialisation, ``InterfaceClass`` resolves the +metclass itself in ``__new__``. + >>> from zope.interface import Interface + >>> from zope.interface.interface import InterfaceClass + >>> class SpecialClass(InterfaceClass): pass + ... + >>> Special = SpecialClass('Special') + >>> class I(Interface): + ... pass + + >>> class S(Special): + ... pass + + >>> class Combined(I, S): + ... pass + + >>> isinstance(Combined, SpecialClass) + True + """ + + + def test_suite(): suite = unittest.makeSuite(InterfaceTests) suite.addTest(doctest.DocTestSuite("zope.interface.interface"))