Metaclass resolution for InterfaceClass
Laurence Rowe <[email protected]>
| Newsgroups | gmane.comp.web.zope.devel |
|---|---|
| Message-ID | <[email protected]> |
While experimenting with my InterfaceClass subclass I noticed that it was only being used when it was specified as the first of the bases. I believe this is because InterfaceClass is not a subclass of ``type``, so the normal metaclass derivation logic is not applied. The attached patch implements that logic in InterfaceClass.__new__, picking from the base metaclasses that metaclass which subclasses all other base metaclasses. Laurence _______________________________________________ Zope-Dev maillist - [email protected] https://mail.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - https://mail.zope.org/mailman/listinfo/zope-announce https://mail.zope.org/mailman/listinfo/zope )
metaclass_resolution.diff
(application/octet-stream, 2.2 KB)
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"))