Special case the base Interface in @implementer/classImplements to skip the redundancy detection for the sake of plone.app.caching.
This commit is contained in:
parent
46781f87cc
commit
4cb3e63d3f
|
@ -518,7 +518,7 @@ declarations. Here's a silly example:
|
|||
... zope.interface.implementedBy(Foo),
|
||||
... ISpecial,
|
||||
... )
|
||||
... class Special2(Foo):
|
||||
... class Special2(object):
|
||||
... reason = 'I just am'
|
||||
... def brag(self):
|
||||
... return "I'm special because %s" % self.reason
|
||||
|
|
|
@ -33,6 +33,7 @@ from types import ModuleType
|
|||
import weakref
|
||||
|
||||
from zope.interface.advice import addClassAdvisor
|
||||
from zope.interface.interface import Interface
|
||||
from zope.interface.interface import InterfaceClass
|
||||
from zope.interface.interface import SpecificationBase
|
||||
from zope.interface.interface import Specification
|
||||
|
@ -470,9 +471,6 @@ def classImplements(cls, *interfaces):
|
|||
# order, while still allowing for BWC (in the past, we always
|
||||
# appended)
|
||||
for iface in interfaces:
|
||||
if spec.isOrExtends(iface):
|
||||
continue
|
||||
|
||||
for b in spec.declared:
|
||||
if iface.extends(b):
|
||||
before.append(iface)
|
||||
|
@ -493,18 +491,34 @@ def classImplementsFirst(cls, iface):
|
|||
.. versionadded:: 5.0.0
|
||||
"""
|
||||
spec = implementedBy(cls)
|
||||
if not spec.isOrExtends(iface):
|
||||
_classImplements_ordered(spec, (iface,), ())
|
||||
_classImplements_ordered(spec, (iface,), ())
|
||||
|
||||
|
||||
def _classImplements_ordered(spec, before=(), after=()):
|
||||
# Elide everything already inherited.
|
||||
# Except, if it is the root, and we don't already declare anything else
|
||||
# that would imply it, allow the root through. (TODO: When we disallow non-strict
|
||||
# IRO, this part of the check can be removed because it's not possible to re-declare
|
||||
# like that.)
|
||||
before = [
|
||||
x
|
||||
for x in before
|
||||
if not spec.isOrExtends(x) or (x is Interface and not spec.declared)
|
||||
]
|
||||
after = [
|
||||
x
|
||||
for x in after
|
||||
if not spec.isOrExtends(x) or (x is Interface and not spec.declared)
|
||||
]
|
||||
|
||||
# eliminate duplicates
|
||||
new_declared = []
|
||||
seen = set()
|
||||
for b in before + spec.declared + after:
|
||||
if b not in seen:
|
||||
new_declared.append(b)
|
||||
seen.add(b)
|
||||
for l in before, spec.declared, after:
|
||||
for b in l:
|
||||
if b not in seen:
|
||||
new_declared.append(b)
|
||||
seen.add(b)
|
||||
|
||||
spec.declared = tuple(new_declared)
|
||||
|
||||
|
|
|
@ -890,6 +890,25 @@ class Test_classImplements(unittest.TestCase):
|
|||
pass
|
||||
self.__check_implementer_redundant(Foo)
|
||||
|
||||
def test_redundant_implementer_Interface(self):
|
||||
from zope.interface import Interface
|
||||
from zope.interface import implementedBy
|
||||
from zope.interface import ro
|
||||
from zope.interface.tests.test_ro import C3Setting
|
||||
|
||||
class Foo(object):
|
||||
pass
|
||||
|
||||
with C3Setting(ro.C3.STRICT_IRO, False):
|
||||
self._callFUT(Foo, Interface)
|
||||
self.assertEqual(list(implementedBy(Foo)), [Interface])
|
||||
|
||||
class Baz(Foo):
|
||||
pass
|
||||
|
||||
self._callFUT(Baz, Interface)
|
||||
self.assertEqual(list(implementedBy(Baz)), [Interface])
|
||||
|
||||
def _order_for_two(self, applied_first, applied_second):
|
||||
return (applied_first, applied_second)
|
||||
|
||||
|
|
|
@ -873,7 +873,7 @@ class ComponentsTests(unittest.TestCase):
|
|||
ibar = IFoo('IBar')
|
||||
_info = u'info'
|
||||
_name = u'name'
|
||||
_to_reg = object()
|
||||
|
||||
class _Factory(object):
|
||||
pass
|
||||
|
||||
|
|
Loading…
Reference in New Issue