summaryrefslogtreecommitdiff
path: root/src/zope/interface/tests
diff options
context:
space:
mode:
authorJason Madden <jamadden@gmail.com>2020-04-03 09:55:43 -0500
committerJason Madden <jamadden@gmail.com>2020-04-06 09:14:45 -0500
commit10eadd6305ee57910dbcc508b293f4bf0364fd84 (patch)
tree63a450400cf79c33cb21a1a81d4c00371bf84dcc /src/zope/interface/tests
parent1af83ef9f90aa7a558314892b72eec6d62263981 (diff)
downloadzope-interface-issue3.tar.gz
Let interface 'subclasses' override __adapt__.issue3
Cooperate with InterfaceClass to ensure there is no performance penalty for this. Fixes #3 +-------------------------------------------------------------+----------------+------------------------------+------------------------------+ | Benchmark | bench_master38 | bench_issue3 | bench_issue3_opt | +=============================================================+================+==============================+==============================+ | call interface (provides; deep) | 369 ns | 454 ns: 1.23x slower (+23%) | not significant | +-------------------------------------------------------------+----------------+------------------------------+------------------------------+ | call interface (provides; wide) | 373 ns | 457 ns: 1.22x slower (+22%) | 365 ns: 1.02x faster (-2%) | +-------------------------------------------------------------+----------------+------------------------------+------------------------------+ | call interface (no alternate, no conform, not provided) | 671 ns | 760 ns: 1.13x slower (+13%) | 636 ns: 1.06x faster (-5%) | +-------------------------------------------------------------+----------------+------------------------------+------------------------------+ | call interface (alternate, no conform, not provided) | 395 ns | 494 ns: 1.25x slower (+25%) | not significant | +-------------------------------------------------------------+----------------+------------------------------+------------------------------+ | call interface (no alternate, valid conform, not provided) | 250 ns | not significant | 227 ns: 1.10x faster (-9%) | +-------------------------------------------------------------+----------------+------------------------------+------------------------------+ | call interface (alternate, invalid conform, not provided) | 348 ns | 424 ns: 1.22x slower (+22%) | not significant | +-------------------------------------------------------------+----------------+------------------------------+------------------------------+
Diffstat (limited to 'src/zope/interface/tests')
-rw-r--r--src/zope/interface/tests/test_adapter.py64
-rw-r--r--src/zope/interface/tests/test_declarations.py41
-rw-r--r--src/zope/interface/tests/test_interface.py126
3 files changed, 179 insertions, 52 deletions
diff --git a/src/zope/interface/tests/test_adapter.py b/src/zope/interface/tests/test_adapter.py
index 869df66..8ff96f0 100644
--- a/src/zope/interface/tests/test_adapter.py
+++ b/src/zope/interface/tests/test_adapter.py
@@ -796,12 +796,12 @@ class AdapterLookupBaseTests(unittest.TestCase):
from zope.interface import Interface
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry(IFoo, IBar)
alb = self._makeOne(registry)
self.assertEqual(sorted(alb._extendors.keys()),
sorted([IBar, IFoo, Interface]))
- self.assertEqual(alb._extendors[IFoo], [IFoo])
+ self.assertEqual(alb._extendors[IFoo], [IFoo, IBar])
self.assertEqual(alb._extendors[IBar], [IBar])
self.assertEqual(sorted(alb._extendors[Interface]),
sorted([IFoo, IBar]))
@@ -847,14 +847,14 @@ class AdapterLookupBaseTests(unittest.TestCase):
from zope.interface import Interface
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry()
alb = self._makeOne(registry)
registry._provided = [IFoo, IBar]
alb.init_extendors()
self.assertEqual(sorted(alb._extendors.keys()),
sorted([IBar, IFoo, Interface]))
- self.assertEqual(alb._extendors[IFoo], [IFoo])
+ self.assertEqual(alb._extendors[IFoo], [IFoo, IBar])
self.assertEqual(alb._extendors[IBar], [IBar])
self.assertEqual(sorted(alb._extendors[Interface]),
sorted([IFoo, IBar]))
@@ -863,14 +863,14 @@ class AdapterLookupBaseTests(unittest.TestCase):
from zope.interface import Interface
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry()
alb = self._makeOne(registry)
alb.add_extendor(IFoo)
alb.add_extendor(IBar)
self.assertEqual(sorted(alb._extendors.keys()),
sorted([IBar, IFoo, Interface]))
- self.assertEqual(alb._extendors[IFoo], [IFoo])
+ self.assertEqual(alb._extendors[IFoo], [IFoo, IBar])
self.assertEqual(alb._extendors[IBar], [IBar])
self.assertEqual(sorted(alb._extendors[Interface]),
sorted([IFoo, IBar]))
@@ -879,13 +879,13 @@ class AdapterLookupBaseTests(unittest.TestCase):
from zope.interface import Interface
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry(IFoo, IBar)
alb = self._makeOne(registry)
alb.remove_extendor(IFoo)
self.assertEqual(sorted(alb._extendors.keys()),
sorted([IFoo, IBar, Interface]))
- self.assertEqual(alb._extendors[IFoo], [])
+ self.assertEqual(alb._extendors[IFoo], [IBar])
self.assertEqual(alb._extendors[IBar], [IBar])
self.assertEqual(sorted(alb._extendors[Interface]),
sorted([IBar]))
@@ -895,7 +895,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_lookup_empty_ro(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry()
alb = self._makeOne(registry)
result = alb._uncached_lookup((IFoo,), IBar)
@@ -906,7 +906,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_lookup_order_miss(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
registry.ro.append(subr)
@@ -917,7 +917,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_lookup_extendors_miss(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry()
subr = self._makeSubregistry()
subr._adapters = [{}, {}] #utilities, single adapters
@@ -930,7 +930,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_lookup_components_miss_wrong_iface(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
IQux = InterfaceClass('IQux')
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
@@ -949,7 +949,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_lookup_components_miss_wrong_name(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
@@ -968,7 +968,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_lookup_simple_hit(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
_expected = object()
@@ -985,7 +985,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_lookup_repeated_hit(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
_expected = object()
@@ -1005,7 +1005,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
from zope.interface.declarations import implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
@implementer(IFoo)
class Foo(object):
pass
@@ -1051,7 +1051,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
from zope.interface.declarations import implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
@implementer(IFoo)
class Foo(object):
pass
@@ -1080,7 +1080,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
from zope.interface.declarations import implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
@implementer(IFoo)
class Foo(object):
pass
@@ -1131,7 +1131,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_lookupAll_empty_ro(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry()
alb = self._makeOne(registry)
result = alb._uncached_lookupAll((IFoo,), IBar)
@@ -1142,7 +1142,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_lookupAll_order_miss(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
registry.ro.append(subr)
@@ -1154,7 +1154,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_lookupAll_extendors_miss(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry()
subr = self._makeSubregistry()
subr._adapters = [{}, {}] #utilities, single adapters
@@ -1167,7 +1167,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_lookupAll_components_miss(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
IQux = InterfaceClass('IQux')
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
@@ -1185,7 +1185,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_lookupAll_simple_hit(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
_expected = object()
@@ -1203,7 +1203,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test_names(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
_expected = object()
@@ -1222,7 +1222,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_subscriptions_empty_ro(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry()
alb = self._makeOne(registry)
result = alb._uncached_subscriptions((IFoo,), IBar)
@@ -1233,7 +1233,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_subscriptions_order_miss(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
registry.ro.append(subr)
@@ -1245,7 +1245,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_subscriptions_extendors_miss(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry()
subr = self._makeSubregistry()
subr._subscribers = [{}, {}] #utilities, single adapters
@@ -1258,7 +1258,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_subscriptions_components_miss_wrong_iface(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
IQux = InterfaceClass('IQux')
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
@@ -1276,7 +1276,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_subscriptions_components_miss_wrong_name(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
wrongname = object()
@@ -1293,7 +1293,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
def test__uncached_subscriptions_simple_hit(self):
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
registry = self._makeRegistry(IFoo, IBar)
subr = self._makeSubregistry()
class Foo(object):
@@ -1314,7 +1314,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
from zope.interface.declarations import implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
@implementer(IFoo)
class Foo(object):
pass
@@ -1343,7 +1343,7 @@ class AdapterLookupBaseTests(unittest.TestCase):
from zope.interface.declarations import implementer
from zope.interface.interface import InterfaceClass
IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar', IFoo)
+ IBar = InterfaceClass('IBar', (IFoo,))
@implementer(IFoo)
class Foo(object):
pass
diff --git a/src/zope/interface/tests/test_declarations.py b/src/zope/interface/tests/test_declarations.py
index 5d7272a..83815d7 100644
--- a/src/zope/interface/tests/test_declarations.py
+++ b/src/zope/interface/tests/test_declarations.py
@@ -864,25 +864,30 @@ class Test_classImplements(unittest.TestCase):
def test_w_existing_Implements_w_bases(self):
from zope.interface.declarations import Implements
from zope.interface.interface import InterfaceClass
- IFoo = InterfaceClass('IFoo')
- IBar = InterfaceClass('IBar')
- IBaz = InterfaceClass('IBaz', IFoo)
- b_impl = Implements(IBaz)
- impl = Implements(IFoo)
- impl.declared = (IFoo,)
- class Base1(object):
- __implemented__ = b_impl
- class Base2(object):
- __implemented__ = b_impl
- class Foo(Base1, Base2):
- __implemented__ = impl
- impl.inherit = Foo
- self._callFUT(Foo, IBar)
+ IRoot = InterfaceClass('IRoot')
+ ISecondRoot = InterfaceClass('ISecondRoot')
+ IExtendsRoot = InterfaceClass('IExtendsRoot', (IRoot,))
+
+ impl_root = Implements.named('Root', IRoot)
+ impl_root.declared = (IRoot,)
+
+ class Root1(object):
+ __implemented__ = impl_root
+ class Root2(object):
+ __implemented__ = impl_root
+
+ impl_extends_root = Implements.named('ExtendsRoot1', IExtendsRoot)
+ impl_extends_root.declared = (IExtendsRoot,)
+ class ExtendsRoot(Root1, Root2):
+ __implemented__ = impl_extends_root
+ impl_extends_root.inherit = ExtendsRoot
+
+ self._callFUT(ExtendsRoot, ISecondRoot)
# Same spec, now different values
- self.assertTrue(Foo.__implemented__ is impl)
- self.assertEqual(impl.inherit, Foo)
- self.assertEqual(impl.declared, (IFoo, IBar,))
- self.assertEqual(impl.__bases__, (IFoo, IBar, b_impl))
+ self.assertIs(ExtendsRoot.__implemented__, impl_extends_root)
+ self.assertEqual(impl_extends_root.inherit, ExtendsRoot)
+ self.assertEqual(impl_extends_root.declared, (IExtendsRoot, ISecondRoot,))
+ self.assertEqual(impl_extends_root.__bases__, (IExtendsRoot, ISecondRoot, impl_root))
class Test__implements_advice(unittest.TestCase):
diff --git a/src/zope/interface/tests/test_interface.py b/src/zope/interface/tests/test_interface.py
index 2100340..4bbed1a 100644
--- a/src/zope/interface/tests/test_interface.py
+++ b/src/zope/interface/tests/test_interface.py
@@ -1318,9 +1318,9 @@ class InterfaceTests(unittest.TestCase):
new = Interface.__class__
FunInterface = new('FunInterface')
- BarInterface = new('BarInterface', [FunInterface])
+ BarInterface = new('BarInterface', (FunInterface,))
BobInterface = new('BobInterface')
- BazInterface = new('BazInterface', [BobInterface, BarInterface])
+ BazInterface = new('BazInterface', (BobInterface, BarInterface,))
self.assertTrue(BazInterface.extends(BobInterface))
self.assertTrue(BazInterface.extends(BarInterface))
@@ -2161,6 +2161,128 @@ class InterfaceTests(unittest.TestCase):
finally:
adapter_hooks[:] = old_adapter_hooks
+ def test___call___w_overridden_adapt(self):
+ from zope.interface import Interface
+ from zope.interface import interfacemethod
+ from zope.interface import implementer
+
+ class I(Interface):
+
+ @interfacemethod
+ def __adapt__(self, obj):
+ return 42
+
+ @implementer(I)
+ class O(object):
+ pass
+
+ self.assertEqual(42, I(object()))
+ # __adapt__ supercedes providedBy() if defined.
+ self.assertEqual(42, I(O()))
+
+ def test___call___w_overridden_adapt_call_super(self):
+ import sys
+ from zope.interface import Interface
+ from zope.interface import interfacemethod
+ from zope.interface import implementer
+
+ class I(Interface):
+
+ @interfacemethod
+ def __adapt__(self, obj):
+ if not self.providedBy(obj):
+ return 42
+ if sys.version_info[:2] > (3, 5):
+ # Python 3.5 raises 'RuntimeError: super() __class__ is not a type'
+ return super().__adapt__(obj)
+
+ return super(type(I), self).__adapt__(obj)
+
+ @implementer(I)
+ class O(object):
+ pass
+
+ self.assertEqual(42, I(object()))
+ o = O()
+ self.assertIs(o, I(o))
+
+ def test___adapt___as_method_and_implementation(self):
+ from zope.interface import Interface
+ from zope.interface import interfacemethod
+
+ class I(Interface):
+ @interfacemethod
+ def __adapt__(self, obj):
+ return 42
+
+ def __adapt__(to_adapt):
+ "This is a protocol"
+
+ self.assertEqual(42, I(object()))
+ self.assertEqual(I['__adapt__'].getSignatureString(), '(to_adapt)')
+
+ def test___adapt__inheritance_and_type(self):
+ from zope.interface import Interface
+ from zope.interface import interfacemethod
+
+ class IRoot(Interface):
+ """Root"""
+
+ class IWithAdapt(IRoot):
+ @interfacemethod
+ def __adapt__(self, obj):
+ return 42
+
+ class IOther(IRoot):
+ """Second branch"""
+
+ class IUnrelated(Interface):
+ """Unrelated"""
+
+ class IDerivedAdapt(IUnrelated, IWithAdapt, IOther):
+ """Inherits an adapt"""
+ # Order of "inheritance" matters here.
+
+ class IDerived2Adapt(IDerivedAdapt):
+ """Overrides an inherited custom adapt."""
+ @interfacemethod
+ def __adapt__(self, obj):
+ return 24
+
+ self.assertEqual(42, IDerivedAdapt(object()))
+ for iface in IRoot, IWithAdapt, IOther, IUnrelated, IDerivedAdapt:
+ self.assertEqual(__name__, iface.__module__)
+
+ for iface in IRoot, IOther, IUnrelated:
+ self.assertEqual(type(IRoot), type(Interface))
+
+ # But things that implemented __adapt__ got a new type
+ self.assertNotEqual(type(Interface), type(IWithAdapt))
+ self.assertEqual(type(IWithAdapt), type(IDerivedAdapt))
+ self.assertIsInstance(IWithAdapt, type(Interface))
+
+ self.assertEqual(24, IDerived2Adapt(object()))
+ self.assertNotEqual(type(IDerived2Adapt), type(IDerivedAdapt))
+ self.assertIsInstance(IDerived2Adapt, type(IDerivedAdapt))
+
+ def test_interfacemethod_is_general(self):
+ from zope.interface import Interface
+ from zope.interface import interfacemethod
+
+ class I(Interface):
+
+ @interfacemethod
+ def __call__(self, obj):
+ """Replace an existing method"""
+ return 42
+
+ @interfacemethod
+ def this_is_new(self):
+ return 42
+
+ self.assertEqual(I(self), 42)
+ self.assertEqual(I.this_is_new(), 42)
+
class AttributeTests(ElementTests):