summaryrefslogtreecommitdiff
path: root/src/zope/interface/common/__init__.py
diff options
context:
space:
mode:
authorJason Madden <jamadden@gmail.com>2020-03-05 14:38:39 -0600
committerJason Madden <jamadden@gmail.com>2020-03-15 09:56:14 -0500
commit024f6432270afd021da2d9fff5c3f496f788e54d (patch)
treed9732ae94de818f2e3ea8ac144e1b932cbefa133 /src/zope/interface/common/__init__.py
parent354faccebd5b612a2ac8e081a7e5d2f7fb1089c1 (diff)
downloadzope-interface-issue21.tar.gz
Use C3 (mostly) to compute IRO.issue21
Fixes #21 The 'mostly' is because interfaces are used in cases that C3 forbids; when there's a conflict, we fallback to the legacy algorithm. It turns out there are few conflicts (13K out of 149K total orderings in Plone). I hoped the fix for #8 might shake out automatically, but it didn't. Optimize the extremely common case of a __bases__ of length one. In the benchmark, 4/5 of the interfaces and related objects have a base of length one. Fix the bad IROs in the bundled ABC interfaces, and implement a way to get warnings or errors. In running plone/buildout.coredev and tracking the RO requests, the stats for equal, not equal, and inconsistent-so-fallback, I got {'ros': 148868, 'eq': 138461, 'ne': 10407, 'inconsistent': 12934} Add the interface module to the Attribute str. This was extremely helpful tracking down the Plone problem; IDate is defined in multiple modules.
Diffstat (limited to 'src/zope/interface/common/__init__.py')
-rw-r--r--src/zope/interface/common/__init__.py16
1 files changed, 10 insertions, 6 deletions
diff --git a/src/zope/interface/common/__init__.py b/src/zope/interface/common/__init__.py
index acbc581..a8bedf0 100644
--- a/src/zope/interface/common/__init__.py
+++ b/src/zope/interface/common/__init__.py
@@ -121,19 +121,20 @@ class ABCInterfaceClass(InterfaceClass):
# go ahead and give us a name to ease debugging.
self.__name__ = name
extra_classes = attrs.pop('extra_classes', ())
+ ignored_classes = attrs.pop('ignored_classes', ())
if 'abc' not in attrs:
# Something like ``IList(ISequence)``: We're extending
# abc interfaces but not an ABC interface ourself.
- self.__class__ = InterfaceClass
InterfaceClass.__init__(self, name, bases, attrs)
- for cls in extra_classes:
- classImplements(cls, self)
+ ABCInterfaceClass.__register_classes(self, extra_classes, ignored_classes)
+ self.__class__ = InterfaceClass
return
based_on = attrs.pop('abc')
self.__abc = based_on
self.__extra_classes = tuple(extra_classes)
+ self.__ignored_classes = tuple(ignored_classes)
assert name[1:] == based_on.__name__, (name, based_on)
methods = {
@@ -216,11 +217,14 @@ class ABCInterfaceClass(InterfaceClass):
method.positional = method.positional[1:]
return method
- def __register_classes(self):
+ def __register_classes(self, conformers=None, ignored_classes=None):
# Make the concrete classes already present in our ABC's registry
# declare that they implement this interface.
-
- for cls in self.getRegisteredConformers():
+ conformers = conformers if conformers is not None else self.getRegisteredConformers()
+ ignored = ignored_classes if ignored_classes is not None else self.__ignored_classes
+ for cls in conformers:
+ if cls in ignored:
+ continue
classImplements(cls, self)
def getABC(self):