aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/zope.interface/py2/zope/interface/tests
diff options
context:
space:
mode:
authormaxim-yurchuk <maxim-yurchuk@yandex-team.com>2024-10-09 12:29:46 +0300
committermaxim-yurchuk <maxim-yurchuk@yandex-team.com>2024-10-09 13:14:22 +0300
commit9731d8a4bb7ee2cc8554eaf133bb85498a4c7d80 (patch)
treea8fb3181d5947c0d78cf402aa56e686130179049 /contrib/python/zope.interface/py2/zope/interface/tests
parenta44b779cd359f06c3ebbef4ec98c6b38609d9d85 (diff)
downloadydb-9731d8a4bb7ee2cc8554eaf133bb85498a4c7d80.tar.gz
publishFullContrib: true for ydb
<HIDDEN_URL> commit_hash:c82a80ac4594723cebf2c7387dec9c60217f603e
Diffstat (limited to 'contrib/python/zope.interface/py2/zope/interface/tests')
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/__init__.py115
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/advisory_testing.py42
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/dummy.py23
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/idummy.py23
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/m1.py21
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/odd.py128
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/test_adapter.py2109
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/test_advice.py355
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/test_compile_flags.py29
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/test_declarations.py2678
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/test_document.py505
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/test_element.py31
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/test_exceptions.py184
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/test_interface.py2660
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/test_interfaces.py128
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/test_odd_declarations.py268
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/test_registry.py3057
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/test_ro.py235
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/test_sorting.py64
-rw-r--r--contrib/python/zope.interface/py2/zope/interface/tests/test_verify.py656
20 files changed, 13311 insertions, 0 deletions
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/__init__.py b/contrib/python/zope.interface/py2/zope/interface/tests/__init__.py
new file mode 100644
index 0000000000..edbd035a89
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/__init__.py
@@ -0,0 +1,115 @@
+from zope.interface._compat import _should_attempt_c_optimizations
+
+
+class OptimizationTestMixin(object):
+ """
+ Helper for testing that C optimizations are used
+ when appropriate.
+ """
+
+ def _getTargetClass(self):
+ """
+ Define this to return the implementation in use,
+ without the 'Py' or 'Fallback' suffix.
+ """
+ raise NotImplementedError
+
+ def _getFallbackClass(self):
+ """
+ Define this to return the fallback Python implementation.
+ """
+ # Is there an algorithmic way to do this? The C
+ # objects all come from the same module so I don't see how we can
+ # get the Python object from that.
+ raise NotImplementedError
+
+ def _test_optimizations(self):
+ used = self._getTargetClass()
+ fallback = self._getFallbackClass()
+
+ if _should_attempt_c_optimizations():
+ self.assertIsNot(used, fallback)
+ else:
+ self.assertIs(used, fallback)
+
+
+class MissingSomeAttrs(object):
+ """
+ Helper for tests that raises a specific exception
+ for attributes that are missing. This is usually not
+ an AttributeError, and this object is used to test that
+ those errors are not improperly caught and treated like
+ an AttributeError.
+ """
+
+ def __init__(self, exc_kind, **other_attrs):
+ self.__exc_kind = exc_kind
+ d = object.__getattribute__(self, '__dict__')
+ d.update(other_attrs)
+
+ def __getattribute__(self, name):
+ # Note that we ignore objects found in the class dictionary.
+ d = object.__getattribute__(self, '__dict__')
+ try:
+ return d[name]
+ except KeyError:
+ raise d['_MissingSomeAttrs__exc_kind'](name)
+
+ EXCEPTION_CLASSES = (
+ TypeError,
+ RuntimeError,
+ BaseException,
+ ValueError,
+ )
+
+ @classmethod
+ def test_raises(cls, unittest, test_func, expected_missing, **other_attrs):
+ """
+ Loop through various exceptions, calling *test_func* inside a ``assertRaises`` block.
+
+ :param test_func: A callable of one argument, the instance of this
+ class.
+ :param str expected_missing: The attribute that should fail with the exception.
+ This is used to ensure that we're testing the path we think we are.
+ :param other_attrs: Attributes that should be provided on the test object.
+ Must not contain *expected_missing*.
+ """
+ assert isinstance(expected_missing, str)
+ assert expected_missing not in other_attrs
+ for exc in cls.EXCEPTION_CLASSES:
+ ob = cls(exc, **other_attrs)
+ with unittest.assertRaises(exc) as ex:
+ test_func(ob)
+
+ unittest.assertEqual(ex.exception.args[0], expected_missing)
+
+ # Now test that the AttributeError for that expected_missing is *not* raised.
+ ob = cls(AttributeError, **other_attrs)
+ try:
+ test_func(ob)
+ except AttributeError as e:
+ unittest.assertNotIn(expected_missing, str(e))
+ except Exception: # pylint:disable=broad-except
+ pass
+
+# Be sure cleanup functionality is available; classes that use the adapter hook
+# need to be sure to subclass ``CleanUp``.
+#
+# If zope.component is installed and imported when we run our tests
+# (import chain:
+# zope.testrunner->zope.security->zope.location->zope.component.api)
+# it adds an adapter hook that uses its global site manager. That can cause
+# leakage from one test to another unless its cleanup hooks are run. The symptoms can
+# be odd, especially if one test used C objects and the next used the Python
+# implementation. (For example, you can get strange TypeErrors or find inexplicable
+# comparisons being done.)
+try:
+ from zope.testing import cleanup
+except ImportError:
+ class CleanUp(object):
+ def cleanUp(self):
+ pass
+
+ setUp = tearDown = cleanUp
+else:
+ CleanUp = cleanup.CleanUp
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/advisory_testing.py b/contrib/python/zope.interface/py2/zope/interface/tests/advisory_testing.py
new file mode 100644
index 0000000000..b159e937dc
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/advisory_testing.py
@@ -0,0 +1,42 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import sys
+
+from zope.interface.advice import addClassAdvisor
+from zope.interface.advice import getFrameInfo
+
+my_globals = globals()
+
+def ping(log, value):
+
+ def pong(klass):
+ log.append((value,klass))
+ return [klass]
+
+ addClassAdvisor(pong)
+
+try:
+ from types import ClassType
+
+ class ClassicClass:
+ __metaclass__ = ClassType
+ classLevelFrameInfo = getFrameInfo(sys._getframe())
+except ImportError:
+ ClassicClass = None
+
+class NewStyleClass:
+ __metaclass__ = type
+ classLevelFrameInfo = getFrameInfo(sys._getframe())
+
+moduleLevelFrameInfo = getFrameInfo(sys._getframe())
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/dummy.py b/contrib/python/zope.interface/py2/zope/interface/tests/dummy.py
new file mode 100644
index 0000000000..2aedf2c50d
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/dummy.py
@@ -0,0 +1,23 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Dummy Module
+"""
+from zope.interface import moduleProvides
+from .idummy import IDummyModule
+
+moduleProvides(IDummyModule)
+
+def bar(baz):
+ # Note: no 'self', because the module provides the interface directly.
+ raise NotImplementedError()
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/idummy.py b/contrib/python/zope.interface/py2/zope/interface/tests/idummy.py
new file mode 100644
index 0000000000..1e34fe0f14
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/idummy.py
@@ -0,0 +1,23 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" Interface describing API of zope.interface.tests.dummy test module
+"""
+from zope.interface import Interface
+
+class IDummyModule(Interface):
+ """ Dummy interface for unit tests.
+ """
+ def bar(baz):
+ """ Just a note.
+ """
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/m1.py b/contrib/python/zope.interface/py2/zope/interface/tests/m1.py
new file mode 100644
index 0000000000..d311fb40e0
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/m1.py
@@ -0,0 +1,21 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Test module that declares an interface
+"""
+from zope.interface import Interface, moduleProvides
+
+class I1(Interface): pass
+class I2(Interface): pass
+
+moduleProvides(I1, I2)
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/odd.py b/contrib/python/zope.interface/py2/zope/interface/tests/odd.py
new file mode 100644
index 0000000000..74c6158438
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/odd.py
@@ -0,0 +1,128 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Odd meta class that doesn't subclass type.
+
+This is used for testing support for ExtensionClass in new interfaces.
+
+ >>> class A(object):
+ ... __metaclass__ = MetaClass
+ ... a = 1
+ ...
+ >>> A.__name__
+ 'A'
+ >>> A.__bases__ == (object,)
+ True
+ >>> class B(object):
+ ... __metaclass__ = MetaClass
+ ... b = 1
+ ...
+ >>> class C(A, B): pass
+ ...
+ >>> C.__name__
+ 'C'
+ >>> int(C.__bases__ == (A, B))
+ 1
+ >>> a = A()
+ >>> aa = A()
+ >>> a.a
+ 1
+ >>> aa.a
+ 1
+ >>> aa.a = 2
+ >>> a.a
+ 1
+ >>> aa.a
+ 2
+ >>> c = C()
+ >>> c.a
+ 1
+ >>> c.b
+ 1
+ >>> c.b = 2
+ >>> c.b
+ 2
+ >>> C.c = 1
+ >>> c.c
+ 1
+ >>> import sys
+ >>> if sys.version[0] == '2': # This test only makes sense under Python 2.x
+ ... from types import ClassType
+ ... assert not isinstance(C, (type, ClassType))
+
+ >>> int(C.__class__.__class__ is C.__class__)
+ 1
+"""
+
+# class OddClass is an odd meta class
+
+class MetaMetaClass(type):
+
+ def __getattribute__(cls, name):
+ if name == '__class__':
+ return cls
+ # Under Python 3.6, __prepare__ gets requested
+ return type.__getattribute__(cls, name)
+
+
+class MetaClass(object):
+ """Odd classes
+ """
+
+ def __init__(self, name, bases, dict):
+ self.__name__ = name
+ self.__bases__ = bases
+ self.__dict__.update(dict)
+
+ def __call__(self):
+ return OddInstance(self)
+
+ def __getattr__(self, name):
+ for b in self.__bases__:
+ v = getattr(b, name, self)
+ if v is not self:
+ return v
+ raise AttributeError(name)
+
+ def __repr__(self): # pragma: no cover
+ return "<odd class %s at %s>" % (self.__name__, hex(id(self)))
+
+
+MetaClass = MetaMetaClass('MetaClass',
+ MetaClass.__bases__,
+ {k: v for k, v in MetaClass.__dict__.items()
+ if k not in ('__dict__',)})
+
+class OddInstance(object):
+
+ def __init__(self, cls):
+ self.__dict__['__class__'] = cls
+
+ def __getattribute__(self, name):
+ dict = object.__getattribute__(self, '__dict__')
+ if name == '__dict__':
+ return dict
+ v = dict.get(name, self)
+ if v is not self:
+ return v
+ return getattr(dict['__class__'], name)
+
+ def __setattr__(self, name, v):
+ self.__dict__[name] = v
+
+ def __delattr__(self, name):
+ raise NotImplementedError()
+
+ def __repr__(self): # pragma: no cover
+ return "<odd %s instance at %s>" % (
+ self.__class__.__name__, hex(id(self)))
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/test_adapter.py b/contrib/python/zope.interface/py2/zope/interface/tests/test_adapter.py
new file mode 100644
index 0000000000..3a2df58326
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/test_adapter.py
@@ -0,0 +1,2109 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Adapter registry tests
+"""
+import unittest
+
+from __tests__.tests import OptimizationTestMixin
+
+# pylint:disable=inherit-non-class,protected-access,too-many-lines
+# pylint:disable=attribute-defined-outside-init,blacklisted-name
+
+def _makeInterfaces():
+ from zope.interface import Interface
+
+ class IB0(Interface):
+ pass
+ class IB1(IB0):
+ pass
+ class IB2(IB0):
+ pass
+ class IB3(IB2, IB1):
+ pass
+ class IB4(IB1, IB2):
+ pass
+
+ class IF0(Interface):
+ pass
+ class IF1(IF0):
+ pass
+
+ class IR0(Interface):
+ pass
+ class IR1(IR0):
+ pass
+
+ return IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1
+
+
+# Custom types to use as part of the AdapterRegistry data structures.
+# Our custom types do strict type checking to make sure
+# types propagate through the data tree as expected.
+class CustomDataTypeBase(object):
+ _data = None
+ def __getitem__(self, name):
+ return self._data[name]
+
+ def __setitem__(self, name, value):
+ self._data[name] = value
+
+ def __delitem__(self, name):
+ del self._data[name]
+
+ def __len__(self):
+ return len(self._data)
+
+ def __contains__(self, name):
+ return name in self._data
+
+ def __eq__(self, other):
+ if other is self:
+ return True
+ # pylint:disable=unidiomatic-typecheck
+ if type(other) != type(self):
+ return False
+ return other._data == self._data
+
+ def __repr__(self):
+ return repr(self._data)
+
+class CustomMapping(CustomDataTypeBase):
+ def __init__(self, other=None):
+ self._data = {}
+ if other:
+ self._data.update(other)
+ self.get = self._data.get
+ self.items = self._data.items
+
+
+class CustomSequence(CustomDataTypeBase):
+ def __init__(self, other=None):
+ self._data = []
+ if other:
+ self._data.extend(other)
+ self.append = self._data.append
+
+class CustomLeafSequence(CustomSequence):
+ pass
+
+class CustomProvided(CustomMapping):
+ pass
+
+
+class BaseAdapterRegistryTests(unittest.TestCase):
+
+ maxDiff = None
+
+ def _getBaseAdapterRegistry(self):
+ from zope.interface.adapter import BaseAdapterRegistry
+ return BaseAdapterRegistry
+
+ def _getTargetClass(self):
+ BaseAdapterRegistry = self._getBaseAdapterRegistry()
+ class _CUT(BaseAdapterRegistry):
+ class LookupClass(object):
+ _changed = _extendors = ()
+ def __init__(self, reg):
+ pass
+ def changed(self, orig):
+ self._changed += (orig,)
+ def add_extendor(self, provided):
+ self._extendors += (provided,)
+ def remove_extendor(self, provided):
+ self._extendors = tuple([x for x in self._extendors
+ if x != provided])
+ for name in BaseAdapterRegistry._delegated:
+ setattr(_CUT.LookupClass, name, object())
+ return _CUT
+
+ def _makeOne(self):
+ return self._getTargetClass()()
+
+ def _getMappingType(self):
+ return dict
+
+ def _getProvidedType(self):
+ return dict
+
+ def _getMutableListType(self):
+ return list
+
+ def _getLeafSequenceType(self):
+ return tuple
+
+ def test_lookup_delegation(self):
+ CUT = self._getTargetClass()
+ registry = CUT()
+ for name in CUT._delegated:
+ self.assertIs(getattr(registry, name), getattr(registry._v_lookup, name))
+
+ def test__generation_on_first_creation(self):
+ registry = self._makeOne()
+ # Bumped to 1 in BaseAdapterRegistry.__init__
+ self.assertEqual(registry._generation, 1)
+
+ def test__generation_after_calling_changed(self):
+ registry = self._makeOne()
+ orig = object()
+ registry.changed(orig)
+ # Bumped to 1 in BaseAdapterRegistry.__init__
+ self.assertEqual(registry._generation, 2)
+ self.assertEqual(registry._v_lookup._changed, (registry, orig,))
+
+ def test__generation_after_changing___bases__(self):
+ class _Base(object):
+ pass
+ registry = self._makeOne()
+ registry.__bases__ = (_Base,)
+ self.assertEqual(registry._generation, 2)
+
+ def _check_basic_types_of_adapters(self, registry, expected_order=2):
+ self.assertEqual(len(registry._adapters), expected_order) # order 0 and order 1
+ self.assertIsInstance(registry._adapters, self._getMutableListType())
+ MT = self._getMappingType()
+ for mapping in registry._adapters:
+ self.assertIsInstance(mapping, MT)
+ self.assertEqual(registry._adapters[0], MT())
+ self.assertIsInstance(registry._adapters[1], MT)
+ self.assertEqual(len(registry._adapters[expected_order - 1]), 1)
+
+ def _check_basic_types_of_subscribers(self, registry, expected_order=2):
+ self.assertEqual(len(registry._subscribers), expected_order) # order 0 and order 1
+ self.assertIsInstance(registry._subscribers, self._getMutableListType())
+ MT = self._getMappingType()
+ for mapping in registry._subscribers:
+ self.assertIsInstance(mapping, MT)
+ if expected_order:
+ self.assertEqual(registry._subscribers[0], MT())
+ self.assertIsInstance(registry._subscribers[1], MT)
+ self.assertEqual(len(registry._subscribers[expected_order - 1]), 1)
+
+ def test_register(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ registry.register([IB0], IR0, '', 'A1')
+ self.assertEqual(registry.registered([IB0], IR0, ''), 'A1')
+ self.assertEqual(registry._generation, 2)
+ self._check_basic_types_of_adapters(registry)
+ MT = self._getMappingType()
+ self.assertEqual(registry._adapters[1], MT({
+ IB0: MT({
+ IR0: MT({'': 'A1'})
+ })
+ }))
+ PT = self._getProvidedType()
+ self.assertEqual(registry._provided, PT({
+ IR0: 1
+ }))
+
+ registered = list(registry.allRegistrations())
+ self.assertEqual(registered, [(
+ (IB0,), # required
+ IR0, # provided
+ '', # name
+ 'A1' # value
+ )])
+
+ def test_register_multiple_allRegistrations(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ # Use several different depths and several different names
+ registry.register([], IR0, '', 'A1')
+ registry.register([], IR0, 'name1', 'A2')
+
+ registry.register([IB0], IR0, '', 'A1')
+ registry.register([IB0], IR0, 'name2', 'A2')
+ registry.register([IB0], IR1, '', 'A3')
+ registry.register([IB0], IR1, 'name3', 'A4')
+
+ registry.register([IB0, IB1], IR0, '', 'A1')
+ registry.register([IB0, IB2], IR0, 'name2', 'A2')
+ registry.register([IB0, IB2], IR1, 'name4', 'A4')
+ registry.register([IB0, IB3], IR1, '', 'A3')
+
+ def build_adapters(L, MT):
+ return L([
+ # 0
+ MT({
+ IR0: MT({
+ '': 'A1',
+ 'name1': 'A2'
+ })
+ }),
+ # 1
+ MT({
+ IB0: MT({
+ IR0: MT({
+ '': 'A1',
+ 'name2': 'A2'
+ }),
+ IR1: MT({
+ '': 'A3',
+ 'name3': 'A4'
+ })
+ })
+ }),
+ # 3
+ MT({
+ IB0: MT({
+ IB1: MT({
+ IR0: MT({'': 'A1'})
+ }),
+ IB2: MT({
+ IR0: MT({'name2': 'A2'}),
+ IR1: MT({'name4': 'A4'}),
+ }),
+ IB3: MT({
+ IR1: MT({'': 'A3'})
+ })
+ }),
+ }),
+ ])
+
+ self.assertEqual(registry._adapters,
+ build_adapters(L=self._getMutableListType(),
+ MT=self._getMappingType()))
+
+ registered = sorted(registry.allRegistrations())
+ self.assertEqual(registered, [
+ ((), IR0, '', 'A1'),
+ ((), IR0, 'name1', 'A2'),
+ ((IB0,), IR0, '', 'A1'),
+ ((IB0,), IR0, 'name2', 'A2'),
+ ((IB0,), IR1, '', 'A3'),
+ ((IB0,), IR1, 'name3', 'A4'),
+ ((IB0, IB1), IR0, '', 'A1'),
+ ((IB0, IB2), IR0, 'name2', 'A2'),
+ ((IB0, IB2), IR1, 'name4', 'A4'),
+ ((IB0, IB3), IR1, '', 'A3')
+ ])
+
+ # We can duplicate to another object.
+ registry2 = self._makeOne()
+ for args in registered:
+ registry2.register(*args)
+
+ self.assertEqual(registry2._adapters, registry._adapters)
+ self.assertEqual(registry2._provided, registry._provided)
+
+ # We can change the types and rebuild the data structures.
+ registry._mappingType = CustomMapping
+ registry._leafSequenceType = CustomLeafSequence
+ registry._sequenceType = CustomSequence
+ registry._providedType = CustomProvided
+ def addValue(existing, new):
+ existing = existing if existing is not None else CustomLeafSequence()
+ existing.append(new)
+ return existing
+ registry._addValueToLeaf = addValue
+
+ registry.rebuild()
+
+ self.assertEqual(registry._adapters,
+ build_adapters(
+ L=CustomSequence,
+ MT=CustomMapping
+ ))
+
+ def test_register_with_invalid_name(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ with self.assertRaises(ValueError):
+ registry.register([IB0], IR0, object(), 'A1')
+
+ def test_register_with_value_None_unregisters(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ registry.register([None], IR0, '', 'A1')
+ registry.register([None], IR0, '', None)
+ self.assertEqual(len(registry._adapters), 0)
+ self.assertIsInstance(registry._adapters, self._getMutableListType())
+ registered = list(registry.allRegistrations())
+ self.assertEqual(registered, [])
+
+ def test_register_with_same_value(self):
+ from zope.interface import Interface
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ _value = object()
+ registry.register([None], IR0, '', _value)
+ _before = registry._generation
+ registry.register([None], IR0, '', _value)
+ self.assertEqual(registry._generation, _before) # skipped changed()
+ self._check_basic_types_of_adapters(registry)
+ MT = self._getMappingType()
+ self.assertEqual(registry._adapters[1], MT(
+ {
+ Interface: MT(
+ {
+ IR0: MT({'': _value})
+ }
+ )
+ }
+ ))
+ registered = list(registry.allRegistrations())
+ self.assertEqual(registered, [(
+ (Interface,), # required
+ IR0, # provided
+ '', # name
+ _value # value
+ )])
+
+
+ def test_registered_empty(self):
+ registry = self._makeOne()
+ self.assertEqual(registry.registered([None], None, ''), None)
+ registered = list(registry.allRegistrations())
+ self.assertEqual(registered, [])
+
+ def test_registered_non_empty_miss(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ registry.register([IB1], None, '', 'A1')
+ self.assertEqual(registry.registered([IB2], None, ''), None)
+
+ def test_registered_non_empty_hit(self):
+ registry = self._makeOne()
+ registry.register([None], None, '', 'A1')
+ self.assertEqual(registry.registered([None], None, ''), 'A1')
+
+ def test_unregister_empty(self):
+ registry = self._makeOne()
+ registry.unregister([None], None, '') # doesn't raise
+ self.assertEqual(registry.registered([None], None, ''), None)
+ self.assertEqual(len(registry._provided), 0)
+
+ def test_unregister_non_empty_miss_on_required(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ registry.register([IB1], None, '', 'A1')
+ registry.unregister([IB2], None, '') # doesn't raise
+ self.assertEqual(registry.registered([IB1], None, ''), 'A1')
+ self._check_basic_types_of_adapters(registry)
+ MT = self._getMappingType()
+ self.assertEqual(registry._adapters[1], MT(
+ {
+ IB1: MT(
+ {
+ None: MT({'': 'A1'})
+ }
+ )
+ }
+ ))
+ PT = self._getProvidedType()
+ self.assertEqual(registry._provided, PT({
+ None: 1
+ }))
+
+ def test_unregister_non_empty_miss_on_name(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ registry.register([IB1], None, '', 'A1')
+ registry.unregister([IB1], None, 'nonesuch') # doesn't raise
+ self.assertEqual(registry.registered([IB1], None, ''), 'A1')
+ self._check_basic_types_of_adapters(registry)
+ MT = self._getMappingType()
+ self.assertEqual(registry._adapters[1], MT(
+ {
+ IB1: MT(
+ {
+ None: MT({'': 'A1'})
+ }
+ )
+ }
+ ))
+ PT = self._getProvidedType()
+ self.assertEqual(registry._provided, PT({
+ None: 1
+ }))
+
+ def test_unregister_with_value_not_None_miss(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ orig = object()
+ nomatch = object()
+ registry.register([IB1], None, '', orig)
+ registry.unregister([IB1], None, '', nomatch) #doesn't raise
+ self.assertIs(registry.registered([IB1], None, ''), orig)
+
+ def test_unregister_hit_clears_empty_subcomponents(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ one = object()
+ another = object()
+ registry.register([IB1, IB2], None, '', one)
+ registry.register([IB1, IB3], None, '', another)
+ self._check_basic_types_of_adapters(registry, expected_order=3)
+ self.assertIn(IB2, registry._adapters[2][IB1])
+ self.assertIn(IB3, registry._adapters[2][IB1])
+ MT = self._getMappingType()
+ self.assertEqual(registry._adapters[2], MT(
+ {
+ IB1: MT(
+ {
+ IB2: MT({None: MT({'': one})}),
+ IB3: MT({None: MT({'': another})})
+ }
+ )
+ }
+ ))
+ PT = self._getProvidedType()
+ self.assertEqual(registry._provided, PT({
+ None: 2
+ }))
+
+ registry.unregister([IB1, IB3], None, '', another)
+ self.assertIn(IB2, registry._adapters[2][IB1])
+ self.assertNotIn(IB3, registry._adapters[2][IB1])
+ self.assertEqual(registry._adapters[2], MT(
+ {
+ IB1: MT(
+ {
+ IB2: MT({None: MT({'': one})}),
+ }
+ )
+ }
+ ))
+ self.assertEqual(registry._provided, PT({
+ None: 1
+ }))
+
+ def test_unsubscribe_empty(self):
+ registry = self._makeOne()
+ registry.unsubscribe([None], None, '') #doesn't raise
+ self.assertEqual(registry.registered([None], None, ''), None)
+ self._check_basic_types_of_subscribers(registry, expected_order=0)
+
+ def test_unsubscribe_hit(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ orig = object()
+ registry.subscribe([IB1], None, orig)
+ MT = self._getMappingType()
+ L = self._getLeafSequenceType()
+ PT = self._getProvidedType()
+ self._check_basic_types_of_subscribers(registry)
+ self.assertEqual(registry._subscribers[1], MT({
+ IB1: MT({
+ None: MT({
+ '': L((orig,))
+ })
+ })
+ }))
+ self.assertEqual(registry._provided, PT({}))
+ registry.unsubscribe([IB1], None, orig) #doesn't raise
+ self.assertEqual(len(registry._subscribers), 0)
+ self.assertEqual(registry._provided, PT({}))
+
+ def assertLeafIdentity(self, leaf1, leaf2):
+ """
+ Implementations may choose to use new, immutable objects
+ instead of mutating existing subscriber leaf objects, or vice versa.
+
+ The default implementation uses immutable tuples, so they are never
+ the same. Other implementations may use persistent lists so they should be
+ the same and mutated in place. Subclasses testing this behaviour need to
+ override this method.
+ """
+ self.assertIsNot(leaf1, leaf2)
+
+ def test_unsubscribe_after_multiple(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ first = object()
+ second = object()
+ third = object()
+ fourth = object()
+ registry.subscribe([IB1], None, first)
+ registry.subscribe([IB1], None, second)
+ registry.subscribe([IB1], IR0, third)
+ registry.subscribe([IB1], IR0, fourth)
+ self._check_basic_types_of_subscribers(registry, expected_order=2)
+ MT = self._getMappingType()
+ L = self._getLeafSequenceType()
+ PT = self._getProvidedType()
+ self.assertEqual(registry._subscribers[1], MT({
+ IB1: MT({
+ None: MT({'': L((first, second))}),
+ IR0: MT({'': L((third, fourth))}),
+ })
+ }))
+ self.assertEqual(registry._provided, PT({
+ IR0: 2
+ }))
+ # The leaf objects may or may not stay the same as they are unsubscribed,
+ # depending on the implementation
+ IR0_leaf_orig = registry._subscribers[1][IB1][IR0]['']
+ Non_leaf_orig = registry._subscribers[1][IB1][None]['']
+
+ registry.unsubscribe([IB1], None, first)
+ registry.unsubscribe([IB1], IR0, third)
+
+ self.assertEqual(registry._subscribers[1], MT({
+ IB1: MT({
+ None: MT({'': L((second,))}),
+ IR0: MT({'': L((fourth,))}),
+ })
+ }))
+ self.assertEqual(registry._provided, PT({
+ IR0: 1
+ }))
+ IR0_leaf_new = registry._subscribers[1][IB1][IR0]['']
+ Non_leaf_new = registry._subscribers[1][IB1][None]['']
+
+ self.assertLeafIdentity(IR0_leaf_orig, IR0_leaf_new)
+ self.assertLeafIdentity(Non_leaf_orig, Non_leaf_new)
+
+ registry.unsubscribe([IB1], None, second)
+ registry.unsubscribe([IB1], IR0, fourth)
+ self.assertEqual(len(registry._subscribers), 0)
+ self.assertEqual(len(registry._provided), 0)
+
+ def test_subscribe_unsubscribe_identical_objects_provided(self):
+ # https://github.com/zopefoundation/zope.interface/issues/227
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ first = object()
+ registry.subscribe([IB1], IR0, first)
+ registry.subscribe([IB1], IR0, first)
+
+ MT = self._getMappingType()
+ L = self._getLeafSequenceType()
+ PT = self._getProvidedType()
+ self.assertEqual(registry._subscribers[1], MT({
+ IB1: MT({
+ IR0: MT({'': L((first, first))}),
+ })
+ }))
+ self.assertEqual(registry._provided, PT({
+ IR0: 2
+ }))
+
+ registry.unsubscribe([IB1], IR0, first)
+ registry.unsubscribe([IB1], IR0, first)
+ self.assertEqual(len(registry._subscribers), 0)
+ self.assertEqual(registry._provided, PT())
+
+ def test_subscribe_unsubscribe_nonequal_objects_provided(self):
+ # https://github.com/zopefoundation/zope.interface/issues/227
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ first = object()
+ second = object()
+ registry.subscribe([IB1], IR0, first)
+ registry.subscribe([IB1], IR0, second)
+
+ MT = self._getMappingType()
+ L = self._getLeafSequenceType()
+ PT = self._getProvidedType()
+ self.assertEqual(registry._subscribers[1], MT({
+ IB1: MT({
+ IR0: MT({'': L((first, second))}),
+ })
+ }))
+ self.assertEqual(registry._provided, PT({
+ IR0: 2
+ }))
+
+ registry.unsubscribe([IB1], IR0, first)
+ registry.unsubscribe([IB1], IR0, second)
+ self.assertEqual(len(registry._subscribers), 0)
+ self.assertEqual(registry._provided, PT())
+
+ def test_subscribed_empty(self):
+ registry = self._makeOne()
+ self.assertIsNone(registry.subscribed([None], None, ''))
+ subscribed = list(registry.allSubscriptions())
+ self.assertEqual(subscribed, [])
+
+ def test_subscribed_non_empty_miss(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ registry.subscribe([IB1], IF0, 'A1')
+ # Mismatch required
+ self.assertIsNone(registry.subscribed([IB2], IF0, ''))
+ # Mismatch provided
+ self.assertIsNone(registry.subscribed([IB1], IF1, ''))
+ # Mismatch value
+ self.assertIsNone(registry.subscribed([IB1], IF0, ''))
+
+ def test_subscribed_non_empty_hit(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ registry.subscribe([IB0], IF0, 'A1')
+ self.assertEqual(registry.subscribed([IB0], IF0, 'A1'), 'A1')
+
+ def test_unsubscribe_w_None_after_multiple(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ first = object()
+ second = object()
+
+ registry.subscribe([IB1], None, first)
+ registry.subscribe([IB1], None, second)
+ self._check_basic_types_of_subscribers(registry, expected_order=2)
+ registry.unsubscribe([IB1], None)
+ self.assertEqual(len(registry._subscribers), 0)
+
+ def test_unsubscribe_non_empty_miss_on_required(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ registry.subscribe([IB1], None, 'A1')
+ self._check_basic_types_of_subscribers(registry, expected_order=2)
+ registry.unsubscribe([IB2], None, '') # doesn't raise
+ self.assertEqual(len(registry._subscribers), 2)
+ MT = self._getMappingType()
+ L = self._getLeafSequenceType()
+ self.assertEqual(registry._subscribers[1], MT({
+ IB1: MT({
+ None: MT({'': L(('A1',))}),
+ })
+ }))
+
+ def test_unsubscribe_non_empty_miss_on_value(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ registry.subscribe([IB1], None, 'A1')
+ self._check_basic_types_of_subscribers(registry, expected_order=2)
+ registry.unsubscribe([IB1], None, 'A2') # doesn't raise
+ self.assertEqual(len(registry._subscribers), 2)
+ MT = self._getMappingType()
+ L = self._getLeafSequenceType()
+ self.assertEqual(registry._subscribers[1], MT({
+ IB1: MT({
+ None: MT({'': L(('A1',))}),
+ })
+ }))
+
+ def test_unsubscribe_with_value_not_None_miss(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ orig = object()
+ nomatch = object()
+ registry.subscribe([IB1], None, orig)
+ registry.unsubscribe([IB1], None, nomatch) #doesn't raise
+ self.assertEqual(len(registry._subscribers), 2)
+
+ def _instance_method_notify_target(self):
+ self.fail("Example method, not intended to be called.")
+
+ def test_unsubscribe_instance_method(self):
+ # Checking that the values are compared by equality, not identity
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ self.assertEqual(len(registry._subscribers), 0)
+ registry.subscribe([IB1], None, self._instance_method_notify_target)
+ registry.unsubscribe([IB1], None, self._instance_method_notify_target)
+ self.assertEqual(len(registry._subscribers), 0)
+
+ def test_subscribe_multiple_allRegistrations(self):
+ IB0, IB1, IB2, IB3, IB4, IF0, IF1, IR0, IR1 = _makeInterfaces() # pylint:disable=unused-variable
+ registry = self._makeOne()
+ # Use several different depths and several different values
+ registry.subscribe([], IR0, 'A1')
+ registry.subscribe([], IR0, 'A2')
+
+ registry.subscribe([IB0], IR0, 'A1')
+ registry.subscribe([IB0], IR0, 'A2')
+ registry.subscribe([IB0], IR1, 'A3')
+ registry.subscribe([IB0], IR1, 'A4')
+
+ registry.subscribe([IB0, IB1], IR0, 'A1')
+ registry.subscribe([IB0, IB2], IR0, 'A2')
+ registry.subscribe([IB0, IB2], IR1, 'A4')
+ registry.subscribe([IB0, IB3], IR1, 'A3')
+
+
+ def build_subscribers(L, F, MT):
+ return L([
+ # 0
+ MT({
+ IR0: MT({
+ '': F(['A1', 'A2'])
+ })
+ }),
+ # 1
+ MT({
+ IB0: MT({
+ IR0: MT({
+ '': F(['A1', 'A2'])
+ }),
+ IR1: MT({
+ '': F(['A3', 'A4'])
+ })
+ })
+ }),
+ # 3
+ MT({
+ IB0: MT({
+ IB1: MT({
+ IR0: MT({'': F(['A1'])})
+ }),
+ IB2: MT({
+ IR0: MT({'': F(['A2'])}),
+ IR1: MT({'': F(['A4'])}),
+ }),
+ IB3: MT({
+ IR1: MT({'': F(['A3'])})
+ })
+ }),
+ }),
+ ])
+
+ self.assertEqual(registry._subscribers,
+ build_subscribers(
+ L=self._getMutableListType(),
+ F=self._getLeafSequenceType(),
+ MT=self._getMappingType()
+ ))
+
+ def build_provided(P):
+ return P({
+ IR0: 6,
+ IR1: 4,
+ })
+
+
+ self.assertEqual(registry._provided,
+ build_provided(P=self._getProvidedType()))
+
+ registered = sorted(registry.allSubscriptions())
+ self.assertEqual(registered, [
+ ((), IR0, 'A1'),
+ ((), IR0, 'A2'),
+ ((IB0,), IR0, 'A1'),
+ ((IB0,), IR0, 'A2'),
+ ((IB0,), IR1, 'A3'),
+ ((IB0,), IR1, 'A4'),
+ ((IB0, IB1), IR0, 'A1'),
+ ((IB0, IB2), IR0, 'A2'),
+ ((IB0, IB2), IR1, 'A4'),
+ ((IB0, IB3), IR1, 'A3')
+ ])
+
+ # We can duplicate this to another object
+ registry2 = self._makeOne()
+ for args in registered:
+ registry2.subscribe(*args)
+
+ self.assertEqual(registry2._subscribers, registry._subscribers)
+ self.assertEqual(registry2._provided, registry._provided)
+
+ # We can change the types and rebuild the data structures.
+ registry._mappingType = CustomMapping
+ registry._leafSequenceType = CustomLeafSequence
+ registry._sequenceType = CustomSequence
+ registry._providedType = CustomProvided
+ def addValue(existing, new):
+ existing = existing if existing is not None else CustomLeafSequence()
+ existing.append(new)
+ return existing
+ registry._addValueToLeaf = addValue
+
+ registry.rebuild()
+
+ self.assertEqual(registry._subscribers,
+ build_subscribers(
+ L=CustomSequence,
+ F=CustomLeafSequence,
+ MT=CustomMapping
+ ))
+
+
+class CustomTypesBaseAdapterRegistryTests(BaseAdapterRegistryTests):
+ """
+ This class may be extended by other packages to test their own
+ adapter registries that use custom types. (So be cautious about
+ breaking changes.)
+
+ One known user is ``zope.component.persistentregistry``.
+ """
+
+ def _getMappingType(self):
+ return CustomMapping
+
+ def _getProvidedType(self):
+ return CustomProvided
+
+ def _getMutableListType(self):
+ return CustomSequence
+
+ def _getLeafSequenceType(self):
+ return CustomLeafSequence
+
+ def _getBaseAdapterRegistry(self):
+ from zope.interface.adapter import BaseAdapterRegistry
+ class CustomAdapterRegistry(BaseAdapterRegistry):
+ _mappingType = self._getMappingType()
+ _sequenceType = self._getMutableListType()
+ _leafSequenceType = self._getLeafSequenceType()
+ _providedType = self._getProvidedType()
+
+ def _addValueToLeaf(self, existing_leaf_sequence, new_item):
+ if not existing_leaf_sequence:
+ existing_leaf_sequence = self._leafSequenceType()
+ existing_leaf_sequence.append(new_item)
+ return existing_leaf_sequence
+
+ def _removeValueFromLeaf(self, existing_leaf_sequence, to_remove):
+ without_removed = BaseAdapterRegistry._removeValueFromLeaf(
+ self,
+ existing_leaf_sequence,
+ to_remove)
+ existing_leaf_sequence[:] = without_removed
+ assert to_remove not in existing_leaf_sequence
+ return existing_leaf_sequence
+
+ return CustomAdapterRegistry
+
+ def assertLeafIdentity(self, leaf1, leaf2):
+ self.assertIs(leaf1, leaf2)
+
+
+class LookupBaseFallbackTests(unittest.TestCase):
+
+ def _getFallbackClass(self):
+ from zope.interface.adapter import LookupBaseFallback # pylint:disable=no-name-in-module
+ return LookupBaseFallback
+
+ _getTargetClass = _getFallbackClass
+
+ def _makeOne(self, uc_lookup=None, uc_lookupAll=None,
+ uc_subscriptions=None):
+ # pylint:disable=function-redefined
+ if uc_lookup is None:
+ def uc_lookup(self, required, provided, name):
+ pass
+ if uc_lookupAll is None:
+ def uc_lookupAll(self, required, provided):
+ raise NotImplementedError()
+ if uc_subscriptions is None:
+ def uc_subscriptions(self, required, provided):
+ raise NotImplementedError()
+ class Derived(self._getTargetClass()):
+ _uncached_lookup = uc_lookup
+ _uncached_lookupAll = uc_lookupAll
+ _uncached_subscriptions = uc_subscriptions
+ return Derived()
+
+ def test_lookup_w_invalid_name(self):
+ def _lookup(self, required, provided, name):
+ self.fail("This should never be called")
+ lb = self._makeOne(uc_lookup=_lookup)
+ with self.assertRaises(ValueError):
+ lb.lookup(('A',), 'B', object())
+
+ def test_lookup_miss_no_default(self):
+ _called_with = []
+ def _lookup(self, required, provided, name):
+ _called_with.append((required, provided, name))
+
+ lb = self._makeOne(uc_lookup=_lookup)
+ found = lb.lookup(('A',), 'B', 'C')
+ self.assertIsNone(found)
+ self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+
+ def test_lookup_miss_w_default(self):
+ _called_with = []
+ _default = object()
+ def _lookup(self, required, provided, name):
+ _called_with.append((required, provided, name))
+
+ lb = self._makeOne(uc_lookup=_lookup)
+ found = lb.lookup(('A',), 'B', 'C', _default)
+ self.assertIs(found, _default)
+ self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+
+ def test_lookup_not_cached(self):
+ _called_with = []
+ a, b, c = object(), object(), object()
+ _results = [a, b, c]
+ def _lookup(self, required, provided, name):
+ _called_with.append((required, provided, name))
+ return _results.pop(0)
+ lb = self._makeOne(uc_lookup=_lookup)
+ found = lb.lookup(('A',), 'B', 'C')
+ self.assertIs(found, a)
+ self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+ self.assertEqual(_results, [b, c])
+
+ def test_lookup_cached(self):
+ _called_with = []
+ a, b, c = object(), object(), object()
+ _results = [a, b, c]
+ def _lookup(self, required, provided, name):
+ _called_with.append((required, provided, name))
+ return _results.pop(0)
+ lb = self._makeOne(uc_lookup=_lookup)
+ found = lb.lookup(('A',), 'B', 'C')
+ found = lb.lookup(('A',), 'B', 'C')
+ self.assertIs(found, a)
+ self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+ self.assertEqual(_results, [b, c])
+
+ def test_lookup_not_cached_multi_required(self):
+ _called_with = []
+ a, b, c = object(), object(), object()
+ _results = [a, b, c]
+ def _lookup(self, required, provided, name):
+ _called_with.append((required, provided, name))
+ return _results.pop(0)
+ lb = self._makeOne(uc_lookup=_lookup)
+ found = lb.lookup(('A', 'D'), 'B', 'C')
+ self.assertIs(found, a)
+ self.assertEqual(_called_with, [(('A', 'D'), 'B', 'C')])
+ self.assertEqual(_results, [b, c])
+
+ def test_lookup_cached_multi_required(self):
+ _called_with = []
+ a, b, c = object(), object(), object()
+ _results = [a, b, c]
+ def _lookup(self, required, provided, name):
+ _called_with.append((required, provided, name))
+ return _results.pop(0)
+ lb = self._makeOne(uc_lookup=_lookup)
+ found = lb.lookup(('A', 'D'), 'B', 'C')
+ found = lb.lookup(('A', 'D'), 'B', 'C')
+ self.assertIs(found, a)
+ self.assertEqual(_called_with, [(('A', 'D'), 'B', 'C')])
+ self.assertEqual(_results, [b, c])
+
+ def test_lookup_not_cached_after_changed(self):
+ _called_with = []
+ a, b, c = object(), object(), object()
+ _results = [a, b, c]
+ def _lookup(self, required, provided, name):
+ _called_with.append((required, provided, name))
+ return _results.pop(0)
+ lb = self._makeOne(uc_lookup=_lookup)
+ found = lb.lookup(('A',), 'B', 'C')
+ lb.changed(lb)
+ found = lb.lookup(('A',), 'B', 'C')
+ self.assertIs(found, b)
+ self.assertEqual(_called_with,
+ [(('A',), 'B', 'C'), (('A',), 'B', 'C')])
+ self.assertEqual(_results, [c])
+
+ def test_lookup1_w_invalid_name(self):
+ def _lookup(self, required, provided, name):
+ self.fail("This should never be called")
+
+ lb = self._makeOne(uc_lookup=_lookup)
+ with self.assertRaises(ValueError):
+ lb.lookup1('A', 'B', object())
+
+ def test_lookup1_miss_no_default(self):
+ _called_with = []
+ def _lookup(self, required, provided, name):
+ _called_with.append((required, provided, name))
+
+ lb = self._makeOne(uc_lookup=_lookup)
+ found = lb.lookup1('A', 'B', 'C')
+ self.assertIsNone(found)
+ self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+
+ def test_lookup1_miss_w_default(self):
+ _called_with = []
+ _default = object()
+ def _lookup(self, required, provided, name):
+ _called_with.append((required, provided, name))
+
+ lb = self._makeOne(uc_lookup=_lookup)
+ found = lb.lookup1('A', 'B', 'C', _default)
+ self.assertIs(found, _default)
+ self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+
+ def test_lookup1_miss_w_default_negative_cache(self):
+ _called_with = []
+ _default = object()
+ def _lookup(self, required, provided, name):
+ _called_with.append((required, provided, name))
+
+ lb = self._makeOne(uc_lookup=_lookup)
+ found = lb.lookup1('A', 'B', 'C', _default)
+ self.assertIs(found, _default)
+ found = lb.lookup1('A', 'B', 'C', _default)
+ self.assertIs(found, _default)
+ self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+
+ def test_lookup1_not_cached(self):
+ _called_with = []
+ a, b, c = object(), object(), object()
+ _results = [a, b, c]
+ def _lookup(self, required, provided, name):
+ _called_with.append((required, provided, name))
+ return _results.pop(0)
+ lb = self._makeOne(uc_lookup=_lookup)
+ found = lb.lookup1('A', 'B', 'C')
+ self.assertIs(found, a)
+ self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+ self.assertEqual(_results, [b, c])
+
+ def test_lookup1_cached(self):
+ _called_with = []
+ a, b, c = object(), object(), object()
+ _results = [a, b, c]
+ def _lookup(self, required, provided, name):
+ _called_with.append((required, provided, name))
+ return _results.pop(0)
+ lb = self._makeOne(uc_lookup=_lookup)
+ found = lb.lookup1('A', 'B', 'C')
+ found = lb.lookup1('A', 'B', 'C')
+ self.assertIs(found, a)
+ self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+ self.assertEqual(_results, [b, c])
+
+ def test_lookup1_not_cached_after_changed(self):
+ _called_with = []
+ a, b, c = object(), object(), object()
+ _results = [a, b, c]
+ def _lookup(self, required, provided, name):
+ _called_with.append((required, provided, name))
+ return _results.pop(0)
+ lb = self._makeOne(uc_lookup=_lookup)
+ found = lb.lookup1('A', 'B', 'C')
+ lb.changed(lb)
+ found = lb.lookup1('A', 'B', 'C')
+ self.assertIs(found, b)
+ self.assertEqual(_called_with,
+ [(('A',), 'B', 'C'), (('A',), 'B', 'C')])
+ self.assertEqual(_results, [c])
+
+ def test_adapter_hook_w_invalid_name(self):
+ req, prv = object(), object()
+ lb = self._makeOne()
+ with self.assertRaises(ValueError):
+ lb.adapter_hook(prv, req, object())
+
+ def test_adapter_hook_miss_no_default(self):
+ req, prv = object(), object()
+ lb = self._makeOne()
+ found = lb.adapter_hook(prv, req, '')
+ self.assertIsNone(found)
+
+ def test_adapter_hook_miss_w_default(self):
+ req, prv, _default = object(), object(), object()
+ lb = self._makeOne()
+ found = lb.adapter_hook(prv, req, '', _default)
+ self.assertIs(found, _default)
+
+ def test_adapter_hook_hit_factory_returns_None(self):
+ _f_called_with = []
+ def _factory(context):
+ _f_called_with.append(context)
+
+ def _lookup(self, required, provided, name):
+ return _factory
+ req, prv, _default = object(), object(), object()
+ lb = self._makeOne(uc_lookup=_lookup)
+ adapted = lb.adapter_hook(prv, req, 'C', _default)
+ self.assertIs(adapted, _default)
+ self.assertEqual(_f_called_with, [req])
+
+ def test_adapter_hook_hit_factory_returns_adapter(self):
+ _f_called_with = []
+ _adapter = object()
+ def _factory(context):
+ _f_called_with.append(context)
+ return _adapter
+ def _lookup(self, required, provided, name):
+ return _factory
+ req, prv, _default = object(), object(), object()
+ lb = self._makeOne(uc_lookup=_lookup)
+ adapted = lb.adapter_hook(prv, req, 'C', _default)
+ self.assertIs(adapted, _adapter)
+ self.assertEqual(_f_called_with, [req])
+
+ def test_adapter_hook_super_unwraps(self):
+ _f_called_with = []
+ def _factory(context):
+ _f_called_with.append(context)
+ return context
+ def _lookup(self, required, provided, name=''):
+ return _factory
+ required = super(LookupBaseFallbackTests, self)
+ provided = object()
+ lb = self._makeOne(uc_lookup=_lookup)
+ adapted = lb.adapter_hook(provided, required)
+ self.assertIs(adapted, self)
+ self.assertEqual(_f_called_with, [self])
+
+ def test_queryAdapter(self):
+ _f_called_with = []
+ _adapter = object()
+ def _factory(context):
+ _f_called_with.append(context)
+ return _adapter
+ def _lookup(self, required, provided, name):
+ return _factory
+ req, prv, _default = object(), object(), object()
+ lb = self._makeOne(uc_lookup=_lookup)
+ adapted = lb.queryAdapter(req, prv, 'C', _default)
+ self.assertIs(adapted, _adapter)
+ self.assertEqual(_f_called_with, [req])
+
+ def test_lookupAll_uncached(self):
+ _called_with = []
+ _results = [object(), object(), object()]
+ def _lookupAll(self, required, provided):
+ _called_with.append((required, provided))
+ return tuple(_results)
+ lb = self._makeOne(uc_lookupAll=_lookupAll)
+ found = lb.lookupAll('A', 'B')
+ self.assertEqual(found, tuple(_results))
+ self.assertEqual(_called_with, [(('A',), 'B')])
+
+ def test_lookupAll_cached(self):
+ _called_with = []
+ _results = [object(), object(), object()]
+ def _lookupAll(self, required, provided):
+ _called_with.append((required, provided))
+ return tuple(_results)
+ lb = self._makeOne(uc_lookupAll=_lookupAll)
+ found = lb.lookupAll('A', 'B')
+ found = lb.lookupAll('A', 'B')
+ self.assertEqual(found, tuple(_results))
+ self.assertEqual(_called_with, [(('A',), 'B')])
+
+ def test_subscriptions_uncached(self):
+ _called_with = []
+ _results = [object(), object(), object()]
+ def _subscriptions(self, required, provided):
+ _called_with.append((required, provided))
+ return tuple(_results)
+ lb = self._makeOne(uc_subscriptions=_subscriptions)
+ found = lb.subscriptions('A', 'B')
+ self.assertEqual(found, tuple(_results))
+ self.assertEqual(_called_with, [(('A',), 'B')])
+
+ def test_subscriptions_cached(self):
+ _called_with = []
+ _results = [object(), object(), object()]
+ def _subscriptions(self, required, provided):
+ _called_with.append((required, provided))
+ return tuple(_results)
+ lb = self._makeOne(uc_subscriptions=_subscriptions)
+ found = lb.subscriptions('A', 'B')
+ found = lb.subscriptions('A', 'B')
+ self.assertEqual(found, tuple(_results))
+ self.assertEqual(_called_with, [(('A',), 'B')])
+
+
+class LookupBaseTests(LookupBaseFallbackTests,
+ OptimizationTestMixin):
+
+ def _getTargetClass(self):
+ from zope.interface.adapter import LookupBase
+ return LookupBase
+
+
+class VerifyingBaseFallbackTests(unittest.TestCase):
+
+ def _getFallbackClass(self):
+ from zope.interface.adapter import VerifyingBaseFallback # pylint:disable=no-name-in-module
+ return VerifyingBaseFallback
+
+ _getTargetClass = _getFallbackClass
+
+ def _makeOne(self, registry, uc_lookup=None, uc_lookupAll=None,
+ uc_subscriptions=None):
+ # pylint:disable=function-redefined
+ if uc_lookup is None:
+ def uc_lookup(self, required, provided, name):
+ raise NotImplementedError()
+ if uc_lookupAll is None:
+ def uc_lookupAll(self, required, provided):
+ raise NotImplementedError()
+ if uc_subscriptions is None:
+ def uc_subscriptions(self, required, provided):
+ raise NotImplementedError()
+ class Derived(self._getTargetClass()):
+ _uncached_lookup = uc_lookup
+ _uncached_lookupAll = uc_lookupAll
+ _uncached_subscriptions = uc_subscriptions
+ def __init__(self, registry):
+ super(Derived, self).__init__()
+ self._registry = registry
+ derived = Derived(registry)
+ derived.changed(derived) # init. '_verify_ro' / '_verify_generations'
+ return derived
+
+ def _makeRegistry(self, depth):
+ class WithGeneration(object):
+ _generation = 1
+ class Registry:
+ def __init__(self, depth):
+ self.ro = [WithGeneration() for i in range(depth)]
+ return Registry(depth)
+
+ def test_lookup(self):
+ _called_with = []
+ a, b, c = object(), object(), object()
+ _results = [a, b, c]
+ def _lookup(self, required, provided, name):
+ _called_with.append((required, provided, name))
+ return _results.pop(0)
+ reg = self._makeRegistry(3)
+ lb = self._makeOne(reg, uc_lookup=_lookup)
+ found = lb.lookup(('A',), 'B', 'C')
+ found = lb.lookup(('A',), 'B', 'C')
+ self.assertIs(found, a)
+ self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+ self.assertEqual(_results, [b, c])
+ reg.ro[1]._generation += 1
+ found = lb.lookup(('A',), 'B', 'C')
+ self.assertIs(found, b)
+ self.assertEqual(_called_with,
+ [(('A',), 'B', 'C'), (('A',), 'B', 'C')])
+ self.assertEqual(_results, [c])
+
+ def test_lookup1(self):
+ _called_with = []
+ a, b, c = object(), object(), object()
+ _results = [a, b, c]
+ def _lookup(self, required, provided, name):
+ _called_with.append((required, provided, name))
+ return _results.pop(0)
+ reg = self._makeRegistry(3)
+ lb = self._makeOne(reg, uc_lookup=_lookup)
+ found = lb.lookup1('A', 'B', 'C')
+ found = lb.lookup1('A', 'B', 'C')
+ self.assertIs(found, a)
+ self.assertEqual(_called_with, [(('A',), 'B', 'C')])
+ self.assertEqual(_results, [b, c])
+ reg.ro[1]._generation += 1
+ found = lb.lookup1('A', 'B', 'C')
+ self.assertIs(found, b)
+ self.assertEqual(_called_with,
+ [(('A',), 'B', 'C'), (('A',), 'B', 'C')])
+ self.assertEqual(_results, [c])
+
+ def test_adapter_hook(self):
+ a, b, _c = [object(), object(), object()]
+ def _factory1(context):
+ return a
+ def _factory2(context):
+ return b
+ def _factory3(context):
+ self.fail("This should never be called")
+ _factories = [_factory1, _factory2, _factory3]
+ def _lookup(self, required, provided, name):
+ return _factories.pop(0)
+ req, prv, _default = object(), object(), object()
+ reg = self._makeRegistry(3)
+ lb = self._makeOne(reg, uc_lookup=_lookup)
+ adapted = lb.adapter_hook(prv, req, 'C', _default)
+ self.assertIs(adapted, a)
+ adapted = lb.adapter_hook(prv, req, 'C', _default)
+ self.assertIs(adapted, a)
+ reg.ro[1]._generation += 1
+ adapted = lb.adapter_hook(prv, req, 'C', _default)
+ self.assertIs(adapted, b)
+
+ def test_queryAdapter(self):
+ a, b, _c = [object(), object(), object()]
+ def _factory1(context):
+ return a
+ def _factory2(context):
+ return b
+ def _factory3(context):
+ self.fail("This should never be called")
+ _factories = [_factory1, _factory2, _factory3]
+ def _lookup(self, required, provided, name):
+ return _factories.pop(0)
+ req, prv, _default = object(), object(), object()
+ reg = self._makeRegistry(3)
+ lb = self._makeOne(reg, uc_lookup=_lookup)
+ adapted = lb.queryAdapter(req, prv, 'C', _default)
+ self.assertIs(adapted, a)
+ adapted = lb.queryAdapter(req, prv, 'C', _default)
+ self.assertIs(adapted, a)
+ reg.ro[1]._generation += 1
+ adapted = lb.adapter_hook(prv, req, 'C', _default)
+ self.assertIs(adapted, b)
+
+ def test_lookupAll(self):
+ _results_1 = [object(), object(), object()]
+ _results_2 = [object(), object(), object()]
+ _results = [_results_1, _results_2]
+ def _lookupAll(self, required, provided):
+ return tuple(_results.pop(0))
+ reg = self._makeRegistry(3)
+ lb = self._makeOne(reg, uc_lookupAll=_lookupAll)
+ found = lb.lookupAll('A', 'B')
+ self.assertEqual(found, tuple(_results_1))
+ found = lb.lookupAll('A', 'B')
+ self.assertEqual(found, tuple(_results_1))
+ reg.ro[1]._generation += 1
+ found = lb.lookupAll('A', 'B')
+ self.assertEqual(found, tuple(_results_2))
+
+ def test_subscriptions(self):
+ _results_1 = [object(), object(), object()]
+ _results_2 = [object(), object(), object()]
+ _results = [_results_1, _results_2]
+ def _subscriptions(self, required, provided):
+ return tuple(_results.pop(0))
+ reg = self._makeRegistry(3)
+ lb = self._makeOne(reg, uc_subscriptions=_subscriptions)
+ found = lb.subscriptions('A', 'B')
+ self.assertEqual(found, tuple(_results_1))
+ found = lb.subscriptions('A', 'B')
+ self.assertEqual(found, tuple(_results_1))
+ reg.ro[1]._generation += 1
+ found = lb.subscriptions('A', 'B')
+ self.assertEqual(found, tuple(_results_2))
+
+
+class VerifyingBaseTests(VerifyingBaseFallbackTests,
+ OptimizationTestMixin):
+
+ def _getTargetClass(self):
+ from zope.interface.adapter import VerifyingBase
+ return VerifyingBase
+
+
+class AdapterLookupBaseTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.adapter import AdapterLookupBase
+ return AdapterLookupBase
+
+ def _makeOne(self, registry):
+ return self._getTargetClass()(registry)
+
+ def _makeSubregistry(self, *provided):
+ class Subregistry:
+ def __init__(self):
+ self._adapters = []
+ self._subscribers = []
+ return Subregistry()
+
+ def _makeRegistry(self, *provided):
+ class Registry:
+ def __init__(self, provided):
+ self._provided = provided
+ self.ro = []
+ return Registry(provided)
+
+ def test_ctor_empty_registry(self):
+ registry = self._makeRegistry()
+ alb = self._makeOne(registry)
+ self.assertEqual(alb._extendors, {})
+
+ def test_ctor_w_registry_provided(self):
+ from zope.interface import Interface
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('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, IBar])
+ self.assertEqual(alb._extendors[IBar], [IBar])
+ self.assertEqual(sorted(alb._extendors[Interface]),
+ sorted([IFoo, IBar]))
+
+ def test_changed_empty_required(self):
+ # ALB.changed expects to call a mixed in changed.
+ class Mixin(object):
+ def changed(self, *other):
+ pass
+ class Derived(self._getTargetClass(), Mixin):
+ pass
+ registry = self._makeRegistry()
+ alb = Derived(registry)
+ alb.changed(alb)
+
+ def test_changed_w_required(self):
+ # ALB.changed expects to call a mixed in changed.
+ class Mixin(object):
+ def changed(self, *other):
+ pass
+ class Derived(self._getTargetClass(), Mixin):
+ pass
+ class FauxWeakref(object):
+ _unsub = None
+ def __init__(self, here):
+ self._here = here
+ def __call__(self):
+ return self if self._here else None
+ def unsubscribe(self, target):
+ self._unsub = target
+ gone = FauxWeakref(False)
+ here = FauxWeakref(True)
+ registry = self._makeRegistry()
+ alb = Derived(registry)
+ alb._required[gone] = 1
+ alb._required[here] = 1
+ alb.changed(alb)
+ self.assertEqual(len(alb._required), 0)
+ self.assertEqual(gone._unsub, None)
+ self.assertEqual(here._unsub, alb)
+
+ def test_init_extendors_after_registry_update(self):
+ from zope.interface import Interface
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('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, IBar])
+ self.assertEqual(alb._extendors[IBar], [IBar])
+ self.assertEqual(sorted(alb._extendors[Interface]),
+ sorted([IFoo, IBar]))
+
+ def test_add_extendor(self):
+ from zope.interface import Interface
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('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, IBar])
+ self.assertEqual(alb._extendors[IBar], [IBar])
+ self.assertEqual(sorted(alb._extendors[Interface]),
+ sorted([IFoo, IBar]))
+
+ def test_remove_extendor(self):
+ from zope.interface import Interface
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('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], [IBar])
+ self.assertEqual(alb._extendors[IBar], [IBar])
+ self.assertEqual(sorted(alb._extendors[Interface]),
+ sorted([IBar]))
+
+ # test '_subscribe' via its callers, '_uncached_lookup', etc.
+
+ def test__uncached_lookup_empty_ro(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry()
+ alb = self._makeOne(registry)
+ result = alb._uncached_lookup((IFoo,), IBar)
+ self.assertEqual(result, None)
+ self.assertEqual(len(alb._required), 1)
+ self.assertIn(IFoo.weakref(), alb._required)
+
+ def test__uncached_lookup_order_miss(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ result = alb._uncached_lookup((IFoo,), IBar)
+ self.assertEqual(result, None)
+
+ def test__uncached_lookup_extendors_miss(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry()
+ subr = self._makeSubregistry()
+ subr._adapters = [{}, {}] #utilities, single adapters
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ subr._v_lookup = alb
+ result = alb._uncached_lookup((IFoo,), IBar)
+ self.assertEqual(result, None)
+
+ def test__uncached_lookup_components_miss_wrong_iface(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ IQux = InterfaceClass('IQux')
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ irrelevant = object()
+ subr._adapters = [ #utilities, single adapters
+ {},
+ {IFoo: {IQux: {'': irrelevant},
+ }},
+ ]
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ subr._v_lookup = alb
+ result = alb._uncached_lookup((IFoo,), IBar)
+ self.assertEqual(result, None)
+
+ def test__uncached_lookup_components_miss_wrong_name(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+
+ wrongname = object()
+ subr._adapters = [ #utilities, single adapters
+ {},
+ {IFoo: {IBar: {'wrongname': wrongname},
+ }},
+ ]
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ subr._v_lookup = alb
+ result = alb._uncached_lookup((IFoo,), IBar)
+ self.assertEqual(result, None)
+
+ def test__uncached_lookup_simple_hit(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ _expected = object()
+ subr._adapters = [ #utilities, single adapters
+ {},
+ {IFoo: {IBar: {'': _expected}}},
+ ]
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ subr._v_lookup = alb
+ result = alb._uncached_lookup((IFoo,), IBar)
+ self.assertIs(result, _expected)
+
+ def test__uncached_lookup_repeated_hit(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ _expected = object()
+ subr._adapters = [ #utilities, single adapters
+ {},
+ {IFoo: {IBar: {'': _expected}}},
+ ]
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ subr._v_lookup = alb
+ result = alb._uncached_lookup((IFoo,), IBar)
+ result2 = alb._uncached_lookup((IFoo,), IBar)
+ self.assertIs(result, _expected)
+ self.assertIs(result2, _expected)
+
+ def test_queryMultiAdaptor_lookup_miss(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ foo = Foo()
+ registry = self._makeRegistry()
+ subr = self._makeSubregistry()
+ subr._adapters = [ #utilities, single adapters
+ {},
+ {},
+ ]
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ alb.lookup = alb._uncached_lookup # provided by derived
+ subr._v_lookup = alb
+ _default = object()
+ result = alb.queryMultiAdapter((foo,), IBar, default=_default)
+ self.assertIs(result, _default)
+
+ def test_queryMultiAdapter_errors_on_attribute_access(self):
+ # Any error on attribute access previously lead to using the _empty singleton as "requires"
+ # argument (See https://github.com/zopefoundation/zope.interface/issues/162)
+ # but after https://github.com/zopefoundation/zope.interface/issues/200
+ # they get propagated.
+ from zope.interface.interface import InterfaceClass
+ from __tests__.tests import MissingSomeAttrs
+
+ IFoo = InterfaceClass('IFoo')
+ registry = self._makeRegistry()
+ alb = self._makeOne(registry)
+ alb.lookup = alb._uncached_lookup
+
+ def test(ob):
+ return alb.queryMultiAdapter(
+ (ob,),
+ IFoo,
+ )
+
+ PY3 = str is not bytes
+ MissingSomeAttrs.test_raises(self, test,
+ expected_missing='__class__' if PY3 else '__providedBy__')
+
+ def test_queryMultiAdaptor_factory_miss(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ foo = Foo()
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ _expected = object()
+ _called_with = []
+ def _factory(context):
+ _called_with.append(context)
+
+ subr._adapters = [ #utilities, single adapters
+ {},
+ {IFoo: {IBar: {'': _factory}}},
+ ]
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ alb.lookup = alb._uncached_lookup # provided by derived
+ subr._v_lookup = alb
+ _default = object()
+ result = alb.queryMultiAdapter((foo,), IBar, default=_default)
+ self.assertIs(result, _default)
+ self.assertEqual(_called_with, [foo])
+
+ def test_queryMultiAdaptor_factory_hit(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ foo = Foo()
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ _expected = object()
+ _called_with = []
+ def _factory(context):
+ _called_with.append(context)
+ return _expected
+ subr._adapters = [ #utilities, single adapters
+ {},
+ {IFoo: {IBar: {'': _factory}}},
+ ]
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ alb.lookup = alb._uncached_lookup # provided by derived
+ subr._v_lookup = alb
+ _default = object()
+ result = alb.queryMultiAdapter((foo,), IBar, default=_default)
+ self.assertIs(result, _expected)
+ self.assertEqual(_called_with, [foo])
+
+ def test_queryMultiAdapter_super_unwraps(self):
+ alb = self._makeOne(self._makeRegistry())
+ def lookup(*args):
+ return factory
+ def factory(*args):
+ return args
+ alb.lookup = lookup
+
+ objects = [
+ super(AdapterLookupBaseTests, self),
+ 42,
+ "abc",
+ super(AdapterLookupBaseTests, self),
+ ]
+
+ result = alb.queryMultiAdapter(objects, None)
+ self.assertEqual(result, (
+ self,
+ 42,
+ "abc",
+ self,
+ ))
+
+ def test__uncached_lookupAll_empty_ro(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry()
+ alb = self._makeOne(registry)
+ result = alb._uncached_lookupAll((IFoo,), IBar)
+ self.assertEqual(result, ())
+ self.assertEqual(len(alb._required), 1)
+ self.assertIn(IFoo.weakref(), alb._required)
+
+ def test__uncached_lookupAll_order_miss(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ subr._v_lookup = alb
+ result = alb._uncached_lookupAll((IFoo,), IBar)
+ self.assertEqual(result, ())
+
+ def test__uncached_lookupAll_extendors_miss(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry()
+ subr = self._makeSubregistry()
+ subr._adapters = [{}, {}] #utilities, single adapters
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ subr._v_lookup = alb
+ result = alb._uncached_lookupAll((IFoo,), IBar)
+ self.assertEqual(result, ())
+
+ def test__uncached_lookupAll_components_miss(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ IQux = InterfaceClass('IQux')
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ irrelevant = object()
+ subr._adapters = [ #utilities, single adapters
+ {},
+ {IFoo: {IQux: {'': irrelevant}}},
+ ]
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ subr._v_lookup = alb
+ result = alb._uncached_lookupAll((IFoo,), IBar)
+ self.assertEqual(result, ())
+
+ def test__uncached_lookupAll_simple_hit(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ _expected = object()
+ _named = object()
+ subr._adapters = [ #utilities, single adapters
+ {},
+ {IFoo: {IBar: {'': _expected, 'named': _named}}},
+ ]
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ subr._v_lookup = alb
+ result = alb._uncached_lookupAll((IFoo,), IBar)
+ self.assertEqual(sorted(result), [('', _expected), ('named', _named)])
+
+ def test_names(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ _expected = object()
+ _named = object()
+ subr._adapters = [ #utilities, single adapters
+ {},
+ {IFoo: {IBar: {'': _expected, 'named': _named}}},
+ ]
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ alb.lookupAll = alb._uncached_lookupAll
+ subr._v_lookup = alb
+ result = alb.names((IFoo,), IBar)
+ self.assertEqual(sorted(result), ['', 'named'])
+
+ def test__uncached_subscriptions_empty_ro(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry()
+ alb = self._makeOne(registry)
+ result = alb._uncached_subscriptions((IFoo,), IBar)
+ self.assertEqual(result, [])
+ self.assertEqual(len(alb._required), 1)
+ self.assertIn(IFoo.weakref(), alb._required)
+
+ def test__uncached_subscriptions_order_miss(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ subr._v_lookup = alb
+ result = alb._uncached_subscriptions((IFoo,), IBar)
+ self.assertEqual(result, [])
+
+ def test__uncached_subscriptions_extendors_miss(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry()
+ subr = self._makeSubregistry()
+ subr._subscribers = [{}, {}] #utilities, single adapters
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ subr._v_lookup = alb
+ result = alb._uncached_subscriptions((IFoo,), IBar)
+ self.assertEqual(result, [])
+
+ def test__uncached_subscriptions_components_miss_wrong_iface(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ IQux = InterfaceClass('IQux')
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ irrelevant = object()
+ subr._subscribers = [ #utilities, single adapters
+ {},
+ {IFoo: {IQux: {'': irrelevant}}},
+ ]
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ subr._v_lookup = alb
+ result = alb._uncached_subscriptions((IFoo,), IBar)
+ self.assertEqual(result, [])
+
+ def test__uncached_subscriptions_components_miss_wrong_name(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ wrongname = object()
+ subr._subscribers = [ #utilities, single adapters
+ {},
+ {IFoo: {IBar: {'wrongname': wrongname}}},
+ ]
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ subr._v_lookup = alb
+ result = alb._uncached_subscriptions((IFoo,), IBar)
+ self.assertEqual(result, [])
+
+ def test__uncached_subscriptions_simple_hit(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ class Foo(object):
+ def __lt__(self, other):
+ return True
+ _exp1, _exp2 = Foo(), Foo()
+ subr._subscribers = [ #utilities, single adapters
+ {},
+ {IFoo: {IBar: {'': (_exp1, _exp2)}}},
+ ]
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ subr._v_lookup = alb
+ result = alb._uncached_subscriptions((IFoo,), IBar)
+ self.assertEqual(sorted(result), sorted([_exp1, _exp2]))
+
+ def test_subscribers_wo_provided(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ foo = Foo()
+ registry = self._makeRegistry(IFoo, IBar)
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ _called = {}
+ def _factory1(context):
+ _called.setdefault('_factory1', []).append(context)
+ def _factory2(context):
+ _called.setdefault('_factory2', []).append(context)
+ subr._subscribers = [ #utilities, single adapters
+ {},
+ {IFoo: {None: {'': (_factory1, _factory2)}}},
+ ]
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ alb.subscriptions = alb._uncached_subscriptions
+ subr._v_lookup = alb
+ result = alb.subscribers((foo,), None)
+ self.assertEqual(result, ())
+ self.assertEqual(_called, {'_factory1': [foo], '_factory2': [foo]})
+
+ def test_subscribers_w_provided(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ foo = Foo()
+ registry = self._makeRegistry(IFoo, IBar)
+ registry = self._makeRegistry(IFoo, IBar)
+ subr = self._makeSubregistry()
+ _called = {}
+ _exp1, _exp2 = object(), object()
+ def _factory1(context):
+ _called.setdefault('_factory1', []).append(context)
+ return _exp1
+ def _factory2(context):
+ _called.setdefault('_factory2', []).append(context)
+ return _exp2
+ def _side_effect_only(context):
+ _called.setdefault('_side_effect_only', []).append(context)
+
+ subr._subscribers = [ #utilities, single adapters
+ {},
+ {IFoo: {IBar: {'': (_factory1, _factory2, _side_effect_only)}}},
+ ]
+ registry.ro.append(subr)
+ alb = self._makeOne(registry)
+ alb.subscriptions = alb._uncached_subscriptions
+ subr._v_lookup = alb
+ result = alb.subscribers((foo,), IBar)
+ self.assertEqual(result, [_exp1, _exp2])
+ self.assertEqual(_called,
+ {'_factory1': [foo],
+ '_factory2': [foo],
+ '_side_effect_only': [foo],
+ })
+
+
+class VerifyingAdapterRegistryTests(unittest.TestCase):
+ # This is also the base for AdapterRegistryTests. That makes the
+ # inheritance seems backwards, but even though they implement the
+ # same interfaces, VAR and AR each only extend BAR; and neither
+ # one will pass the test cases for BAR (it uses a special
+ # LookupClass just for the tests).
+
+ def _getTargetClass(self):
+ from zope.interface.adapter import VerifyingAdapterRegistry
+ return VerifyingAdapterRegistry
+
+ def _makeOne(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def test_verify_object_provides_IAdapterRegistry(self):
+ from zope.interface.verify import verifyObject
+ from zope.interface.interfaces import IAdapterRegistry
+ registry = self._makeOne()
+ verifyObject(IAdapterRegistry, registry)
+
+
+class AdapterRegistryTests(VerifyingAdapterRegistryTests):
+
+ def _getTargetClass(self):
+ from zope.interface.adapter import AdapterRegistry
+ return AdapterRegistry
+
+ def test_ctor_no_bases(self):
+ ar = self._makeOne()
+ self.assertEqual(len(ar._v_subregistries), 0)
+
+ def test_ctor_w_bases(self):
+ base = self._makeOne()
+ sub = self._makeOne([base])
+ self.assertEqual(len(sub._v_subregistries), 0)
+ self.assertEqual(len(base._v_subregistries), 1)
+ self.assertIn(sub, base._v_subregistries)
+
+ # test _addSubregistry / _removeSubregistry via only caller, _setBases
+
+ def test__setBases_removing_existing_subregistry(self):
+ before = self._makeOne()
+ after = self._makeOne()
+ sub = self._makeOne([before])
+ sub.__bases__ = [after]
+ self.assertEqual(len(before._v_subregistries), 0)
+ self.assertEqual(len(after._v_subregistries), 1)
+ self.assertIn(sub, after._v_subregistries)
+
+ def test__setBases_wo_stray_entry(self):
+ before = self._makeOne()
+ stray = self._makeOne()
+ after = self._makeOne()
+ sub = self._makeOne([before])
+ sub.__dict__['__bases__'].append(stray)
+ sub.__bases__ = [after]
+ self.assertEqual(len(before._v_subregistries), 0)
+ self.assertEqual(len(after._v_subregistries), 1)
+ self.assertIn(sub, after._v_subregistries)
+
+ def test__setBases_w_existing_entry_continuing(self):
+ before = self._makeOne()
+ after = self._makeOne()
+ sub = self._makeOne([before])
+ sub.__bases__ = [before, after]
+ self.assertEqual(len(before._v_subregistries), 1)
+ self.assertEqual(len(after._v_subregistries), 1)
+ self.assertIn(sub, before._v_subregistries)
+ self.assertIn(sub, after._v_subregistries)
+
+ def test_changed_w_subregistries(self):
+ base = self._makeOne()
+ class Derived(object):
+ _changed = None
+ def changed(self, originally_changed):
+ self._changed = originally_changed
+ derived1, derived2 = Derived(), Derived()
+ base._addSubregistry(derived1)
+ base._addSubregistry(derived2)
+ orig = object()
+ base.changed(orig)
+ self.assertIs(derived1._changed, orig)
+ self.assertIs(derived2._changed, orig)
+
+
+class Test_utils(unittest.TestCase):
+
+ def test__convert_None_to_Interface_w_None(self):
+ from zope.interface.adapter import _convert_None_to_Interface
+ from zope.interface.interface import Interface
+ self.assertIs(_convert_None_to_Interface(None), Interface)
+
+ def test__convert_None_to_Interface_w_other(self):
+ from zope.interface.adapter import _convert_None_to_Interface
+ other = object()
+ self.assertIs(_convert_None_to_Interface(other), other)
+
+ def test__normalize_name_str(self):
+ from zope.interface.adapter import _normalize_name
+ STR = b'str'
+ UNICODE = u'str'
+ norm = _normalize_name(STR)
+ self.assertEqual(norm, UNICODE)
+ self.assertIsInstance(norm, type(UNICODE))
+
+ def test__normalize_name_unicode(self):
+ from zope.interface.adapter import _normalize_name
+
+ USTR = u'ustr'
+ self.assertEqual(_normalize_name(USTR), USTR)
+
+ def test__normalize_name_other(self):
+ from zope.interface.adapter import _normalize_name
+ for other in 1, 1.0, (), [], {}, object():
+ self.assertRaises(TypeError, _normalize_name, other)
+
+ # _lookup, _lookupAll, and _subscriptions tested via their callers
+ # (AdapterLookupBase.{lookup,lookupAll,subscriptions}).
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/test_advice.py b/contrib/python/zope.interface/py2/zope/interface/tests/test_advice.py
new file mode 100644
index 0000000000..100cb379a4
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/test_advice.py
@@ -0,0 +1,355 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Tests for advice
+
+This module was adapted from 'protocols.tests.advice', part of the Python
+Enterprise Application Kit (PEAK). Please notify the PEAK authors
+(pje@telecommunity.com and tsarna@sarna.org) if bugs are found or
+Zope-specific changes are required, so that the PEAK version of this module
+can be kept in sync.
+
+PEAK is a Python application framework that interoperates with (but does
+not require) Zope 3 and Twisted. It provides tools for manipulating UML
+models, object-relational persistence, aspect-oriented programming, and more.
+Visit the PEAK home page at http://peak.telecommunity.com for more information.
+"""
+
+import unittest
+import sys
+
+from zope.interface._compat import _skip_under_py2
+from zope.interface._compat import _skip_under_py3k
+
+
+class FrameInfoTest(unittest.TestCase):
+
+ def test_w_module(self):
+ from . import advisory_testing
+ (kind, module,
+ f_locals, f_globals) = advisory_testing.moduleLevelFrameInfo
+ self.assertEqual(kind, "module")
+ for d in module.__dict__, f_locals, f_globals:
+ self.assertTrue(d is advisory_testing.my_globals)
+
+ @_skip_under_py3k
+ def test_w_ClassicClass(self):
+ from . import advisory_testing
+ (kind,
+ module,
+ f_locals,
+ f_globals) = advisory_testing.ClassicClass.classLevelFrameInfo
+ self.assertEqual(kind, "class")
+
+ self.assertTrue(
+ f_locals is advisory_testing.ClassicClass.__dict__) # ???
+ for d in module.__dict__, f_globals:
+ self.assertTrue(d is advisory_testing.my_globals)
+
+ def test_w_NewStyleClass(self):
+ from . import advisory_testing
+ (kind,
+ module,
+ f_locals,
+ f_globals) = advisory_testing.NewStyleClass.classLevelFrameInfo
+ self.assertEqual(kind, "class")
+
+ for d in module.__dict__, f_globals:
+ self.assertTrue(d is advisory_testing.my_globals)
+
+ def test_inside_function_call(self):
+ from zope.interface.advice import getFrameInfo
+ kind, module, f_locals, f_globals = getFrameInfo(sys._getframe())
+ self.assertEqual(kind, "function call")
+ self.assertTrue(f_locals is locals()) # ???
+ for d in module.__dict__, f_globals:
+ self.assertTrue(d is globals())
+
+ def test_inside_exec(self):
+ from zope.interface.advice import getFrameInfo
+ _globals = {'getFrameInfo': getFrameInfo}
+ _locals = {}
+ exec(_FUNKY_EXEC, _globals, _locals)
+ self.assertEqual(_locals['kind'], "exec")
+ self.assertTrue(_locals['f_locals'] is _locals)
+ self.assertTrue(_locals['module'] is None)
+ self.assertTrue(_locals['f_globals'] is _globals)
+
+
+_FUNKY_EXEC = """\
+import sys
+kind, module, f_locals, f_globals = getFrameInfo(sys._getframe())
+"""
+
+class AdviceTests(unittest.TestCase):
+
+ @_skip_under_py3k
+ def test_order(self):
+ from .advisory_testing import ping
+ log = []
+ class Foo(object):
+ ping(log, 1)
+ ping(log, 2)
+ ping(log, 3)
+
+ # Strip the list nesting
+ for i in 1, 2, 3:
+ self.assertTrue(isinstance(Foo, list))
+ Foo, = Foo
+
+ self.assertEqual(log, [(1, Foo), (2, [Foo]), (3, [[Foo]])])
+
+ @_skip_under_py3k
+ def test_single_explicit_meta(self):
+ from .advisory_testing import ping
+
+ class Metaclass(type):
+ pass
+
+ class Concrete(Metaclass):
+ __metaclass__ = Metaclass
+ ping([],1)
+
+ Concrete, = Concrete
+ self.assertTrue(Concrete.__class__ is Metaclass)
+
+
+ @_skip_under_py3k
+ def test_mixed_metas(self):
+ from .advisory_testing import ping
+
+ class Metaclass1(type):
+ pass
+
+ class Metaclass2(type):
+ pass
+
+ class Base1:
+ __metaclass__ = Metaclass1
+
+ class Base2:
+ __metaclass__ = Metaclass2
+
+ try:
+ class Derived(Base1, Base2):
+ ping([], 1)
+ self.fail("Should have gotten incompatibility error")
+ except TypeError:
+ pass
+
+ class Metaclass3(Metaclass1, Metaclass2):
+ pass
+
+ class Derived(Base1, Base2):
+ __metaclass__ = Metaclass3
+ ping([], 1)
+
+ self.assertTrue(isinstance(Derived, list))
+ Derived, = Derived
+ self.assertTrue(isinstance(Derived, Metaclass3))
+
+ @_skip_under_py3k
+ def test_meta_no_bases(self):
+ from .advisory_testing import ping
+ from types import ClassType
+ class Thing:
+ ping([], 1)
+ klass, = Thing # unpack list created by pong
+ self.assertEqual(type(klass), ClassType)
+
+
+class Test_isClassAdvisor(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.interface.advice import isClassAdvisor
+ return isClassAdvisor(*args, **kw)
+
+ def test_w_non_function(self):
+ self.assertEqual(self._callFUT(self), False)
+
+ def test_w_normal_function(self):
+ def foo():
+ raise NotImplementedError()
+ self.assertEqual(self._callFUT(foo), False)
+
+ def test_w_advisor_function(self):
+ def bar():
+ raise NotImplementedError()
+ bar.previousMetaclass = object()
+ self.assertEqual(self._callFUT(bar), True)
+
+
+class Test_determineMetaclass(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.interface.advice import determineMetaclass
+ return determineMetaclass(*args, **kw)
+
+ @_skip_under_py3k
+ def test_empty(self):
+ from types import ClassType
+ self.assertEqual(self._callFUT(()), ClassType)
+
+ def test_empty_w_explicit_metatype(self):
+ class Meta(type):
+ pass
+ self.assertEqual(self._callFUT((), Meta), Meta)
+
+ def test_single(self):
+ class Meta(type):
+ pass
+ self.assertEqual(self._callFUT((Meta,)), type)
+
+ @_skip_under_py3k
+ def test_meta_of_class(self):
+ class Metameta(type):
+ pass
+
+ class Meta(type):
+ __metaclass__ = Metameta
+
+ self.assertEqual(self._callFUT((Meta, type)), Metameta)
+
+ @_skip_under_py2
+ def test_meta_of_class_py3k(self):
+ # Work around SyntaxError under Python2.
+ EXEC = '\n'.join([
+ 'class Metameta(type):',
+ ' pass',
+ 'class Meta(type, metaclass=Metameta):',
+ ' pass',
+ ])
+ globs = {}
+ exec(EXEC, globs)
+ Meta = globs['Meta']
+ Metameta = globs['Metameta']
+
+ self.assertEqual(self._callFUT((Meta, type)), Metameta)
+
+ @_skip_under_py3k
+ def test_multiple_in_hierarchy(self):
+ class Meta_A(type):
+ pass
+ class Meta_B(Meta_A):
+ pass
+ class A(type):
+ __metaclass__ = Meta_A
+ class B(type):
+ __metaclass__ = Meta_B
+ self.assertEqual(self._callFUT((A, B,)), Meta_B)
+
+ @_skip_under_py2
+ def test_multiple_in_hierarchy_py3k(self):
+ # Work around SyntaxError under Python2.
+ EXEC = '\n'.join([
+ 'class Meta_A(type):',
+ ' pass',
+ 'class Meta_B(Meta_A):',
+ ' pass',
+ 'class A(type, metaclass=Meta_A):',
+ ' pass',
+ 'class B(type, metaclass=Meta_B):',
+ ' pass',
+ ])
+ globs = {}
+ exec(EXEC, globs)
+ Meta_A = globs['Meta_A']
+ Meta_B = globs['Meta_B']
+ A = globs['A']
+ B = globs['B']
+ self.assertEqual(self._callFUT((A, B)), Meta_B)
+
+ @_skip_under_py3k
+ def test_multiple_not_in_hierarchy(self):
+ class Meta_A(type):
+ pass
+ class Meta_B(type):
+ pass
+ class A(type):
+ __metaclass__ = Meta_A
+ class B(type):
+ __metaclass__ = Meta_B
+ self.assertRaises(TypeError, self._callFUT, (A, B,))
+
+ @_skip_under_py2
+ def test_multiple_not_in_hierarchy_py3k(self):
+ # Work around SyntaxError under Python2.
+ EXEC = '\n'.join([
+ 'class Meta_A(type):',
+ ' pass',
+ 'class Meta_B(type):',
+ ' pass',
+ 'class A(type, metaclass=Meta_A):',
+ ' pass',
+ 'class B(type, metaclass=Meta_B):',
+ ' pass',
+ ])
+ globs = {}
+ exec(EXEC, globs)
+ Meta_A = globs['Meta_A']
+ Meta_B = globs['Meta_B']
+ A = globs['A']
+ B = globs['B']
+ self.assertRaises(TypeError, self._callFUT, (A, B))
+
+
+class Test_minimalBases(unittest.TestCase):
+
+ def _callFUT(self, klasses):
+ from zope.interface.advice import minimalBases
+ return minimalBases(klasses)
+
+ def test_empty(self):
+ self.assertEqual(self._callFUT([]), [])
+
+ @_skip_under_py3k
+ def test_w_oldstyle_meta(self):
+ class C:
+ pass
+ self.assertEqual(self._callFUT([type(C)]), [])
+
+ @_skip_under_py3k
+ def test_w_oldstyle_class(self):
+ class C:
+ pass
+ self.assertEqual(self._callFUT([C]), [C])
+
+ def test_w_newstyle_meta(self):
+ self.assertEqual(self._callFUT([type]), [type])
+
+ def test_w_newstyle_class(self):
+ class C(object):
+ pass
+ self.assertEqual(self._callFUT([C]), [C])
+
+ def test_simple_hierarchy_skips_implied(self):
+ class A(object):
+ pass
+ class B(A):
+ pass
+ class C(B):
+ pass
+ class D(object):
+ pass
+ self.assertEqual(self._callFUT([A, B, C]), [C])
+ self.assertEqual(self._callFUT([A, C]), [C])
+ self.assertEqual(self._callFUT([B, C]), [C])
+ self.assertEqual(self._callFUT([A, B]), [B])
+ self.assertEqual(self._callFUT([D, B, D]), [B, D])
+
+ def test_repeats_kicked_to_end_of_queue(self):
+ class A(object):
+ pass
+ class B(object):
+ pass
+ self.assertEqual(self._callFUT([A, B, A]), [B, A])
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/test_compile_flags.py b/contrib/python/zope.interface/py2/zope/interface/tests/test_compile_flags.py
new file mode 100644
index 0000000000..3455c445f8
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/test_compile_flags.py
@@ -0,0 +1,29 @@
+##############################################################################
+#
+# Copyright (c) 2022 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+import struct
+import unittest
+
+import zope.interface # noqa: try to load a C module for side effects
+
+
+class TestFloatingPoint(unittest.TestCase):
+
+ def test_no_fast_math_optimization(self):
+ # Building with -Ofast enables -ffast-math, which sets certain FPU
+ # flags that can cause breakage elsewhere. A library such as BTrees
+ # has no business changing global FPU flags for the entire process.
+ zero_bits = struct.unpack("!Q", struct.pack("!d", 0.0))[0]
+ next_up = zero_bits + 1
+ smallest_subnormal = struct.unpack("!d", struct.pack("!Q", next_up))[0]
+ self.assertNotEqual(smallest_subnormal, 0.0)
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/test_declarations.py b/contrib/python/zope.interface/py2/zope/interface/tests/test_declarations.py
new file mode 100644
index 0000000000..38f166f39a
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/test_declarations.py
@@ -0,0 +1,2678 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Test the new API for making and checking interface declarations
+"""
+import unittest
+
+from zope.interface._compat import _skip_under_py3k
+from zope.interface._compat import PYTHON3
+from __tests__.tests import OptimizationTestMixin
+from __tests__.tests import MissingSomeAttrs
+from __tests__.tests.test_interface import NameAndModuleComparisonTestsMixin
+
+# pylint:disable=inherit-non-class,too-many-lines,protected-access
+# pylint:disable=blacklisted-name,attribute-defined-outside-init
+
+class _Py3ClassAdvice(object):
+
+ def _run_generated_code(self, code, globs, locs,
+ fails_under_py3k=True,
+ ):
+ # pylint:disable=exec-used,no-member
+ import warnings
+ with warnings.catch_warnings(record=True) as log:
+ warnings.resetwarnings()
+ if not PYTHON3:
+ exec(code, globs, locs)
+ self.assertEqual(len(log), 0) # no longer warn
+ return True
+
+ try:
+ exec(code, globs, locs)
+ except TypeError:
+ return False
+ else:
+ if fails_under_py3k:
+ self.fail("Didn't raise TypeError")
+ return None
+
+
+class NamedTests(unittest.TestCase):
+
+ def test_class(self):
+ from zope.interface.declarations import named
+
+ @named(u'foo')
+ class Foo(object):
+ pass
+
+ self.assertEqual(Foo.__component_name__, u'foo') # pylint:disable=no-member
+
+ def test_function(self):
+ from zope.interface.declarations import named
+
+ @named(u'foo')
+ def doFoo(o):
+ raise NotImplementedError()
+
+ self.assertEqual(doFoo.__component_name__, u'foo')
+
+ def test_instance(self):
+ from zope.interface.declarations import named
+
+ class Foo(object):
+ pass
+ foo = Foo()
+ named(u'foo')(foo)
+
+ self.assertEqual(foo.__component_name__, u'foo') # pylint:disable=no-member
+
+
+class EmptyDeclarationTests(unittest.TestCase):
+ # Tests that should pass for all objects that are empty
+ # declarations. This includes a Declaration explicitly created
+ # that way, and the empty ImmutableDeclaration.
+ def _getEmpty(self):
+ from zope.interface.declarations import Declaration
+ return Declaration()
+
+ def test___iter___empty(self):
+ decl = self._getEmpty()
+ self.assertEqual(list(decl), [])
+
+ def test_flattened_empty(self):
+ from zope.interface.interface import Interface
+ decl = self._getEmpty()
+ self.assertEqual(list(decl.flattened()), [Interface])
+
+ def test___contains___empty(self):
+ from zope.interface.interface import Interface
+ decl = self._getEmpty()
+ self.assertNotIn(Interface, decl)
+
+ def test_extends_empty(self):
+ from zope.interface.interface import Interface
+ decl = self._getEmpty()
+ self.assertTrue(decl.extends(Interface))
+ self.assertTrue(decl.extends(Interface, strict=True))
+
+ def test_interfaces_empty(self):
+ decl = self._getEmpty()
+ l = list(decl.interfaces())
+ self.assertEqual(l, [])
+
+ def test___sro___(self):
+ from zope.interface.interface import Interface
+ decl = self._getEmpty()
+ self.assertEqual(decl.__sro__, (decl, Interface,))
+
+ def test___iro___(self):
+ from zope.interface.interface import Interface
+ decl = self._getEmpty()
+ self.assertEqual(decl.__iro__, (Interface,))
+
+ def test_get(self):
+ decl = self._getEmpty()
+ self.assertIsNone(decl.get('attr'))
+ self.assertEqual(decl.get('abc', 'def'), 'def')
+ # It's a positive cache only (when it even exists)
+ # so this added nothing.
+ self.assertFalse(decl._v_attrs)
+
+ def test_changed_w_existing__v_attrs(self):
+ decl = self._getEmpty()
+ decl._v_attrs = object()
+ decl.changed(decl)
+ self.assertFalse(decl._v_attrs)
+
+
+class DeclarationTests(EmptyDeclarationTests):
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import Declaration
+ return Declaration
+
+ def _makeOne(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def test_ctor_no_bases(self):
+ decl = self._makeOne()
+ self.assertEqual(list(decl.__bases__), [])
+
+ def test_ctor_w_interface_in_bases(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ decl = self._makeOne(IFoo)
+ self.assertEqual(list(decl.__bases__), [IFoo])
+
+ def test_ctor_w_implements_in_bases(self):
+ from zope.interface.declarations import Implements
+ impl = Implements()
+ decl = self._makeOne(impl)
+ self.assertEqual(list(decl.__bases__), [impl])
+
+ def test_changed_wo_existing__v_attrs(self):
+ decl = self._makeOne()
+ decl.changed(decl) # doesn't raise
+ self.assertIsNone(decl._v_attrs)
+
+ def test___contains__w_self(self):
+ decl = self._makeOne()
+ self.assertNotIn(decl, decl)
+
+ def test___contains__w_unrelated_iface(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ decl = self._makeOne()
+ self.assertNotIn(IFoo, decl)
+
+ def test___contains__w_base_interface(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ decl = self._makeOne(IFoo)
+ self.assertIn(IFoo, decl)
+
+ def test___iter___single_base(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ decl = self._makeOne(IFoo)
+ self.assertEqual(list(decl), [IFoo])
+
+ def test___iter___multiple_bases(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar')
+ decl = self._makeOne(IFoo, IBar)
+ self.assertEqual(list(decl), [IFoo, IBar])
+
+ def test___iter___inheritance(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ decl = self._makeOne(IBar)
+ self.assertEqual(list(decl), [IBar]) #IBar.interfaces() omits bases
+
+ def test___iter___w_nested_sequence_overlap(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar')
+ decl = self._makeOne(IBar, (IFoo, IBar))
+ self.assertEqual(list(decl), [IBar, IFoo])
+
+ def test_flattened_single_base(self):
+ from zope.interface.interface import Interface
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ decl = self._makeOne(IFoo)
+ self.assertEqual(list(decl.flattened()), [IFoo, Interface])
+
+ def test_flattened_multiple_bases(self):
+ from zope.interface.interface import Interface
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar')
+ decl = self._makeOne(IFoo, IBar)
+ self.assertEqual(list(decl.flattened()), [IFoo, IBar, Interface])
+
+ def test_flattened_inheritance(self):
+ from zope.interface.interface import Interface
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ decl = self._makeOne(IBar)
+ self.assertEqual(list(decl.flattened()), [IBar, IFoo, Interface])
+
+ def test_flattened_w_nested_sequence_overlap(self):
+ from zope.interface.interface import Interface
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar')
+ # This is the same as calling ``Declaration(IBar, IFoo, IBar)``
+ # which doesn't make much sense, but here it is. In older
+ # versions of zope.interface, the __iro__ would have been
+ # IFoo, IBar, Interface, which especially makes no sense.
+ decl = self._makeOne(IBar, (IFoo, IBar))
+ # Note that decl.__iro__ has IFoo first.
+ self.assertEqual(list(decl.flattened()), [IBar, IFoo, Interface])
+
+ def test___sub___unrelated_interface(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar')
+ before = self._makeOne(IFoo)
+ after = before - IBar
+ self.assertIsInstance(after, self._getTargetClass())
+ self.assertEqual(list(after), [IFoo])
+
+ def test___sub___related_interface(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ before = self._makeOne(IFoo)
+ after = before - IFoo
+ self.assertEqual(list(after), [])
+
+ def test___sub___related_interface_by_inheritance(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar', (IFoo,))
+ before = self._makeOne(IBar)
+ after = before - IBar
+ self.assertEqual(list(after), [])
+
+ def test___add___unrelated_interface(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar')
+ before = self._makeOne(IFoo)
+ after = before + IBar
+ self.assertIsInstance(after, self._getTargetClass())
+ self.assertEqual(list(after), [IFoo, IBar])
+
+ def test___add___related_interface(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar')
+ IBaz = InterfaceClass('IBaz')
+ before = self._makeOne(IFoo, IBar)
+ other = self._makeOne(IBar, IBaz)
+ after = before + other
+ self.assertEqual(list(after), [IFoo, IBar, IBaz])
+
+ def test___add___overlapping_interface(self):
+ # The derived interfaces end up with higher priority, and
+ # don't produce a C3 resolution order violation. This
+ # example produced a C3 error, and the resulting legacy order
+ # used to be wrong ([IBase, IDerived] instead of
+ # the other way).
+ from zope.interface import Interface
+ from zope.interface.interface import InterfaceClass
+ from __tests__.tests.test_ro import C3Setting
+ from zope.interface import ro
+
+ IBase = InterfaceClass('IBase')
+ IDerived = InterfaceClass('IDerived', (IBase,))
+
+ with C3Setting(ro.C3.STRICT_IRO, True):
+ base = self._makeOne(IBase)
+ after = base + IDerived
+
+ self.assertEqual(after.__iro__, (IDerived, IBase, Interface))
+ self.assertEqual(after.__bases__, (IDerived, IBase))
+ self.assertEqual(list(after), [IDerived, IBase])
+
+ def test___add___overlapping_interface_implementedBy(self):
+ # Like test___add___overlapping_interface, but pulling
+ # in a realistic example. This one previously produced a
+ # C3 error, but the resulting legacy order was (somehow)
+ # correct.
+ from zope.interface import Interface
+ from zope.interface import implementedBy
+ from zope.interface import implementer
+ from __tests__.tests.test_ro import C3Setting
+ from zope.interface import ro
+
+ class IBase(Interface):
+ pass
+
+ class IDerived(IBase):
+ pass
+
+ @implementer(IBase)
+ class Base(object):
+ pass
+
+ with C3Setting(ro.C3.STRICT_IRO, True):
+ after = implementedBy(Base) + IDerived
+
+ self.assertEqual(after.__sro__, (after, IDerived, IBase, Interface))
+ self.assertEqual(after.__bases__, (IDerived, IBase))
+ self.assertEqual(list(after), [IDerived, IBase])
+
+
+class TestImmutableDeclaration(EmptyDeclarationTests):
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import _ImmutableDeclaration
+ return _ImmutableDeclaration
+
+ def _getEmpty(self):
+ from zope.interface.declarations import _empty
+ return _empty
+
+ def test_pickle(self):
+ import pickle
+ copied = pickle.loads(pickle.dumps(self._getEmpty()))
+ self.assertIs(copied, self._getEmpty())
+
+ def test_singleton(self):
+ self.assertIs(
+ self._getTargetClass()(),
+ self._getEmpty()
+ )
+
+ def test__bases__(self):
+ self.assertEqual(self._getEmpty().__bases__, ())
+
+ def test_change__bases__(self):
+ empty = self._getEmpty()
+ empty.__bases__ = ()
+ self.assertEqual(self._getEmpty().__bases__, ())
+
+ with self.assertRaises(TypeError):
+ empty.__bases__ = (1,)
+
+ def test_dependents(self):
+ empty = self._getEmpty()
+ deps = empty.dependents
+ self.assertEqual({}, deps)
+ # Doesn't change the return.
+ deps[1] = 2
+ self.assertEqual({}, empty.dependents)
+
+ def test_changed(self):
+ # Does nothing, has no visible side-effects
+ self._getEmpty().changed(None)
+
+ def test_extends_always_false(self):
+ self.assertFalse(self._getEmpty().extends(self))
+ self.assertFalse(self._getEmpty().extends(self, strict=True))
+ self.assertFalse(self._getEmpty().extends(self, strict=False))
+
+ def test_get_always_default(self):
+ self.assertIsNone(self._getEmpty().get('name'))
+ self.assertEqual(self._getEmpty().get('name', 42), 42)
+
+ def test_v_attrs(self):
+ decl = self._getEmpty()
+ self.assertEqual(decl._v_attrs, {})
+
+ decl._v_attrs['attr'] = 42
+ self.assertEqual(decl._v_attrs, {})
+ self.assertIsNone(decl.get('attr'))
+
+ attrs = decl._v_attrs = {}
+ attrs['attr'] = 42
+ self.assertEqual(decl._v_attrs, {})
+ self.assertIsNone(decl.get('attr'))
+
+
+class TestImplements(NameAndModuleComparisonTestsMixin,
+ unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import Implements
+ return Implements
+
+ def _makeOne(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def _makeOneToCompare(self):
+ from zope.interface.declarations import implementedBy
+ class A(object):
+ pass
+
+ return implementedBy(A)
+
+ def test_ctor_no_bases(self):
+ impl = self._makeOne()
+ self.assertEqual(impl.inherit, None)
+ self.assertEqual(impl.declared, ())
+ self.assertEqual(impl.__name__, '?')
+ self.assertEqual(list(impl.__bases__), [])
+
+ def test___repr__(self):
+ impl = self._makeOne()
+ impl.__name__ = 'Testing'
+ self.assertEqual(repr(impl), 'classImplements(Testing)')
+
+ def test___reduce__(self):
+ from zope.interface.declarations import implementedBy
+ impl = self._makeOne()
+ self.assertEqual(impl.__reduce__(), (implementedBy, (None,)))
+
+ def test_sort(self):
+ from zope.interface.declarations import implementedBy
+ class A(object):
+ pass
+ class B(object):
+ pass
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+
+ self.assertEqual(implementedBy(A), implementedBy(A))
+ self.assertEqual(hash(implementedBy(A)), hash(implementedBy(A)))
+ self.assertTrue(implementedBy(A) < None)
+ self.assertTrue(None > implementedBy(A)) # pylint:disable=misplaced-comparison-constant
+ self.assertTrue(implementedBy(A) < implementedBy(B))
+ self.assertTrue(implementedBy(A) > IFoo)
+ self.assertTrue(implementedBy(A) <= implementedBy(B))
+ self.assertTrue(implementedBy(A) >= IFoo)
+ self.assertTrue(implementedBy(A) != IFoo)
+
+ def test_proxy_equality(self):
+ # https://github.com/zopefoundation/zope.interface/issues/55
+ class Proxy(object):
+ def __init__(self, wrapped):
+ self._wrapped = wrapped
+
+ def __getattr__(self, name):
+ raise NotImplementedError()
+
+ def __eq__(self, other):
+ return self._wrapped == other
+
+ def __ne__(self, other):
+ return self._wrapped != other
+
+ from zope.interface.declarations import implementedBy
+ class A(object):
+ pass
+
+ class B(object):
+ pass
+
+ implementedByA = implementedBy(A)
+ implementedByB = implementedBy(B)
+ proxy = Proxy(implementedByA)
+
+ # The order of arguments to the operators matters,
+ # test both
+ self.assertTrue(implementedByA == implementedByA) # pylint:disable=comparison-with-itself
+ self.assertTrue(implementedByA != implementedByB)
+ self.assertTrue(implementedByB != implementedByA)
+
+ self.assertTrue(proxy == implementedByA)
+ self.assertTrue(implementedByA == proxy)
+ self.assertFalse(proxy != implementedByA)
+ self.assertFalse(implementedByA != proxy)
+
+ self.assertTrue(proxy != implementedByB)
+ self.assertTrue(implementedByB != proxy)
+
+ def test_changed_deletes_super_cache(self):
+ impl = self._makeOne()
+ self.assertIsNone(impl._super_cache)
+ self.assertNotIn('_super_cache', impl.__dict__)
+
+ impl._super_cache = 42
+ self.assertIn('_super_cache', impl.__dict__)
+
+ impl.changed(None)
+ self.assertIsNone(impl._super_cache)
+ self.assertNotIn('_super_cache', impl.__dict__)
+
+ def test_changed_does_not_add_super_cache(self):
+ impl = self._makeOne()
+ self.assertIsNone(impl._super_cache)
+ self.assertNotIn('_super_cache', impl.__dict__)
+
+ impl.changed(None)
+ self.assertIsNone(impl._super_cache)
+ self.assertNotIn('_super_cache', impl.__dict__)
+
+
+class Test_implementedByFallback(unittest.TestCase):
+
+ def _getTargetClass(self):
+ # pylint:disable=no-name-in-module
+ from zope.interface.declarations import implementedByFallback
+ return implementedByFallback
+
+ _getFallbackClass = _getTargetClass
+
+ def _callFUT(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def test_dictless_wo_existing_Implements_wo_registrations(self):
+ class Foo(object):
+ __slots__ = ('__implemented__',)
+ foo = Foo()
+ foo.__implemented__ = None
+ self.assertEqual(list(self._callFUT(foo)), [])
+
+ def test_dictless_wo_existing_Implements_cant_assign___implemented__(self):
+ class Foo(object):
+ def _get_impl(self):
+ raise NotImplementedError()
+ def _set_impl(self, val):
+ raise TypeError
+ __implemented__ = property(_get_impl, _set_impl)
+ def __call__(self):
+ # act like a factory
+ raise NotImplementedError()
+ foo = Foo()
+ self.assertRaises(TypeError, self._callFUT, foo)
+
+ def test_dictless_wo_existing_Implements_w_registrations(self):
+ from zope.interface import declarations
+ class Foo(object):
+ __slots__ = ('__implemented__',)
+ foo = Foo()
+ foo.__implemented__ = None
+ reg = object()
+ with _MonkeyDict(declarations,
+ 'BuiltinImplementationSpecifications') as specs:
+ specs[foo] = reg
+ self.assertTrue(self._callFUT(foo) is reg)
+
+ def test_dictless_w_existing_Implements(self):
+ from zope.interface.declarations import Implements
+ impl = Implements()
+ class Foo(object):
+ __slots__ = ('__implemented__',)
+ foo = Foo()
+ foo.__implemented__ = impl
+ self.assertTrue(self._callFUT(foo) is impl)
+
+ def test_dictless_w_existing_not_Implements(self):
+ from zope.interface.interface import InterfaceClass
+ class Foo(object):
+ __slots__ = ('__implemented__',)
+ foo = Foo()
+ IFoo = InterfaceClass('IFoo')
+ foo.__implemented__ = (IFoo,)
+ self.assertEqual(list(self._callFUT(foo)), [IFoo])
+
+ def test_w_existing_attr_as_Implements(self):
+ from zope.interface.declarations import Implements
+ impl = Implements()
+ class Foo(object):
+ __implemented__ = impl
+ self.assertTrue(self._callFUT(Foo) is impl)
+
+ def test_builtins_added_to_cache(self):
+ from zope.interface import declarations
+ from zope.interface.declarations import Implements
+ with _MonkeyDict(declarations,
+ 'BuiltinImplementationSpecifications') as specs:
+ self.assertEqual(list(self._callFUT(tuple)), [])
+ self.assertEqual(list(self._callFUT(list)), [])
+ self.assertEqual(list(self._callFUT(dict)), [])
+ for typ in (tuple, list, dict):
+ spec = specs[typ]
+ self.assertIsInstance(spec, Implements)
+ self.assertEqual(repr(spec),
+ 'classImplements(%s)'
+ % (typ.__name__,))
+
+ def test_builtins_w_existing_cache(self):
+ from zope.interface import declarations
+ t_spec, l_spec, d_spec = object(), object(), object()
+ with _MonkeyDict(declarations,
+ 'BuiltinImplementationSpecifications') as specs:
+ specs[tuple] = t_spec
+ specs[list] = l_spec
+ specs[dict] = d_spec
+ self.assertTrue(self._callFUT(tuple) is t_spec)
+ self.assertTrue(self._callFUT(list) is l_spec)
+ self.assertTrue(self._callFUT(dict) is d_spec)
+
+ def test_oldstyle_class_no_assertions(self):
+ # TODO: Figure out P3 story
+ class Foo:
+ pass
+ self.assertEqual(list(self._callFUT(Foo)), [])
+
+ def test_no_assertions(self):
+ # TODO: Figure out P3 story
+ class Foo(object):
+ pass
+ self.assertEqual(list(self._callFUT(Foo)), [])
+
+ def test_w_None_no_bases_not_factory(self):
+ class Foo(object):
+ __implemented__ = None
+ foo = Foo()
+ self.assertRaises(TypeError, self._callFUT, foo)
+
+ def test_w_None_no_bases_w_factory(self):
+ from zope.interface.declarations import objectSpecificationDescriptor
+ class Foo(object):
+ __implemented__ = None
+ def __call__(self):
+ raise NotImplementedError()
+
+ foo = Foo()
+ foo.__name__ = 'foo'
+ spec = self._callFUT(foo)
+ self.assertEqual(spec.__name__,
+ '__tests__.tests.test_declarations.foo')
+ self.assertIs(spec.inherit, foo)
+ self.assertIs(foo.__implemented__, spec)
+ self.assertIs(foo.__providedBy__, objectSpecificationDescriptor) # pylint:disable=no-member
+ self.assertNotIn('__provides__', foo.__dict__)
+
+ def test_w_None_no_bases_w_class(self):
+ from zope.interface.declarations import ClassProvides
+ class Foo(object):
+ __implemented__ = None
+ spec = self._callFUT(Foo)
+ self.assertEqual(spec.__name__,
+ '__tests__.tests.test_declarations.Foo')
+ self.assertIs(spec.inherit, Foo)
+ self.assertIs(Foo.__implemented__, spec)
+ self.assertIsInstance(Foo.__providedBy__, ClassProvides) # pylint:disable=no-member
+ self.assertIsInstance(Foo.__provides__, ClassProvides) # pylint:disable=no-member
+ self.assertEqual(Foo.__provides__, Foo.__providedBy__) # pylint:disable=no-member
+
+ def test_w_existing_Implements(self):
+ from zope.interface.declarations import Implements
+ impl = Implements()
+ class Foo(object):
+ __implemented__ = impl
+ self.assertTrue(self._callFUT(Foo) is impl)
+
+ def test_super_when_base_implements_interface(self):
+ from zope.interface import Interface
+ from zope.interface.declarations import implementer
+
+ class IBase(Interface):
+ pass
+
+ class IDerived(IBase):
+ pass
+
+ @implementer(IBase)
+ class Base(object):
+ pass
+
+ @implementer(IDerived)
+ class Derived(Base):
+ pass
+
+ self.assertEqual(list(self._callFUT(Derived)), [IDerived, IBase])
+ sup = super(Derived, Derived)
+ self.assertEqual(list(self._callFUT(sup)), [IBase])
+
+ def test_super_when_base_implements_interface_diamond(self):
+ from zope.interface import Interface
+ from zope.interface.declarations import implementer
+
+ class IBase(Interface):
+ pass
+
+ class IDerived(IBase):
+ pass
+
+ @implementer(IBase)
+ class Base(object):
+ pass
+
+ class Child1(Base):
+ pass
+
+ class Child2(Base):
+ pass
+
+ @implementer(IDerived)
+ class Derived(Child1, Child2):
+ pass
+
+ self.assertEqual(list(self._callFUT(Derived)), [IDerived, IBase])
+ sup = super(Derived, Derived)
+ self.assertEqual(list(self._callFUT(sup)), [IBase])
+
+ def test_super_when_parent_implements_interface_diamond(self):
+ from zope.interface import Interface
+ from zope.interface.declarations import implementer
+
+ class IBase(Interface):
+ pass
+
+ class IDerived(IBase):
+ pass
+
+
+ class Base(object):
+ pass
+
+ class Child1(Base):
+ pass
+
+ @implementer(IBase)
+ class Child2(Base):
+ pass
+
+ @implementer(IDerived)
+ class Derived(Child1, Child2):
+ pass
+
+ self.assertEqual(Derived.__mro__, (Derived, Child1, Child2, Base, object))
+ self.assertEqual(list(self._callFUT(Derived)), [IDerived, IBase])
+ sup = super(Derived, Derived)
+ fut = self._callFUT(sup)
+ self.assertEqual(list(fut), [IBase])
+ self.assertIsNone(fut._dependents)
+
+ def test_super_when_base_doesnt_implement_interface(self):
+ from zope.interface import Interface
+ from zope.interface.declarations import implementer
+
+ class IBase(Interface):
+ pass
+
+ class IDerived(IBase):
+ pass
+
+ class Base(object):
+ pass
+
+ @implementer(IDerived)
+ class Derived(Base):
+ pass
+
+ self.assertEqual(list(self._callFUT(Derived)), [IDerived])
+
+ sup = super(Derived, Derived)
+ self.assertEqual(list(self._callFUT(sup)), [])
+
+ def test_super_when_base_is_object(self):
+ from zope.interface import Interface
+ from zope.interface.declarations import implementer
+
+ class IBase(Interface):
+ pass
+
+ class IDerived(IBase):
+ pass
+
+ @implementer(IDerived)
+ class Derived(object):
+ pass
+
+ self.assertEqual(list(self._callFUT(Derived)), [IDerived])
+
+ sup = super(Derived, Derived)
+ self.assertEqual(list(self._callFUT(sup)), [])
+ def test_super_multi_level_multi_inheritance(self):
+ from zope.interface.declarations import implementer
+ from zope.interface import Interface
+
+ class IBase(Interface):
+ pass
+
+ class IM1(Interface):
+ pass
+
+ class IM2(Interface):
+ pass
+
+ class IDerived(IBase):
+ pass
+
+ class IUnrelated(Interface):
+ pass
+
+ @implementer(IBase)
+ class Base(object):
+ pass
+
+ @implementer(IM1)
+ class M1(Base):
+ pass
+
+ @implementer(IM2)
+ class M2(Base):
+ pass
+
+ @implementer(IDerived, IUnrelated)
+ class Derived(M1, M2):
+ pass
+
+ d = Derived
+ sd = super(Derived, Derived)
+ sm1 = super(M1, Derived)
+ sm2 = super(M2, Derived)
+
+ self.assertEqual(list(self._callFUT(d)),
+ [IDerived, IUnrelated, IM1, IBase, IM2])
+ self.assertEqual(list(self._callFUT(sd)),
+ [IM1, IBase, IM2])
+ self.assertEqual(list(self._callFUT(sm1)),
+ [IM2, IBase])
+ self.assertEqual(list(self._callFUT(sm2)),
+ [IBase])
+
+
+class Test_implementedBy(Test_implementedByFallback,
+ OptimizationTestMixin):
+ # Repeat tests for C optimizations
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import implementedBy
+ return implementedBy
+
+
+class _ImplementsTestMixin(object):
+ FUT_SETS_PROVIDED_BY = True
+
+ def _callFUT(self, cls, iface):
+ # Declare that *cls* implements *iface*; return *cls*
+ raise NotImplementedError
+
+ def _check_implementer(self, Foo,
+ orig_spec=None,
+ spec_name=__name__ + '.Foo',
+ inherit="not given"):
+ from zope.interface.declarations import ClassProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+
+ returned = self._callFUT(Foo, IFoo)
+
+ self.assertIs(returned, Foo)
+ spec = Foo.__implemented__
+ if orig_spec is not None:
+ self.assertIs(spec, orig_spec)
+
+ self.assertEqual(spec.__name__,
+ spec_name)
+ inherit = Foo if inherit == "not given" else inherit
+ self.assertIs(spec.inherit, inherit)
+ self.assertIs(Foo.__implemented__, spec)
+ if self.FUT_SETS_PROVIDED_BY:
+ self.assertIsInstance(Foo.__providedBy__, ClassProvides)
+ self.assertIsInstance(Foo.__provides__, ClassProvides)
+ self.assertEqual(Foo.__provides__, Foo.__providedBy__)
+
+ return Foo, IFoo
+
+ def test_oldstyle_class(self):
+ # This only matters on Python 2
+ class Foo:
+ pass
+ self._check_implementer(Foo)
+
+ def test_newstyle_class(self):
+ class Foo(object):
+ pass
+ self._check_implementer(Foo)
+
+class Test_classImplementsOnly(_ImplementsTestMixin, unittest.TestCase):
+ FUT_SETS_PROVIDED_BY = False
+
+ def _callFUT(self, cls, iface):
+ from zope.interface.declarations import classImplementsOnly
+ classImplementsOnly(cls, iface)
+ return cls
+
+ def test_w_existing_Implements(self):
+ from zope.interface.declarations import Implements
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar')
+ impl = Implements(IFoo)
+ impl.declared = (IFoo,)
+ class Foo(object):
+ __implemented__ = impl
+ impl.inherit = Foo
+ self._callFUT(Foo, IBar)
+ # Same spec, now different values
+ self.assertTrue(Foo.__implemented__ is impl)
+ self.assertEqual(impl.inherit, None)
+ self.assertEqual(impl.declared, (IBar,))
+
+ def test_oldstyle_class(self):
+ from zope.interface.declarations import Implements
+ from zope.interface.interface import InterfaceClass
+ IBar = InterfaceClass('IBar')
+ old_spec = Implements(IBar)
+
+ class Foo:
+ __implemented__ = old_spec
+ self._check_implementer(Foo, old_spec, '?', inherit=None)
+
+ def test_newstyle_class(self):
+ from zope.interface.declarations import Implements
+ from zope.interface.interface import InterfaceClass
+ IBar = InterfaceClass('IBar')
+ old_spec = Implements(IBar)
+
+ class Foo(object):
+ __implemented__ = old_spec
+ self._check_implementer(Foo, old_spec, '?', inherit=None)
+
+
+ def test_redundant_with_super_still_implements(self):
+ Base, IBase = self._check_implementer(
+ type('Foo', (object,), {}),
+ inherit=None,
+ )
+
+ class Child(Base):
+ pass
+
+ self._callFUT(Child, IBase)
+ self.assertTrue(IBase.implementedBy(Child))
+
+
+class Test_classImplements(_ImplementsTestMixin, unittest.TestCase):
+
+ def _callFUT(self, cls, iface):
+ from zope.interface.declarations import classImplements
+ result = classImplements(cls, iface) # pylint:disable=assignment-from-no-return
+ self.assertIsNone(result)
+ return cls
+
+ def __check_implementer_redundant(self, Base):
+ # If we @implementer exactly what was already present, we write
+ # no declared attributes on the parent (we still set everything, though)
+ Base, IBase = self._check_implementer(Base)
+
+ class Child(Base):
+ pass
+
+ returned = self._callFUT(Child, IBase)
+ self.assertIn('__implemented__', returned.__dict__)
+ self.assertNotIn('__providedBy__', returned.__dict__)
+ self.assertIn('__provides__', returned.__dict__)
+
+ spec = Child.__implemented__
+ self.assertEqual(spec.declared, ())
+ self.assertEqual(spec.inherit, Child)
+
+ self.assertTrue(IBase.providedBy(Child()))
+
+ def test_redundant_implementer_empty_class_declarations_newstyle(self):
+ self.__check_implementer_redundant(type('Foo', (object,), {}))
+
+ def test_redundant_implementer_empty_class_declarations_oldstyle(self):
+ # This only matters on Python 2
+ class Foo:
+ 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 __tests__.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)
+
+ def test_w_existing_Implements(self):
+ from zope.interface.declarations import Implements
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar')
+ impl = Implements(IFoo)
+ impl.declared = (IFoo,)
+ class Foo(object):
+ __implemented__ = impl
+ impl.inherit = Foo
+ self._callFUT(Foo, IBar)
+ # Same spec, now different values
+ self.assertIs(Foo.__implemented__, impl)
+ self.assertEqual(impl.inherit, Foo)
+ self.assertEqual(impl.declared,
+ self._order_for_two(IFoo, IBar))
+
+ def test_w_existing_Implements_w_bases(self):
+ from zope.interface.declarations import Implements
+ from zope.interface.interface import InterfaceClass
+ 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.assertIs(ExtendsRoot.__implemented__, impl_extends_root)
+ self.assertEqual(impl_extends_root.inherit, ExtendsRoot)
+ self.assertEqual(impl_extends_root.declared,
+ self._order_for_two(IExtendsRoot, ISecondRoot,))
+ self.assertEqual(impl_extends_root.__bases__,
+ self._order_for_two(IExtendsRoot, ISecondRoot) + (impl_root,))
+
+
+class Test_classImplementsFirst(Test_classImplements):
+
+ def _callFUT(self, cls, iface):
+ from zope.interface.declarations import classImplementsFirst
+ result = classImplementsFirst(cls, iface) # pylint:disable=assignment-from-no-return
+ self.assertIsNone(result)
+ return cls
+
+ def _order_for_two(self, applied_first, applied_second):
+ return (applied_second, applied_first)
+
+
+class Test__implements_advice(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.interface.declarations import _implements_advice
+ return _implements_advice(*args, **kw)
+
+ def test_no_existing_implements(self):
+ from zope.interface.declarations import classImplements
+ from zope.interface.declarations import Implements
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ class Foo(object):
+ __implements_advice_data__ = ((IFoo,), classImplements)
+ self._callFUT(Foo)
+ self.assertNotIn('__implements_advice_data__', Foo.__dict__)
+ self.assertIsInstance(Foo.__implemented__, Implements) # pylint:disable=no-member
+ self.assertEqual(list(Foo.__implemented__), [IFoo]) # pylint:disable=no-member
+
+
+class Test_implementer(Test_classImplements):
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import implementer
+ return implementer
+
+ def _makeOne(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def _callFUT(self, cls, *ifaces):
+ decorator = self._makeOne(*ifaces)
+ return decorator(cls)
+
+ def test_nonclass_cannot_assign_attr(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ decorator = self._makeOne(IFoo)
+ self.assertRaises(TypeError, decorator, object())
+
+ def test_nonclass_can_assign_attr(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ class Foo(object):
+ pass
+ foo = Foo()
+ decorator = self._makeOne(IFoo)
+ returned = decorator(foo)
+ self.assertTrue(returned is foo)
+ spec = foo.__implemented__ # pylint:disable=no-member
+ self.assertEqual(spec.__name__, '__tests__.tests.test_declarations.?')
+ self.assertIsNone(spec.inherit,)
+ self.assertIs(foo.__implemented__, spec) # pylint:disable=no-member
+
+ def test_does_not_leak_on_unique_classes(self):
+ # Make sure nothing is hanging on to the class or Implements
+ # object after they go out of scope. There was briefly a bug
+ # in 5.x that caused SpecificationBase._bases (in C) to not be
+ # traversed or cleared.
+ # https://github.com/zopefoundation/zope.interface/issues/216
+ import gc
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+
+ begin_count = len(gc.get_objects())
+
+ for _ in range(1900):
+ class TestClass(object):
+ pass
+
+ self._callFUT(TestClass, IFoo)
+
+ gc.collect()
+
+ end_count = len(gc.get_objects())
+
+ # How many new objects might still be around? In all currently
+ # tested interpreters, there aren't any, so our counts should
+ # match exactly. When the bug existed, in a steady state, the loop
+ # would grow by two objects each iteration
+ fudge_factor = 0
+ self.assertLessEqual(end_count, begin_count + fudge_factor)
+
+
+
+class Test_implementer_only(Test_classImplementsOnly):
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import implementer_only
+ return implementer_only
+
+ def _makeOne(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def _callFUT(self, cls, iface):
+ decorator = self._makeOne(iface)
+ return decorator(cls)
+
+ def test_function(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ decorator = self._makeOne(IFoo)
+ def _function():
+ raise NotImplementedError()
+ self.assertRaises(ValueError, decorator, _function)
+
+ def test_method(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass('IFoo')
+ decorator = self._makeOne(IFoo)
+ class Bar:
+ def _method(self):
+ raise NotImplementedError()
+ self.assertRaises(ValueError, decorator, Bar._method)
+
+
+
+# Test '_implements' by way of 'implements{,Only}', its only callers.
+
+class Test_implementsOnly(unittest.TestCase, _Py3ClassAdvice):
+
+ def test_simple(self):
+ import warnings
+ from zope.interface.declarations import implementsOnly
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ globs = {'implementsOnly': implementsOnly,
+ 'IFoo': IFoo,
+ }
+ locs = {}
+ CODE = "\n".join([
+ 'class Foo(object):'
+ ' implementsOnly(IFoo)',
+ ])
+ with warnings.catch_warnings(record=True) as log:
+ warnings.resetwarnings()
+ try:
+ exec(CODE, globs, locs) # pylint:disable=exec-used
+ except TypeError:
+ self.assertTrue(PYTHON3, "Must be Python 3")
+ else:
+ if PYTHON3:
+ self.fail("Didn't raise TypeError")
+ Foo = locs['Foo']
+ spec = Foo.__implemented__
+ self.assertEqual(list(spec), [IFoo])
+ self.assertEqual(len(log), 0) # no longer warn
+
+ def test_called_once_from_class_w_bases(self):
+ from zope.interface.declarations import implements
+ from zope.interface.declarations import implementsOnly
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ IBar = InterfaceClass("IBar")
+ globs = {'implements': implements,
+ 'implementsOnly': implementsOnly,
+ 'IFoo': IFoo,
+ 'IBar': IBar,
+ }
+ locs = {}
+ CODE = "\n".join([
+ 'class Foo(object):',
+ ' implements(IFoo)',
+ 'class Bar(Foo):'
+ ' implementsOnly(IBar)',
+ ])
+ if self._run_generated_code(CODE, globs, locs):
+ Bar = locs['Bar']
+ spec = Bar.__implemented__
+ self.assertEqual(list(spec), [IBar])
+
+
+class Test_implements(unittest.TestCase, _Py3ClassAdvice):
+
+ def test_called_from_function(self):
+ import warnings
+ from zope.interface.declarations import implements
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ globs = {'implements': implements, 'IFoo': IFoo}
+ locs = {}
+ CODE = "\n".join([
+ 'def foo():',
+ ' implements(IFoo)'
+ ])
+ if self._run_generated_code(CODE, globs, locs, False):
+ foo = locs['foo']
+ with warnings.catch_warnings(record=True) as log:
+ warnings.resetwarnings()
+ self.assertRaises(TypeError, foo)
+ self.assertEqual(len(log), 0) # no longer warn
+
+ def test_called_twice_from_class(self):
+ import warnings
+ from zope.interface.declarations import implements
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ IBar = InterfaceClass("IBar")
+ globs = {'implements': implements, 'IFoo': IFoo, 'IBar': IBar}
+ locs = {}
+ CODE = "\n".join([
+ 'class Foo(object):',
+ ' implements(IFoo)',
+ ' implements(IBar)',
+ ])
+ with warnings.catch_warnings(record=True) as log:
+ warnings.resetwarnings()
+ try:
+ exec(CODE, globs, locs) # pylint:disable=exec-used
+ except TypeError:
+ if not PYTHON3:
+ self.assertEqual(len(log), 0) # no longer warn
+ else:
+ self.fail("Didn't raise TypeError")
+
+ def test_called_once_from_class(self):
+ from zope.interface.declarations import implements
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ globs = {'implements': implements, 'IFoo': IFoo}
+ locs = {}
+ CODE = "\n".join([
+ 'class Foo(object):',
+ ' implements(IFoo)',
+ ])
+ if self._run_generated_code(CODE, globs, locs):
+ Foo = locs['Foo']
+ spec = Foo.__implemented__
+ self.assertEqual(list(spec), [IFoo])
+
+
+class ProvidesClassTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import ProvidesClass
+ return ProvidesClass
+
+ def _makeOne(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def test_simple_class_one_interface(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ spec = self._makeOne(Foo, IFoo)
+ self.assertEqual(list(spec), [IFoo])
+
+ def test___reduce__(self):
+ from zope.interface.declarations import Provides # the function
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ spec = self._makeOne(Foo, IFoo)
+ klass, args = spec.__reduce__()
+ self.assertIs(klass, Provides)
+ self.assertEqual(args, (Foo, IFoo))
+
+ def test___get___class(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ spec = self._makeOne(Foo, IFoo)
+ Foo.__provides__ = spec
+ self.assertIs(Foo.__provides__, spec)
+
+ def test___get___instance(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ spec = self._makeOne(Foo, IFoo)
+ Foo.__provides__ = spec
+ def _test():
+ foo = Foo()
+ return foo.__provides__
+ self.assertRaises(AttributeError, _test)
+
+
+class ProvidesClassStrictTests(ProvidesClassTests):
+ # Tests that require the strict C3 resolution order.
+
+ def _getTargetClass(self):
+ ProvidesClass = super(ProvidesClassStrictTests, self)._getTargetClass()
+ class StrictProvides(ProvidesClass):
+ def _do_calculate_ro(self, base_mros):
+ return ProvidesClass._do_calculate_ro(self, base_mros=base_mros, strict=True)
+ return StrictProvides
+
+ def test_overlapping_interfaces_corrected(self):
+ # Giving Provides(cls, IFace), where IFace is already
+ # provided by cls, doesn't produce invalid resolution orders.
+ from zope.interface import implementedBy
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class IBase(Interface):
+ pass
+
+ @implementer(IBase)
+ class Base(object):
+ pass
+
+ spec = self._makeOne(Base, IBase)
+ self.assertEqual(spec.__sro__, (
+ spec,
+ implementedBy(Base),
+ IBase,
+ implementedBy(object),
+ Interface
+ ))
+
+
+class TestProvidesClassRepr(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import ProvidesClass
+ return ProvidesClass
+
+ def _makeOne(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def test__repr__(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ assert IFoo.__name__ == 'IFoo'
+ assert IFoo.__module__ == __name__
+ assert repr(IFoo) == '<InterfaceClass %s.IFoo>' % (__name__,)
+
+ IBar = InterfaceClass("IBar")
+
+ inst = self._makeOne(type(self), IFoo, IBar)
+ self.assertEqual(
+ repr(inst),
+ "directlyProvides(TestProvidesClassRepr, IFoo, IBar)"
+ )
+
+ def test__repr__module_provides_typical_use(self):
+ # as created through a ``moduleProvides()`` statement
+ # in a module body
+ from __tests__.tests import dummy
+ provides = dummy.__provides__ # pylint:disable=no-member
+ self.assertEqual(
+ repr(provides),
+ "directlyProvides(sys.modules['__tests__.tests.dummy'], IDummyModule)"
+ )
+
+ def test__repr__module_after_pickle(self):
+ # It doesn't matter, these objects can't be pickled.
+ import pickle
+ from __tests__.tests import dummy
+ provides = dummy.__provides__ # pylint:disable=no-member
+ for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+ with self.assertRaises(pickle.PicklingError):
+ pickle.dumps(provides, proto)
+
+ def test__repr__directlyProvides_module(self):
+ import sys
+ from __tests__.tests import dummy
+ from zope.interface.declarations import directlyProvides
+ from zope.interface.declarations import alsoProvides
+ from zope.interface.interface import InterfaceClass
+
+ IFoo = InterfaceClass('IFoo')
+ IBar = InterfaceClass('IBar')
+
+ orig_provides = dummy.__provides__ # pylint:disable=no-member
+ del dummy.__provides__ # pylint:disable=no-member
+ self.addCleanup(setattr, dummy, '__provides__', orig_provides)
+
+ directlyProvides(dummy, IFoo)
+ provides = dummy.__provides__ # pylint:disable=no-member
+
+ self.assertEqual(
+ repr(provides),
+ "directlyProvides(sys.modules['__tests__.tests.dummy'], IFoo)"
+ )
+
+ alsoProvides(dummy, IBar)
+ provides = dummy.__provides__ # pylint:disable=no-member
+
+ self.assertEqual(
+ repr(provides),
+ "directlyProvides(sys.modules['__tests__.tests.dummy'], IFoo, IBar)"
+ )
+
+ # If we make this module also provide IFoo and IBar, then the repr
+ # lists both names.
+ my_module = sys.modules[__name__]
+ assert not hasattr(my_module, '__provides__')
+
+ directlyProvides(my_module, IFoo, IBar)
+ self.addCleanup(delattr, my_module, '__provides__')
+ self.assertIs(my_module.__provides__, provides)
+ self.assertEqual(
+ repr(provides),
+ "directlyProvides(('__tests__.tests.dummy', "
+ "'__tests__.tests.test_declarations'), "
+ "IFoo, IBar)"
+ )
+
+ def test__repr__module_provides_cached_shared(self):
+ from zope.interface.interface import InterfaceClass
+ from zope.interface.declarations import ModuleType
+ IFoo = InterfaceClass("IFoo")
+
+ inst = self._makeOne(ModuleType, IFoo)
+ inst._v_module_names += ('some.module',)
+ inst._v_module_names += ('another.module',)
+ self.assertEqual(
+ repr(inst),
+ "directlyProvides(('some.module', 'another.module'), IFoo)"
+ )
+
+ def test__repr__duplicate_names(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo", __module__='mod1')
+ IFoo2 = InterfaceClass("IFoo", __module__='mod2')
+ IBaz = InterfaceClass("IBaz")
+
+ inst = self._makeOne(type(self), IFoo, IBaz, IFoo2)
+ self.assertEqual(
+ repr(inst),
+ "directlyProvides(TestProvidesClassRepr, IFoo, IBaz, mod2.IFoo)"
+ )
+
+ def test__repr__implementedBy_in_interfaces(self):
+ from zope.interface import Interface
+ from zope.interface import implementedBy
+ class IFoo(Interface):
+ "Does nothing"
+
+ class Bar(object):
+ "Does nothing"
+
+ impl = implementedBy(type(self))
+
+ inst = self._makeOne(Bar, IFoo, impl)
+ self.assertEqual(
+ repr(inst),
+ 'directlyProvides(Bar, IFoo, classImplements(TestProvidesClassRepr))'
+ )
+
+ def test__repr__empty_interfaces(self):
+ inst = self._makeOne(type(self))
+ self.assertEqual(
+ repr(inst),
+ 'directlyProvides(TestProvidesClassRepr)',
+ )
+
+ def test__repr__non_class(self):
+ class Object(object):
+ __bases__ = ()
+ __str__ = lambda _: self.fail("Should not call str")
+
+ def __repr__(self):
+ return '<Object>'
+ inst = self._makeOne(Object())
+ self.assertEqual(
+ repr(inst),
+ 'directlyProvides(<Object>)',
+ )
+
+ def test__repr__providedBy_from_class(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.declarations import providedBy
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+
+ inst = providedBy(Foo())
+ self.assertEqual(
+ repr(inst),
+ 'classImplements(Foo, IFoo)'
+ )
+
+ def test__repr__providedBy_alsoProvides(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.declarations import providedBy
+ from zope.interface.declarations import alsoProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ IBar = InterfaceClass("IBar")
+
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+
+ foo = Foo()
+ alsoProvides(foo, IBar)
+
+ inst = providedBy(foo)
+ self.assertEqual(
+ repr(inst),
+ "directlyProvides(Foo, IBar, classImplements(Foo, IFoo))"
+ )
+
+
+
+class Test_Provides(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.interface.declarations import Provides
+ return Provides(*args, **kw)
+
+ def test_no_cached_spec(self):
+ from zope.interface import declarations
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ cache = {}
+ class Foo(object):
+ pass
+ with _Monkey(declarations, InstanceDeclarations=cache):
+ spec = self._callFUT(Foo, IFoo)
+ self.assertEqual(list(spec), [IFoo])
+ self.assertTrue(cache[(Foo, IFoo)] is spec)
+
+ def test_w_cached_spec(self):
+ from zope.interface import declarations
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ prior = object()
+ class Foo(object):
+ pass
+ cache = {(Foo, IFoo): prior}
+ with _Monkey(declarations, InstanceDeclarations=cache):
+ spec = self._callFUT(Foo, IFoo)
+ self.assertTrue(spec is prior)
+
+
+class Test_directlyProvides(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.interface.declarations import directlyProvides
+ return directlyProvides(*args, **kw)
+
+ def test_w_normal_object(self):
+ from zope.interface.declarations import ProvidesClass
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ obj = Foo()
+ self._callFUT(obj, IFoo)
+ self.assertIsInstance(obj.__provides__, ProvidesClass) # pylint:disable=no-member
+ self.assertEqual(list(obj.__provides__), [IFoo]) # pylint:disable=no-member
+
+ def test_w_class(self):
+ from zope.interface.declarations import ClassProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ self._callFUT(Foo, IFoo)
+ self.assertIsInstance(Foo.__provides__, ClassProvides) # pylint:disable=no-member
+ self.assertEqual(list(Foo.__provides__), [IFoo]) # pylint:disable=no-member
+
+ @_skip_under_py3k
+ def test_w_non_descriptor_aware_metaclass(self):
+ # There are no non-descriptor-aware types in Py3k
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class MetaClass(type):
+ def __getattribute__(cls, name):
+ # Emulate metaclass whose base is not the type object.
+ if name == '__class__':
+ return cls
+ # Under certain circumstances, the implementedByFallback
+ # can get here for __dict__
+ return type.__getattribute__(cls, name) # pragma: no cover
+
+ class Foo(object):
+ __metaclass__ = MetaClass
+ obj = Foo()
+ self.assertRaises(TypeError, self._callFUT, obj, IFoo)
+
+ def test_w_classless_object(self):
+ from zope.interface.declarations import ProvidesClass
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ the_dict = {}
+ class Foo(object):
+ def __getattribute__(self, name):
+ # Emulate object w/o any class
+ if name == '__class__':
+ return None
+ raise NotImplementedError(name)
+ def __setattr__(self, name, value):
+ the_dict[name] = value
+ obj = Foo()
+ self._callFUT(obj, IFoo)
+ self.assertIsInstance(the_dict['__provides__'], ProvidesClass)
+ self.assertEqual(list(the_dict['__provides__']), [IFoo])
+
+
+class Test_alsoProvides(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.interface.declarations import alsoProvides
+ return alsoProvides(*args, **kw)
+
+ def test_wo_existing_provides(self):
+ from zope.interface.declarations import ProvidesClass
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ obj = Foo()
+ self._callFUT(obj, IFoo)
+ self.assertIsInstance(obj.__provides__, ProvidesClass) # pylint:disable=no-member
+ self.assertEqual(list(obj.__provides__), [IFoo]) # pylint:disable=no-member
+
+ def test_w_existing_provides(self):
+ from zope.interface.declarations import directlyProvides
+ from zope.interface.declarations import ProvidesClass
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ IBar = InterfaceClass("IBar")
+ class Foo(object):
+ pass
+ obj = Foo()
+ directlyProvides(obj, IFoo)
+ self._callFUT(obj, IBar)
+ self.assertIsInstance(obj.__provides__, ProvidesClass) # pylint:disable=no-member
+ self.assertEqual(list(obj.__provides__), [IFoo, IBar]) # pylint:disable=no-member
+
+
+class Test_noLongerProvides(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.interface.declarations import noLongerProvides
+ return noLongerProvides(*args, **kw)
+
+ def test_wo_existing_provides(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ obj = Foo()
+ self._callFUT(obj, IFoo)
+ self.assertEqual(list(obj.__provides__), []) # pylint:disable=no-member
+
+ def test_w_existing_provides_hit(self):
+ from zope.interface.declarations import directlyProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ obj = Foo()
+ directlyProvides(obj, IFoo)
+ self._callFUT(obj, IFoo)
+ self.assertEqual(list(obj.__provides__), []) # pylint:disable=no-member
+
+ def test_w_existing_provides_miss(self):
+ from zope.interface.declarations import directlyProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ IBar = InterfaceClass("IBar")
+ class Foo(object):
+ pass
+ obj = Foo()
+ directlyProvides(obj, IFoo)
+ self._callFUT(obj, IBar)
+ self.assertEqual(list(obj.__provides__), [IFoo]) # pylint:disable=no-member
+
+ def test_w_iface_implemented_by_class(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ obj = Foo()
+ self.assertRaises(ValueError, self._callFUT, obj, IFoo)
+
+
+class ClassProvidesBaseFallbackTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ # pylint:disable=no-name-in-module
+ from zope.interface.declarations import ClassProvidesBaseFallback
+ return ClassProvidesBaseFallback
+
+ def _makeOne(self, klass, implements):
+ # Don't instantiate directly: the C version can't have attributes
+ # assigned.
+ class Derived(self._getTargetClass()):
+ def __init__(self, k, i):
+ self._cls = k
+ self._implements = i
+ return Derived(klass, implements)
+
+ def test_w_same_class_via_class(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ cpbp = Foo.__provides__ = self._makeOne(Foo, IFoo)
+ self.assertTrue(Foo.__provides__ is cpbp)
+
+ def test_w_same_class_via_instance(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ foo = Foo()
+ Foo.__provides__ = self._makeOne(Foo, IFoo)
+ self.assertIs(foo.__provides__, IFoo)
+
+ def test_w_different_class(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ class Bar(Foo):
+ pass
+ bar = Bar()
+ Foo.__provides__ = self._makeOne(Foo, IFoo)
+ self.assertRaises(AttributeError, getattr, Bar, '__provides__')
+ self.assertRaises(AttributeError, getattr, bar, '__provides__')
+
+
+class ClassProvidesBaseTests(OptimizationTestMixin,
+ ClassProvidesBaseFallbackTests):
+ # Repeat tests for C optimizations
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import ClassProvidesBase
+ return ClassProvidesBase
+
+ def _getFallbackClass(self):
+ # pylint:disable=no-name-in-module
+ from zope.interface.declarations import ClassProvidesBaseFallback
+ return ClassProvidesBaseFallback
+
+
+class ClassProvidesTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import ClassProvides
+ return ClassProvides
+
+ def _makeOne(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def test_w_simple_metaclass(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ IBar = InterfaceClass("IBar")
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ cp = Foo.__provides__ = self._makeOne(Foo, type(Foo), IBar)
+ self.assertTrue(Foo.__provides__ is cp)
+ self.assertEqual(list(Foo().__provides__), [IFoo])
+
+ def test___reduce__(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ IBar = InterfaceClass("IBar")
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ cp = Foo.__provides__ = self._makeOne(Foo, type(Foo), IBar)
+ self.assertEqual(cp.__reduce__(),
+ (type(cp), (Foo, type(Foo), IBar)))
+
+
+class ClassProvidesStrictTests(ClassProvidesTests):
+ # Tests that require the strict C3 resolution order.
+
+ def _getTargetClass(self):
+ ClassProvides = super(ClassProvidesStrictTests, self)._getTargetClass()
+ class StrictClassProvides(ClassProvides):
+ def _do_calculate_ro(self, base_mros):
+ return ClassProvides._do_calculate_ro(self, base_mros=base_mros, strict=True)
+ return StrictClassProvides
+
+ def test_overlapping_interfaces_corrected(self):
+ # Giving ClassProvides(cls, metaclass, IFace), where IFace is already
+ # provided by metacls, doesn't produce invalid resolution orders.
+ from zope.interface import implementedBy
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class IBase(Interface):
+ pass
+
+ @implementer(IBase)
+ class metaclass(type):
+ pass
+
+ cls = metaclass(
+ 'cls',
+ (object,),
+ {}
+ )
+
+ spec = self._makeOne(cls, metaclass, IBase)
+ self.assertEqual(spec.__sro__, (
+ spec,
+ implementedBy(metaclass),
+ IBase,
+ implementedBy(type),
+ implementedBy(object),
+ Interface
+ ))
+
+
+class TestClassProvidesRepr(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import ClassProvides
+ return ClassProvides
+
+ def _makeOne(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def test__repr__empty(self):
+ inst = self._makeOne(type(self), type)
+ self.assertEqual(
+ repr(inst),
+ "directlyProvides(TestClassProvidesRepr)"
+ )
+
+ def test__repr__providing_one(self):
+ from zope.interface import Interface
+ class IFoo(Interface):
+ "Does nothing"
+
+ inst = self._makeOne(type(self), type, IFoo)
+ self.assertEqual(
+ repr(inst),
+ "directlyProvides(TestClassProvidesRepr, IFoo)"
+ )
+
+ def test__repr__duplicate_names(self):
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo", __module__='mod1')
+ IFoo2 = InterfaceClass("IFoo", __module__='mod2')
+ IBaz = InterfaceClass("IBaz")
+
+ inst = self._makeOne(type(self), type, IFoo, IBaz, IFoo2)
+ self.assertEqual(
+ repr(inst),
+ "directlyProvides(TestClassProvidesRepr, IFoo, IBaz, mod2.IFoo)"
+ )
+
+ def test__repr__implementedBy(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.declarations import implementedBy
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+
+ inst = implementedBy(Foo)
+ self.assertEqual(
+ repr(inst),
+ 'classImplements(Foo, IFoo)'
+ )
+
+ def test__repr__implementedBy_generic_callable(self):
+ from zope.interface.declarations import implementedBy
+ # We can't get a __name__ by default, so we get a
+ # module name and a question mark
+ class Callable(object):
+ def __call__(self):
+ return self
+
+ inst = implementedBy(Callable())
+ self.assertEqual(
+ repr(inst),
+ 'classImplements(%s.?)' % (__name__,)
+ )
+
+ c = Callable()
+ c.__name__ = 'Callable'
+ inst = implementedBy(c)
+ self.assertEqual(
+ repr(inst),
+ 'classImplements(Callable)'
+ )
+
+
+class Test_directlyProvidedBy(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.interface.declarations import directlyProvidedBy
+ return directlyProvidedBy(*args, **kw)
+
+ def test_wo_declarations_in_class_or_instance(self):
+ class Foo(object):
+ pass
+ foo = Foo()
+ self.assertEqual(list(self._callFUT(foo)), [])
+
+ def test_w_declarations_in_class_but_not_instance(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ foo = Foo()
+ self.assertEqual(list(self._callFUT(foo)), [])
+
+ def test_w_declarations_in_instance_but_not_class(self):
+ from zope.interface.declarations import directlyProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ foo = Foo()
+ directlyProvides(foo, IFoo)
+ self.assertEqual(list(self._callFUT(foo)), [IFoo])
+
+ def test_w_declarations_in_instance_and_class(self):
+ from zope.interface.declarations import directlyProvides
+ from zope.interface.declarations import implementer
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ IBar = InterfaceClass("IBar")
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ foo = Foo()
+ directlyProvides(foo, IBar)
+ self.assertEqual(list(self._callFUT(foo)), [IBar])
+
+
+class Test_classProvides(unittest.TestCase, _Py3ClassAdvice):
+ # pylint:disable=exec-used
+
+ def test_called_from_function(self):
+ import warnings
+ from zope.interface.declarations import classProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ globs = {'classProvides': classProvides, 'IFoo': IFoo}
+ locs = {}
+ CODE = "\n".join([
+ 'def foo():',
+ ' classProvides(IFoo)'
+ ])
+ exec(CODE, globs, locs)
+ foo = locs['foo']
+ with warnings.catch_warnings(record=True) as log:
+ warnings.resetwarnings()
+ self.assertRaises(TypeError, foo)
+ if not PYTHON3:
+ self.assertEqual(len(log), 0) # no longer warn
+
+ def test_called_twice_from_class(self):
+ import warnings
+ from zope.interface.declarations import classProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ IBar = InterfaceClass("IBar")
+ globs = {'classProvides': classProvides, 'IFoo': IFoo, 'IBar': IBar}
+ locs = {}
+ CODE = "\n".join([
+ 'class Foo(object):',
+ ' classProvides(IFoo)',
+ ' classProvides(IBar)',
+ ])
+ with warnings.catch_warnings(record=True) as log:
+ warnings.resetwarnings()
+ try:
+ exec(CODE, globs, locs)
+ except TypeError:
+ if not PYTHON3:
+ self.assertEqual(len(log), 0) # no longer warn
+ else:
+ self.fail("Didn't raise TypeError")
+
+ def test_called_once_from_class(self):
+ from zope.interface.declarations import classProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ globs = {'classProvides': classProvides, 'IFoo': IFoo}
+ locs = {}
+ CODE = "\n".join([
+ 'class Foo(object):',
+ ' classProvides(IFoo)',
+ ])
+ if self._run_generated_code(CODE, globs, locs):
+ Foo = locs['Foo']
+ spec = Foo.__providedBy__
+ self.assertEqual(list(spec), [IFoo])
+
+# Test _classProvides_advice through classProvides, its only caller.
+
+
+class Test_provider(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import provider
+ return provider
+
+ def _makeOne(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def test_w_class(self):
+ from zope.interface.declarations import ClassProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ @self._makeOne(IFoo)
+ class Foo(object):
+ pass
+ self.assertIsInstance(Foo.__provides__, ClassProvides) # pylint:disable=no-member
+ self.assertEqual(list(Foo.__provides__), [IFoo]) # pylint:disable=no-member
+
+
+class Test_moduleProvides(unittest.TestCase):
+ # pylint:disable=exec-used
+
+ def test_called_from_function(self):
+ from zope.interface.declarations import moduleProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ globs = {'__name__': '__tests__.tests.tests.foo',
+ 'moduleProvides': moduleProvides, 'IFoo': IFoo}
+ locs = {}
+ CODE = "\n".join([
+ 'def foo():',
+ ' moduleProvides(IFoo)'
+ ])
+ exec(CODE, globs, locs)
+ foo = locs['foo']
+ self.assertRaises(TypeError, foo)
+
+ def test_called_from_class(self):
+ from zope.interface.declarations import moduleProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ globs = {'__name__': '__tests__.tests.tests.foo',
+ 'moduleProvides': moduleProvides, 'IFoo': IFoo}
+ locs = {}
+ CODE = "\n".join([
+ 'class Foo(object):',
+ ' moduleProvides(IFoo)',
+ ])
+ with self.assertRaises(TypeError):
+ exec(CODE, globs, locs)
+
+ def test_called_once_from_module_scope(self):
+ from zope.interface.declarations import moduleProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ globs = {'__name__': '__tests__.tests.tests.foo',
+ 'moduleProvides': moduleProvides, 'IFoo': IFoo}
+ CODE = "\n".join([
+ 'moduleProvides(IFoo)',
+ ])
+ exec(CODE, globs)
+ spec = globs['__provides__']
+ self.assertEqual(list(spec), [IFoo])
+
+ def test_called_twice_from_module_scope(self):
+ from zope.interface.declarations import moduleProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ globs = {'__name__': '__tests__.tests.tests.foo',
+ 'moduleProvides': moduleProvides, 'IFoo': IFoo}
+
+ CODE = "\n".join([
+ 'moduleProvides(IFoo)',
+ 'moduleProvides(IFoo)',
+ ])
+ with self.assertRaises(TypeError):
+ exec(CODE, globs)
+
+
+class Test_getObjectSpecificationFallback(unittest.TestCase):
+
+ def _getFallbackClass(self):
+ # pylint:disable=no-name-in-module
+ from zope.interface.declarations import getObjectSpecificationFallback
+ return getObjectSpecificationFallback
+
+ _getTargetClass = _getFallbackClass
+
+ def _callFUT(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def test_wo_existing_provides_classless(self):
+ the_dict = {}
+ class Foo(object):
+ def __getattribute__(self, name):
+ # Emulate object w/o any class
+ if name == '__class__':
+ raise AttributeError(name)
+ try:
+ return the_dict[name]
+ except KeyError:
+ raise AttributeError(name)
+ def __setattr__(self, name, value):
+ raise NotImplementedError()
+ foo = Foo()
+ spec = self._callFUT(foo)
+ self.assertEqual(list(spec), [])
+
+ def test_existing_provides_is_spec(self):
+ from zope.interface.declarations import directlyProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ def foo():
+ raise NotImplementedError()
+ directlyProvides(foo, IFoo)
+ spec = self._callFUT(foo)
+ self.assertIs(spec, foo.__provides__) # pylint:disable=no-member
+
+ def test_existing_provides_is_not_spec(self):
+ def foo():
+ raise NotImplementedError()
+ foo.__provides__ = object() # not a valid spec
+ spec = self._callFUT(foo)
+ self.assertEqual(list(spec), [])
+
+ def test_existing_provides(self):
+ from zope.interface.declarations import directlyProvides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ foo = Foo()
+ directlyProvides(foo, IFoo)
+ spec = self._callFUT(foo)
+ self.assertEqual(list(spec), [IFoo])
+
+ def test_wo_provides_on_class_w_implements(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ foo = Foo()
+ spec = self._callFUT(foo)
+ self.assertEqual(list(spec), [IFoo])
+
+ def test_wo_provides_on_class_wo_implements(self):
+ class Foo(object):
+ pass
+ foo = Foo()
+ spec = self._callFUT(foo)
+ self.assertEqual(list(spec), [])
+
+ def test_catches_only_AttributeError_on_provides(self):
+ MissingSomeAttrs.test_raises(self, self._callFUT, expected_missing='__provides__')
+
+ def test_catches_only_AttributeError_on_class(self):
+ MissingSomeAttrs.test_raises(self, self._callFUT, expected_missing='__class__',
+ __provides__=None)
+
+ def test_raises_AttributeError_when_provides_fails_type_check_AttributeError(self):
+ # isinstance(ob.__provides__, SpecificationBase) is not
+ # protected inside any kind of block.
+
+ class Foo(object):
+ __provides__ = MissingSomeAttrs(AttributeError)
+
+ # isinstance() ignores AttributeError on __class__
+ self._callFUT(Foo())
+
+ def test_raises_AttributeError_when_provides_fails_type_check_RuntimeError(self):
+ # isinstance(ob.__provides__, SpecificationBase) is not
+ # protected inside any kind of block.
+ class Foo(object):
+ __provides__ = MissingSomeAttrs(RuntimeError)
+
+ if PYTHON3:
+ with self.assertRaises(RuntimeError) as exc:
+ self._callFUT(Foo())
+
+ self.assertEqual('__class__', exc.exception.args[0])
+ else:
+ # Python 2 catches everything.
+ self._callFUT(Foo())
+
+
+class Test_getObjectSpecification(Test_getObjectSpecificationFallback,
+ OptimizationTestMixin):
+ # Repeat tests for C optimizations
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import getObjectSpecification
+ return getObjectSpecification
+
+
+class Test_providedByFallback(unittest.TestCase):
+
+ def _getFallbackClass(self):
+ # pylint:disable=no-name-in-module
+ from zope.interface.declarations import providedByFallback
+ return providedByFallback
+
+ _getTargetClass = _getFallbackClass
+
+ def _callFUT(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def test_wo_providedBy_on_class_wo_implements(self):
+ class Foo(object):
+ pass
+ foo = Foo()
+ spec = self._callFUT(foo)
+ self.assertEqual(list(spec), [])
+
+ def test_w_providedBy_valid_spec(self):
+ from zope.interface.declarations import Provides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ foo = Foo()
+ foo.__providedBy__ = Provides(Foo, IFoo)
+ spec = self._callFUT(foo)
+ self.assertEqual(list(spec), [IFoo])
+
+ def test_w_providedBy_invalid_spec(self):
+ class Foo(object):
+ pass
+ foo = Foo()
+ foo.__providedBy__ = object()
+ spec = self._callFUT(foo)
+ self.assertEqual(list(spec), [])
+
+ def test_w_providedBy_invalid_spec_class_w_implements(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ foo = Foo()
+ foo.__providedBy__ = object()
+ spec = self._callFUT(foo)
+ self.assertEqual(list(spec), [IFoo])
+
+ def test_w_providedBy_invalid_spec_w_provides_no_provides_on_class(self):
+ class Foo(object):
+ pass
+ foo = Foo()
+ foo.__providedBy__ = object()
+ expected = foo.__provides__ = object()
+ spec = self._callFUT(foo)
+ self.assertTrue(spec is expected)
+
+ def test_w_providedBy_invalid_spec_w_provides_diff_provides_on_class(self):
+ class Foo(object):
+ pass
+ foo = Foo()
+ foo.__providedBy__ = object()
+ expected = foo.__provides__ = object()
+ Foo.__provides__ = object()
+ spec = self._callFUT(foo)
+ self.assertTrue(spec is expected)
+
+ def test_w_providedBy_invalid_spec_w_provides_same_provides_on_class(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ foo = Foo()
+ foo.__providedBy__ = object()
+ foo.__provides__ = Foo.__provides__ = object()
+ spec = self._callFUT(foo)
+ self.assertEqual(list(spec), [IFoo])
+
+ def test_super_when_base_implements_interface(self):
+ from zope.interface import Interface
+ from zope.interface.declarations import implementer
+
+ class IBase(Interface):
+ pass
+
+ class IDerived(IBase):
+ pass
+
+ @implementer(IBase)
+ class Base(object):
+ pass
+
+ @implementer(IDerived)
+ class Derived(Base):
+ pass
+
+ derived = Derived()
+ self.assertEqual(list(self._callFUT(derived)), [IDerived, IBase])
+
+ sup = super(Derived, derived)
+ fut = self._callFUT(sup)
+ self.assertIsNone(fut._dependents)
+ self.assertEqual(list(fut), [IBase])
+
+ def test_super_when_base_doesnt_implement_interface(self):
+ from zope.interface import Interface
+ from zope.interface.declarations import implementer
+
+ class IBase(Interface):
+ pass
+
+ class IDerived(IBase):
+ pass
+
+ class Base(object):
+ pass
+
+ @implementer(IDerived)
+ class Derived(Base):
+ pass
+
+ derived = Derived()
+ self.assertEqual(list(self._callFUT(derived)), [IDerived])
+
+ sup = super(Derived, derived)
+ self.assertEqual(list(self._callFUT(sup)), [])
+
+ def test_super_when_base_is_object(self):
+ from zope.interface import Interface
+ from zope.interface.declarations import implementer
+
+ class IBase(Interface):
+ pass
+
+ class IDerived(IBase):
+ pass
+
+ @implementer(IDerived)
+ class Derived(object):
+ pass
+
+ derived = Derived()
+ self.assertEqual(list(self._callFUT(derived)), [IDerived])
+
+ sup = super(Derived, derived)
+ fut = self._callFUT(sup)
+ self.assertIsNone(fut._dependents)
+ self.assertEqual(list(fut), [])
+
+ def test_super_when_object_directly_provides(self):
+ from zope.interface import Interface
+ from zope.interface.declarations import implementer
+ from zope.interface.declarations import directlyProvides
+
+ class IBase(Interface):
+ pass
+
+ class IDerived(IBase):
+ pass
+
+ @implementer(IBase)
+ class Base(object):
+ pass
+
+ class Derived(Base):
+ pass
+
+ derived = Derived()
+ self.assertEqual(list(self._callFUT(derived)), [IBase])
+
+ directlyProvides(derived, IDerived)
+ self.assertEqual(list(self._callFUT(derived)), [IDerived, IBase])
+
+ sup = super(Derived, derived)
+ fut = self._callFUT(sup)
+ self.assertIsNone(fut._dependents)
+ self.assertEqual(list(fut), [IBase])
+
+ def test_super_multi_level_multi_inheritance(self):
+ from zope.interface.declarations import implementer
+ from zope.interface import Interface
+
+ class IBase(Interface):
+ pass
+
+ class IM1(Interface):
+ pass
+
+ class IM2(Interface):
+ pass
+
+ class IDerived(IBase):
+ pass
+
+ class IUnrelated(Interface):
+ pass
+
+ @implementer(IBase)
+ class Base(object):
+ pass
+
+ @implementer(IM1)
+ class M1(Base):
+ pass
+
+ @implementer(IM2)
+ class M2(Base):
+ pass
+
+ @implementer(IDerived, IUnrelated)
+ class Derived(M1, M2):
+ pass
+
+ d = Derived()
+ sd = super(Derived, d)
+ sm1 = super(M1, d)
+ sm2 = super(M2, d)
+
+ self.assertEqual(list(self._callFUT(d)),
+ [IDerived, IUnrelated, IM1, IBase, IM2])
+ self.assertEqual(list(self._callFUT(sd)),
+ [IM1, IBase, IM2])
+ self.assertEqual(list(self._callFUT(sm1)),
+ [IM2, IBase])
+ self.assertEqual(list(self._callFUT(sm2)),
+ [IBase])
+
+ def test_catches_only_AttributeError_on_providedBy(self):
+ MissingSomeAttrs.test_raises(self, self._callFUT,
+ expected_missing='__providedBy__',
+ __class__=object)
+
+ def test_catches_only_AttributeError_on_class(self):
+ # isinstance() tries to get the __class__, which is non-obvious,
+ # so it must be protected too.
+ PY3 = str is not bytes
+ MissingSomeAttrs.test_raises(self, self._callFUT,
+ expected_missing='__class__' if PY3 else '__providedBy__')
+
+
+
+class Test_providedBy(Test_providedByFallback,
+ OptimizationTestMixin):
+ # Repeat tests for C optimizations
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import providedBy
+ return providedBy
+
+
+class ObjectSpecificationDescriptorFallbackTests(unittest.TestCase):
+
+ def _getFallbackClass(self):
+ # pylint:disable=no-name-in-module
+ from zope.interface.declarations \
+ import ObjectSpecificationDescriptorFallback
+ return ObjectSpecificationDescriptorFallback
+
+ _getTargetClass = _getFallbackClass
+
+ def _makeOne(self, *args, **kw):
+ return self._getTargetClass()(*args, **kw)
+
+ def test_accessed_via_class(self):
+ from zope.interface.declarations import Provides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ class Foo(object):
+ pass
+ Foo.__provides__ = Provides(Foo, IFoo)
+ Foo.__providedBy__ = self._makeOne()
+ self.assertEqual(list(Foo.__providedBy__), [IFoo])
+
+ def test_accessed_via_inst_wo_provides(self):
+ from zope.interface.declarations import implementer
+ from zope.interface.declarations import Provides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ IBar = InterfaceClass("IBar")
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ Foo.__provides__ = Provides(Foo, IBar)
+ Foo.__providedBy__ = self._makeOne()
+ foo = Foo()
+ self.assertEqual(list(foo.__providedBy__), [IFoo])
+
+ def test_accessed_via_inst_w_provides(self):
+ from zope.interface.declarations import directlyProvides
+ from zope.interface.declarations import implementer
+ from zope.interface.declarations import Provides
+ from zope.interface.interface import InterfaceClass
+ IFoo = InterfaceClass("IFoo")
+ IBar = InterfaceClass("IBar")
+ IBaz = InterfaceClass("IBaz")
+ @implementer(IFoo)
+ class Foo(object):
+ pass
+ Foo.__provides__ = Provides(Foo, IBar)
+ Foo.__providedBy__ = self._makeOne()
+ foo = Foo()
+ directlyProvides(foo, IBaz)
+ self.assertEqual(list(foo.__providedBy__), [IBaz, IFoo])
+
+ def test_arbitrary_exception_accessing_provides_not_caught(self):
+
+ class MyException(Exception):
+ pass
+
+ class Foo(object):
+ __providedBy__ = self._makeOne()
+
+ @property
+ def __provides__(self):
+ raise MyException
+
+ foo = Foo()
+ with self.assertRaises(MyException):
+ getattr(foo, '__providedBy__')
+
+ def test_AttributeError_accessing_provides_caught(self):
+
+ class MyException(Exception):
+ pass
+
+ class Foo(object):
+ __providedBy__ = self._makeOne()
+
+ @property
+ def __provides__(self):
+ raise AttributeError
+
+ foo = Foo()
+ provided = getattr(foo, '__providedBy__')
+ self.assertIsNotNone(provided)
+
+ def test_None_in__provides__overrides(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class IFoo(Interface):
+ pass
+
+ @implementer(IFoo)
+ class Foo(object):
+
+ @property
+ def __provides__(self):
+ return None
+
+ Foo.__providedBy__ = self._makeOne()
+
+ provided = getattr(Foo(), '__providedBy__')
+ self.assertIsNone(provided)
+
+class ObjectSpecificationDescriptorTests(
+ ObjectSpecificationDescriptorFallbackTests,
+ OptimizationTestMixin):
+ # Repeat tests for C optimizations
+
+ def _getTargetClass(self):
+ from zope.interface.declarations import ObjectSpecificationDescriptor
+ return ObjectSpecificationDescriptor
+
+
+# Test _normalizeargs through its callers.
+
+
+class _Monkey(object):
+ # context-manager for replacing module names in the scope of a test.
+ def __init__(self, module, **kw):
+ self.module = module
+ self.to_restore = {key: getattr(module, key) for key in kw}
+ for key, value in kw.items():
+ setattr(module, key, value)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ for key, value in self.to_restore.items():
+ setattr(self.module, key, value)
+
+
+class _MonkeyDict(object):
+ # context-manager for restoring a dict w/in a module in the scope of a test.
+ def __init__(self, module, attrname, **kw):
+ self.module = module
+ self.target = getattr(module, attrname)
+ self.to_restore = self.target.copy()
+ self.target.clear()
+ self.target.update(kw)
+
+ def __enter__(self):
+ return self.target
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self.target.clear()
+ self.target.update(self.to_restore)
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/test_document.py b/contrib/python/zope.interface/py2/zope/interface/tests/test_document.py
new file mode 100644
index 0000000000..3e6dddd81d
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/test_document.py
@@ -0,0 +1,505 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Documentation tests.
+"""
+import unittest
+
+
+class Test_asStructuredText(unittest.TestCase):
+
+ def _callFUT(self, iface):
+ from zope.interface.document import asStructuredText
+ return asStructuredText(iface)
+
+ def test_asStructuredText_no_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "INoDocstring",
+ " Attributes:",
+ " Methods:",
+ ""
+ ])
+ class INoDocstring(Interface):
+ pass
+ self.assertEqual(self._callFUT(INoDocstring), EXPECTED)
+
+ def test_asStructuredText_empty_with_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "IEmpty",
+ " This is an empty interface.",
+ " Attributes:",
+ " Methods:",
+ ""
+ ])
+ class IEmpty(Interface):
+ """ This is an empty interface.
+ """
+ self.assertEqual(self._callFUT(IEmpty), EXPECTED)
+
+ def test_asStructuredText_empty_with_multiline_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n'.join([
+ "IEmpty",
+ "",
+ " This is an empty interface.",
+ " ",
+ (" It can be used to annotate any class or object, "
+ "because it promises"),
+ " nothing.",
+ "",
+ " Attributes:",
+ "",
+ " Methods:",
+ "",
+ ""
+ ])
+ class IEmpty(Interface):
+ """ This is an empty interface.
+
+ It can be used to annotate any class or object, because it promises
+ nothing.
+ """
+ self.assertEqual(self._callFUT(IEmpty), EXPECTED)
+
+ def test_asStructuredText_with_attribute_no_docstring(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "IHasAttribute",
+ " This interface has an attribute.",
+ " Attributes:",
+ " an_attribute -- no documentation",
+ " Methods:",
+ ""
+ ])
+ class IHasAttribute(Interface):
+ """ This interface has an attribute.
+ """
+ an_attribute = Attribute('an_attribute')
+
+ self.assertEqual(self._callFUT(IHasAttribute), EXPECTED)
+
+ def test_asStructuredText_with_attribute_with_docstring(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "IHasAttribute",
+ " This interface has an attribute.",
+ " Attributes:",
+ " an_attribute -- This attribute is documented.",
+ " Methods:",
+ ""
+ ])
+ class IHasAttribute(Interface):
+ """ This interface has an attribute.
+ """
+ an_attribute = Attribute('an_attribute',
+ 'This attribute is documented.')
+
+ self.assertEqual(self._callFUT(IHasAttribute), EXPECTED)
+
+ def test_asStructuredText_with_method_no_args_no_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "IHasMethod",
+ " This interface has a method.",
+ " Attributes:",
+ " Methods:",
+ " aMethod() -- no documentation",
+ ""
+ ])
+ class IHasMethod(Interface):
+ """ This interface has a method.
+ """
+ def aMethod():
+ pass # pragma: no cover
+
+ self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
+
+ def test_asStructuredText_with_method_positional_args_no_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "IHasMethod",
+ " This interface has a method.",
+ " Attributes:",
+ " Methods:",
+ " aMethod(first, second) -- no documentation",
+ ""
+ ])
+ class IHasMethod(Interface):
+ """ This interface has a method.
+ """
+ def aMethod(first, second):
+ pass # pragma: no cover
+
+ self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
+
+ def test_asStructuredText_with_method_starargs_no_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "IHasMethod",
+ " This interface has a method.",
+ " Attributes:",
+ " Methods:",
+ " aMethod(first, second, *rest) -- no documentation",
+ ""
+ ])
+ class IHasMethod(Interface):
+ """ This interface has a method.
+ """
+ def aMethod(first, second, *rest):
+ pass # pragma: no cover
+
+ self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
+
+ def test_asStructuredText_with_method_kwargs_no_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "IHasMethod",
+ " This interface has a method.",
+ " Attributes:",
+ " Methods:",
+ " aMethod(first, second, **kw) -- no documentation",
+ ""
+ ])
+ class IHasMethod(Interface):
+ """ This interface has a method.
+ """
+ def aMethod(first, second, **kw):
+ pass # pragma: no cover
+
+ self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
+
+ def test_asStructuredText_with_method_with_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "IHasMethod",
+ " This interface has a method.",
+ " Attributes:",
+ " Methods:",
+ " aMethod() -- This method is documented.",
+ ""
+ ])
+ class IHasMethod(Interface):
+ """ This interface has a method.
+ """
+ def aMethod():
+ """This method is documented.
+ """
+
+ self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
+
+ def test_asStructuredText_derived_ignores_base(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "IDerived",
+ " IDerived doc",
+ " This interface extends:",
+ " o IBase",
+ " Attributes:",
+ " attr1 -- no documentation",
+ " attr2 -- attr2 doc",
+ " Methods:",
+ " method3() -- method3 doc",
+ " method4() -- no documentation",
+ " method5() -- method5 doc",
+ "",
+ ])
+
+ class IBase(Interface):
+ def method1():
+ """docstring"""
+ def method2():
+ """docstring"""
+
+ class IDerived(IBase):
+ "IDerived doc"
+ attr1 = Attribute('attr1')
+ attr2 = Attribute('attr2', 'attr2 doc')
+
+ def method3():
+ "method3 doc"
+ def method4():
+ pass # pragma: no cover
+ def method5():
+ "method5 doc"
+
+ self.assertEqual(self._callFUT(IDerived), EXPECTED)
+
+
+class Test_asReStructuredText(unittest.TestCase):
+
+ def _callFUT(self, iface):
+ from zope.interface.document import asReStructuredText
+ return asReStructuredText(iface)
+
+ def test_asReStructuredText_no_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "``INoDocstring``",
+ " Attributes:",
+ " Methods:",
+ ""
+ ])
+ class INoDocstring(Interface):
+ pass
+ self.assertEqual(self._callFUT(INoDocstring), EXPECTED)
+
+ def test_asReStructuredText_empty_with_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "``IEmpty``",
+ " This is an empty interface.",
+ " Attributes:",
+ " Methods:",
+ ""
+ ])
+ class IEmpty(Interface):
+ """ This is an empty interface.
+ """
+ self.assertEqual(self._callFUT(IEmpty), EXPECTED)
+
+ def test_asReStructuredText_empty_with_multiline_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n'.join([
+ "``IEmpty``",
+ "",
+ " This is an empty interface.",
+ " ",
+ (" It can be used to annotate any class or object, "
+ "because it promises"),
+ " nothing.",
+ "",
+ " Attributes:",
+ "",
+ " Methods:",
+ "",
+ ""
+ ])
+ class IEmpty(Interface):
+ """ This is an empty interface.
+
+ It can be used to annotate any class or object, because it promises
+ nothing.
+ """
+ self.assertEqual(self._callFUT(IEmpty), EXPECTED)
+
+ def test_asReStructuredText_with_attribute_no_docstring(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "``IHasAttribute``",
+ " This interface has an attribute.",
+ " Attributes:",
+ " ``an_attribute`` -- no documentation",
+ " Methods:",
+ ""
+ ])
+ class IHasAttribute(Interface):
+ """ This interface has an attribute.
+ """
+ an_attribute = Attribute('an_attribute')
+
+ self.assertEqual(self._callFUT(IHasAttribute), EXPECTED)
+
+ def test_asReStructuredText_with_attribute_with_docstring(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "``IHasAttribute``",
+ " This interface has an attribute.",
+ " Attributes:",
+ " ``an_attribute`` -- This attribute is documented.",
+ " Methods:",
+ ""
+ ])
+ class IHasAttribute(Interface):
+ """ This interface has an attribute.
+ """
+ an_attribute = Attribute('an_attribute',
+ 'This attribute is documented.')
+
+ self.assertEqual(self._callFUT(IHasAttribute), EXPECTED)
+
+ def test_asReStructuredText_with_method_no_args_no_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "``IHasMethod``",
+ " This interface has a method.",
+ " Attributes:",
+ " Methods:",
+ " ``aMethod()`` -- no documentation",
+ ""
+ ])
+ class IHasMethod(Interface):
+ """ This interface has a method.
+ """
+ def aMethod():
+ pass # pragma: no cover
+
+ self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
+
+ def test_asReStructuredText_with_method_positional_args_no_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "``IHasMethod``",
+ " This interface has a method.",
+ " Attributes:",
+ " Methods:",
+ " ``aMethod(first, second)`` -- no documentation",
+ ""
+ ])
+ class IHasMethod(Interface):
+ """ This interface has a method.
+ """
+ def aMethod(first, second):
+ pass # pragma: no cover
+
+ self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
+
+ def test_asReStructuredText_with_method_starargs_no_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "``IHasMethod``",
+ " This interface has a method.",
+ " Attributes:",
+ " Methods:",
+ " ``aMethod(first, second, *rest)`` -- no documentation",
+ ""
+ ])
+ class IHasMethod(Interface):
+ """ This interface has a method.
+ """
+ def aMethod(first, second, *rest):
+ pass # pragma: no cover
+
+ self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
+
+ def test_asReStructuredText_with_method_kwargs_no_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "``IHasMethod``",
+ " This interface has a method.",
+ " Attributes:",
+ " Methods:",
+ " ``aMethod(first, second, **kw)`` -- no documentation",
+ ""
+ ])
+ class IHasMethod(Interface):
+ """ This interface has a method.
+ """
+ def aMethod(first, second, **kw):
+ pass # pragma: no cover
+
+ self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
+
+ def test_asReStructuredText_with_method_with_docstring(self):
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "``IHasMethod``",
+ " This interface has a method.",
+ " Attributes:",
+ " Methods:",
+ " ``aMethod()`` -- This method is documented.",
+ ""
+ ])
+ class IHasMethod(Interface):
+ """ This interface has a method.
+ """
+ def aMethod():
+ """This method is documented.
+ """
+
+ self.assertEqual(self._callFUT(IHasMethod), EXPECTED)
+
+ def test_asReStructuredText_derived_ignores_base(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ EXPECTED = '\n\n'.join([
+ "``IDerived``",
+ " IDerived doc",
+ " This interface extends:",
+ " o ``IBase``",
+ " Attributes:",
+ " ``attr1`` -- no documentation",
+ " ``attr2`` -- attr2 doc",
+ " Methods:",
+ " ``method3()`` -- method3 doc",
+ " ``method4()`` -- no documentation",
+ " ``method5()`` -- method5 doc",
+ "",
+ ])
+
+ class IBase(Interface):
+ def method1():
+ pass # pragma: no cover
+ def method2():
+ pass # pragma: no cover
+
+ class IDerived(IBase):
+ "IDerived doc"
+ attr1 = Attribute('attr1')
+ attr2 = Attribute('attr2', 'attr2 doc')
+
+ def method3():
+ "method3 doc"
+ def method4():
+ pass # pragma: no cover
+ def method5():
+ "method5 doc"
+
+ self.assertEqual(self._callFUT(IDerived), EXPECTED)
+
+
+class Test__justify_and_indent(unittest.TestCase):
+
+ def _callFUT(self, text, level, **kw):
+ from zope.interface.document import _justify_and_indent
+ return _justify_and_indent(text, level, **kw)
+
+ def test_simple_level_0(self):
+ LINES = ['Three blind mice', 'See how they run']
+ text = '\n'.join(LINES)
+ self.assertEqual(self._callFUT(text, 0), text)
+
+ def test_simple_level_1(self):
+ LINES = ['Three blind mice', 'See how they run']
+ text = '\n'.join(LINES)
+ self.assertEqual(self._callFUT(text, 1),
+ '\n'.join([' ' + line for line in LINES]))
+
+ def test_simple_level_2(self):
+ LINES = ['Three blind mice', 'See how they run']
+ text = '\n'.join(LINES)
+ self.assertEqual(self._callFUT(text, 1),
+ '\n'.join([' ' + line for line in LINES]))
+
+ def test_simple_w_CRLF(self):
+ LINES = ['Three blind mice', 'See how they run']
+ text = '\r\n'.join(LINES)
+ self.assertEqual(self._callFUT(text, 1),
+ '\n'.join([' ' + line for line in LINES]))
+
+ def test_with_munge(self):
+ TEXT = ("This is a piece of text longer than 15 characters, \n"
+ "and split across multiple lines.")
+ EXPECTED = (" This is a piece\n"
+ " of text longer\n"
+ " than 15 characters,\n"
+ " and split across\n"
+ " multiple lines.\n"
+ " ")
+ self.assertEqual(self._callFUT(TEXT, 1, munge=1, width=15), EXPECTED)
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/test_element.py b/contrib/python/zope.interface/py2/zope/interface/tests/test_element.py
new file mode 100644
index 0000000000..eb003cda29
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/test_element.py
@@ -0,0 +1,31 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Test Element meta-class.
+"""
+
+import unittest
+from zope.interface.interface import Element
+
+class TestElement(unittest.TestCase):
+
+ def test_taggedValues(self):
+ """Test that we can update tagged values of more than one element
+ """
+
+ e1 = Element("foo")
+ e2 = Element("bar")
+ e1.setTaggedValue("x", 1)
+ e2.setTaggedValue("x", 2)
+ self.assertEqual(e1.getTaggedValue("x"), 1)
+ self.assertEqual(e2.getTaggedValue("x"), 2)
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/test_exceptions.py b/contrib/python/zope.interface/py2/zope/interface/tests/test_exceptions.py
new file mode 100644
index 0000000000..d61c8c925a
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/test_exceptions.py
@@ -0,0 +1,184 @@
+##############################################################################
+#
+# Copyright (c) 2010 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" zope.interface.exceptions unit tests
+"""
+import unittest
+
+def _makeIface():
+ from zope.interface import Interface
+ class IDummy(Interface):
+ pass
+ return IDummy
+
+class DoesNotImplementTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.exceptions import DoesNotImplement
+ return DoesNotImplement
+
+ def _makeOne(self, *args):
+ iface = _makeIface()
+ return self._getTargetClass()(iface, *args)
+
+ def test___str__(self):
+ dni = self._makeOne()
+ self.assertEqual(
+ str(dni),
+ "An object has failed to implement interface "
+ "__tests__.tests.test_exceptions.IDummy: "
+ "Does not declaratively implement the interface."
+ )
+
+ def test___str__w_candidate(self):
+ dni = self._makeOne('candidate')
+ self.assertEqual(
+ str(dni),
+ "The object 'candidate' has failed to implement interface "
+ "__tests__.tests.test_exceptions.IDummy: "
+ "Does not declaratively implement the interface."
+ )
+
+
+class BrokenImplementationTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.exceptions import BrokenImplementation
+ return BrokenImplementation
+
+ def _makeOne(self, *args):
+ iface = _makeIface()
+ return self._getTargetClass()(iface, 'missing', *args)
+
+ def test___str__(self):
+ dni = self._makeOne()
+ self.assertEqual(
+ str(dni),
+ 'An object has failed to implement interface '
+ '__tests__.tests.test_exceptions.IDummy: '
+ "The 'missing' attribute was not provided.")
+
+ def test___str__w_candidate(self):
+ dni = self._makeOne('candidate')
+ self.assertEqual(
+ str(dni),
+ 'The object \'candidate\' has failed to implement interface '
+ '__tests__.tests.test_exceptions.IDummy: '
+ "The 'missing' attribute was not provided.")
+
+
+def broken_function():
+ """
+ This is a global function with a simple argument list.
+
+ It exists to be able to report the same information when
+ formatting signatures under Python 2 and Python 3.
+ """
+
+
+class BrokenMethodImplementationTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.exceptions import BrokenMethodImplementation
+ return BrokenMethodImplementation
+
+ message = 'I said so'
+
+ def _makeOne(self, *args):
+ return self._getTargetClass()('aMethod', self.message, *args)
+
+ def test___str__(self):
+ dni = self._makeOne()
+ self.assertEqual(
+ str(dni),
+ "An object has failed to implement interface <Unknown>: "
+ "The contract of 'aMethod' is violated because I said so."
+ )
+
+ def test___str__w_candidate_no_implementation(self):
+ dni = self._makeOne('some_function', '<IFoo>', 'candidate')
+ self.assertEqual(
+ str(dni),
+ "The object 'candidate' has failed to implement interface <IFoo>: "
+ "The contract of 'aMethod' is violated because I said so."
+ )
+
+ def test___str__w_candidate_w_implementation(self):
+ self.message = 'implementation is wonky'
+ dni = self._makeOne(broken_function, '<IFoo>', 'candidate')
+ self.assertEqual(
+ str(dni),
+ "The object 'candidate' has failed to implement interface <IFoo>: "
+ "The contract of 'aMethod' is violated because "
+ "'broken_function()' is wonky."
+ )
+
+ def test___str__w_candidate_w_implementation_not_callable(self):
+ self.message = 'implementation is not callable'
+ dni = self._makeOne(42, '<IFoo>', 'candidate')
+ self.assertEqual(
+ str(dni),
+ "The object 'candidate' has failed to implement interface <IFoo>: "
+ "The contract of 'aMethod' is violated because "
+ "'42' is not callable."
+ )
+
+ def test___repr__w_candidate(self):
+ dni = self._makeOne(None, 'candidate')
+ self.assertEqual(
+ repr(dni),
+ "BrokenMethodImplementation('aMethod', 'I said so', None, 'candidate')"
+ )
+
+
+class MultipleInvalidTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.exceptions import MultipleInvalid
+ return MultipleInvalid
+
+ def _makeOne(self, excs):
+ iface = _makeIface()
+ return self._getTargetClass()(iface, 'target', excs)
+
+ def test__str__(self):
+ from zope.interface.exceptions import BrokenMethodImplementation
+ excs = [
+ BrokenMethodImplementation('aMethod', 'I said so'),
+ Exception("Regular exception")
+ ]
+ dni = self._makeOne(excs)
+ self.assertEqual(
+ str(dni),
+ "The object 'target' has failed to implement interface "
+ "__tests__.tests.test_exceptions.IDummy:\n"
+ " The contract of 'aMethod' is violated because I said so\n"
+ " Regular exception"
+ )
+
+ def test__repr__(self):
+ from zope.interface.exceptions import BrokenMethodImplementation
+ excs = [
+ BrokenMethodImplementation('aMethod', 'I said so'),
+ # Use multiple arguments to normalize repr; versions of Python
+ # prior to 3.7 add a trailing comma if there's just one.
+ Exception("Regular", "exception")
+ ]
+ dni = self._makeOne(excs)
+ self.assertEqual(
+ repr(dni),
+ "MultipleInvalid(<InterfaceClass __tests__.tests.test_exceptions.IDummy>,"
+ " 'target',"
+ " (BrokenMethodImplementation('aMethod', 'I said so'),"
+ " Exception('Regular', 'exception')))"
+ )
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/test_interface.py b/contrib/python/zope.interface/py2/zope/interface/tests/test_interface.py
new file mode 100644
index 0000000000..dc365f0998
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/test_interface.py
@@ -0,0 +1,2660 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Test Interface implementation
+"""
+# Things we let slide because it's a test
+# pylint:disable=protected-access,blacklisted-name,attribute-defined-outside-init
+# pylint:disable=too-many-public-methods,too-many-lines,abstract-method
+# pylint:disable=redefined-builtin,signature-differs,arguments-differ
+# Things you get inheriting from Interface
+# pylint:disable=inherit-non-class,no-self-argument,no-method-argument
+# Things you get using methods of an Interface 'subclass'
+# pylint:disable=no-value-for-parameter
+import unittest
+
+from zope.interface._compat import _skip_under_py3k
+from __tests__.tests import MissingSomeAttrs
+from __tests__.tests import OptimizationTestMixin
+from __tests__.tests import CleanUp
+
+_marker = object()
+
+
+class Test_invariant(unittest.TestCase):
+
+ def test_w_single(self):
+ from zope.interface.interface import invariant
+ from zope.interface.interface import TAGGED_DATA
+
+ def _check(*args, **kw):
+ raise NotImplementedError()
+
+ class Foo(object):
+ invariant(_check)
+
+ self.assertEqual(getattr(Foo, TAGGED_DATA, None),
+ {'invariants': [_check]})
+
+ def test_w_multiple(self):
+ from zope.interface.interface import invariant
+ from zope.interface.interface import TAGGED_DATA
+
+ def _check(*args, **kw):
+ raise NotImplementedError()
+
+ def _another_check(*args, **kw):
+ raise NotImplementedError()
+
+ class Foo(object):
+ invariant(_check)
+ invariant(_another_check)
+
+ self.assertEqual(getattr(Foo, TAGGED_DATA, None),
+ {'invariants': [_check, _another_check]})
+
+
+class Test_taggedValue(unittest.TestCase):
+
+ def test_w_single(self):
+ from zope.interface.interface import taggedValue
+ from zope.interface.interface import TAGGED_DATA
+
+ class Foo(object):
+ taggedValue('bar', ['baz'])
+
+ self.assertEqual(getattr(Foo, TAGGED_DATA, None),
+ {'bar': ['baz']})
+
+ def test_w_multiple(self):
+ from zope.interface.interface import taggedValue
+ from zope.interface.interface import TAGGED_DATA
+
+ class Foo(object):
+ taggedValue('bar', ['baz'])
+ taggedValue('qux', 'spam')
+
+ self.assertEqual(getattr(Foo, TAGGED_DATA, None),
+ {'bar': ['baz'], 'qux': 'spam'})
+
+ def test_w_multiple_overwriting(self):
+ from zope.interface.interface import taggedValue
+ from zope.interface.interface import TAGGED_DATA
+
+ class Foo(object):
+ taggedValue('bar', ['baz'])
+ taggedValue('qux', 'spam')
+ taggedValue('bar', 'frob')
+
+ self.assertEqual(getattr(Foo, TAGGED_DATA, None),
+ {'bar': 'frob', 'qux': 'spam'})
+
+
+class ElementTests(unittest.TestCase):
+
+ DEFAULT_NAME = 'AnElement'
+
+ def _getTargetClass(self):
+ from zope.interface.interface import Element
+ return Element
+
+ def _makeOne(self, name=None):
+ if name is None:
+ name = self.DEFAULT_NAME
+ return self._getTargetClass()(name)
+
+ def test_ctor_defaults(self):
+ element = self._makeOne()
+ self.assertEqual(element.__name__, self.DEFAULT_NAME)
+ self.assertEqual(element.getName(), self.DEFAULT_NAME)
+ self.assertEqual(element.__doc__, '')
+ self.assertEqual(element.getDoc(), '')
+ self.assertEqual(list(element.getTaggedValueTags()), [])
+
+ def test_ctor_no_doc_space_in_name(self):
+ element = self._makeOne('An Element')
+ self.assertEqual(element.__name__, None)
+ self.assertEqual(element.__doc__, 'An Element')
+
+ def test_getTaggedValue_miss(self):
+ element = self._makeOne()
+ self.assertRaises(KeyError, element.getTaggedValue, 'nonesuch')
+
+ def test_getDirectTaggedValueTags(self):
+ element = self._makeOne()
+ self.assertEqual([], list(element.getDirectTaggedValueTags()))
+
+ element.setTaggedValue('foo', 'bar')
+ self.assertEqual(['foo'], list(element.getDirectTaggedValueTags()))
+
+ def test_queryTaggedValue_miss(self):
+ element = self._makeOne()
+ self.assertEqual(element.queryTaggedValue('nonesuch'), None)
+
+ def test_queryTaggedValue_miss_w_default(self):
+ element = self._makeOne()
+ self.assertEqual(element.queryTaggedValue('nonesuch', 'bar'), 'bar')
+
+ def test_getDirectTaggedValue_miss(self):
+ element = self._makeOne()
+ self.assertRaises(KeyError, element.getDirectTaggedValue, 'nonesuch')
+
+ def test_queryDirectTaggedValue_miss(self):
+ element = self._makeOne()
+ self.assertEqual(element.queryDirectTaggedValue('nonesuch'), None)
+
+ def test_queryDirectTaggedValue_miss_w_default(self):
+ element = self._makeOne()
+ self.assertEqual(element.queryDirectTaggedValue('nonesuch', 'bar'), 'bar')
+
+ def test_setTaggedValue(self):
+ element = self._makeOne()
+ element.setTaggedValue('foo', 'bar')
+ self.assertEqual(list(element.getTaggedValueTags()), ['foo'])
+ self.assertEqual(element.getTaggedValue('foo'), 'bar')
+ self.assertEqual(element.queryTaggedValue('foo'), 'bar')
+
+ def test_verifies(self):
+ from zope.interface.interfaces import IElement
+ from zope.interface.verify import verifyObject
+
+ element = self._makeOne()
+ verifyObject(IElement, element)
+
+
+class GenericSpecificationBaseTests(unittest.TestCase):
+ # Tests that work with both implementations
+ def _getFallbackClass(self):
+ from zope.interface.interface import SpecificationBasePy # pylint:disable=no-name-in-module
+ return SpecificationBasePy
+
+ _getTargetClass = _getFallbackClass
+
+ def _makeOne(self):
+ return self._getTargetClass()()
+
+ def test_providedBy_miss(self):
+ from zope.interface import interface
+ from zope.interface.declarations import _empty
+ sb = self._makeOne()
+ def _providedBy(obj):
+ return _empty
+ with _Monkey(interface, providedBy=_providedBy):
+ self.assertFalse(sb.providedBy(object()))
+
+ def test_implementedBy_miss(self):
+ from zope.interface import interface
+ from zope.interface.declarations import _empty
+ sb = self._makeOne()
+ def _implementedBy(obj):
+ return _empty
+ with _Monkey(interface, implementedBy=_implementedBy):
+ self.assertFalse(sb.implementedBy(object()))
+
+
+class SpecificationBaseTests(GenericSpecificationBaseTests,
+ OptimizationTestMixin):
+ # Tests that use the C implementation
+
+ def _getTargetClass(self):
+ from zope.interface.interface import SpecificationBase
+ return SpecificationBase
+
+class SpecificationBasePyTests(GenericSpecificationBaseTests):
+ # Tests that only work with the Python implementation
+
+ def test___call___miss(self):
+ sb = self._makeOne()
+ sb._implied = {} # not defined by SpecificationBasePy
+ self.assertFalse(sb.isOrExtends(object()))
+
+ def test___call___hit(self):
+ sb = self._makeOne()
+ testing = object()
+ sb._implied = {testing: {}} # not defined by SpecificationBasePy
+ self.assertTrue(sb(testing))
+
+ def test_isOrExtends_miss(self):
+ sb = self._makeOne()
+ sb._implied = {} # not defined by SpecificationBasePy
+ self.assertFalse(sb.isOrExtends(object()))
+
+ def test_isOrExtends_hit(self):
+ sb = self._makeOne()
+ testing = object()
+ sb._implied = {testing: {}} # not defined by SpecificationBasePy
+ self.assertTrue(sb(testing))
+
+ def test_implementedBy_hit(self):
+ from zope.interface import interface
+ sb = self._makeOne()
+ class _Decl(object):
+ _implied = {sb: {},}
+ def _implementedBy(obj):
+ return _Decl()
+ with _Monkey(interface, implementedBy=_implementedBy):
+ self.assertTrue(sb.implementedBy(object()))
+
+ def test_providedBy_hit(self):
+ from zope.interface import interface
+ sb = self._makeOne()
+ class _Decl(object):
+ _implied = {sb: {},}
+ def _providedBy(obj):
+ return _Decl()
+ with _Monkey(interface, providedBy=_providedBy):
+ self.assertTrue(sb.providedBy(object()))
+
+
+class NameAndModuleComparisonTestsMixin(CleanUp):
+
+ def _makeOneToCompare(self):
+ return self._makeOne('a', 'b')
+
+ def __check_NotImplemented_comparison(self, name):
+ # Without the correct attributes of __name__ and __module__,
+ # comparison switches to the reverse direction.
+
+ import operator
+ ib = self._makeOneToCompare()
+ op = getattr(operator, name)
+ meth = getattr(ib, '__%s__' % name)
+
+ # If either the __name__ or __module__ attribute
+ # is missing from the other object, then we return
+ # NotImplemented.
+ class RaisesErrorOnMissing(object):
+ Exc = AttributeError
+ def __getattribute__(self, name):
+ try:
+ return object.__getattribute__(self, name)
+ except AttributeError:
+ exc = RaisesErrorOnMissing.Exc
+ raise exc(name)
+
+ class RaisesErrorOnModule(RaisesErrorOnMissing):
+ def __init__(self):
+ self.__name__ = 'foo'
+ @property
+ def __module__(self):
+ raise AttributeError
+
+ class RaisesErrorOnName(RaisesErrorOnMissing):
+ def __init__(self):
+ self.__module__ = 'foo'
+
+ self.assertEqual(RaisesErrorOnModule().__name__, 'foo')
+ self.assertEqual(RaisesErrorOnName().__module__, 'foo')
+ with self.assertRaises(AttributeError):
+ getattr(RaisesErrorOnModule(), '__module__')
+ with self.assertRaises(AttributeError):
+ getattr(RaisesErrorOnName(), '__name__')
+
+ for cls in RaisesErrorOnModule, RaisesErrorOnName:
+ self.assertIs(meth(cls()), NotImplemented)
+
+ # If the other object has a comparison function, returning
+ # NotImplemented means Python calls it.
+
+ class AllowsAnyComparison(RaisesErrorOnMissing):
+ def __eq__(self, other):
+ return True
+ __lt__ = __eq__
+ __le__ = __eq__
+ __gt__ = __eq__
+ __ge__ = __eq__
+ __ne__ = __eq__
+
+ self.assertTrue(op(ib, AllowsAnyComparison()))
+ self.assertIs(meth(AllowsAnyComparison()), NotImplemented)
+
+ # If it doesn't have the comparison, Python raises a TypeError.
+ class AllowsNoComparison(object):
+ __eq__ = None
+ __lt__ = __eq__
+ __le__ = __eq__
+ __gt__ = __eq__
+ __ge__ = __eq__
+ __ne__ = __eq__
+
+ self.assertIs(meth(AllowsNoComparison()), NotImplemented)
+ with self.assertRaises(TypeError):
+ op(ib, AllowsNoComparison())
+
+ # Errors besides AttributeError are passed
+ class MyException(Exception):
+ pass
+
+ RaisesErrorOnMissing.Exc = MyException
+
+ with self.assertRaises(MyException):
+ getattr(RaisesErrorOnModule(), '__module__')
+ with self.assertRaises(MyException):
+ getattr(RaisesErrorOnName(), '__name__')
+
+ for cls in RaisesErrorOnModule, RaisesErrorOnName:
+ with self.assertRaises(MyException):
+ op(ib, cls())
+ with self.assertRaises(MyException):
+ meth(cls())
+
+ def test__lt__NotImplemented(self):
+ self.__check_NotImplemented_comparison('lt')
+
+ def test__le__NotImplemented(self):
+ self.__check_NotImplemented_comparison('le')
+
+ def test__gt__NotImplemented(self):
+ self.__check_NotImplemented_comparison('gt')
+
+ def test__ge__NotImplemented(self):
+ self.__check_NotImplemented_comparison('ge')
+
+
+class InterfaceBaseTestsMixin(NameAndModuleComparisonTestsMixin):
+ # Tests for both C and Python implementation
+
+ def _getTargetClass(self):
+ raise NotImplementedError
+
+ def _getFallbackClass(self):
+ # pylint:disable=no-name-in-module
+ from zope.interface.interface import InterfaceBasePy
+ return InterfaceBasePy
+
+ def _makeOne(self, object_should_provide=False, name=None, module=None):
+ class IB(self._getTargetClass()):
+ def _call_conform(self, conform):
+ return conform(self)
+ def providedBy(self, obj):
+ return object_should_provide
+ return IB(name, module)
+
+ def test___call___w___conform___returning_value(self):
+ ib = self._makeOne(False)
+ conformed = object()
+ class _Adapted(object):
+ def __conform__(self, iface):
+ return conformed
+ self.assertIs(ib(_Adapted()), conformed)
+
+ def test___call___wo___conform___ob_no_provides_w_alternate(self):
+ ib = self._makeOne(False)
+ __traceback_info__ = ib, self._getTargetClass()
+ adapted = object()
+ alternate = object()
+ self.assertIs(ib(adapted, alternate), alternate)
+
+ def test___call___w___conform___ob_no_provides_wo_alternate(self):
+ ib = self._makeOne(False)
+ with self.assertRaises(TypeError) as exc:
+ ib(object())
+
+ self.assertIn('Could not adapt', str(exc.exception))
+
+ def test___call___w_no_conform_catches_only_AttributeError(self):
+ MissingSomeAttrs.test_raises(self, self._makeOne(), expected_missing='__conform__')
+
+
+class InterfaceBaseTests(InterfaceBaseTestsMixin,
+ OptimizationTestMixin,
+ unittest.TestCase):
+ # Tests that work with the C implementation
+ def _getTargetClass(self):
+ from zope.interface.interface import InterfaceBase
+ return InterfaceBase
+
+
+class InterfaceBasePyTests(InterfaceBaseTestsMixin, unittest.TestCase):
+ # Tests that only work with the Python implementation
+
+ _getTargetClass = InterfaceBaseTestsMixin._getFallbackClass
+
+ def test___call___w___conform___miss_ob_provides(self):
+ ib = self._makeOne(True)
+ class _Adapted(object):
+ def __conform__(self, iface):
+ return None
+ adapted = _Adapted()
+ self.assertIs(ib(adapted), adapted)
+
+ def test___adapt___ob_provides(self):
+ ib = self._makeOne(True)
+ adapted = object()
+ self.assertIs(ib.__adapt__(adapted), adapted)
+
+ def test___adapt___ob_no_provides_uses_hooks(self):
+ from zope.interface import interface
+ ib = self._makeOne(False)
+ adapted = object()
+ _missed = []
+ def _hook_miss(iface, obj):
+ _missed.append((iface, obj))
+ def _hook_hit(iface, obj):
+ return obj
+ with _Monkey(interface, adapter_hooks=[_hook_miss, _hook_hit]):
+ self.assertIs(ib.__adapt__(adapted), adapted)
+ self.assertEqual(_missed, [(ib, adapted)])
+
+class SpecificationTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.interface import Specification
+ return Specification
+
+ def _makeOne(self, bases=_marker):
+ if bases is _marker:
+ return self._getTargetClass()()
+ return self._getTargetClass()(bases)
+
+ def test_ctor(self):
+ from zope.interface.interface import Interface
+ spec = self._makeOne()
+ self.assertEqual(spec.__bases__, ())
+ self.assertEqual(len(spec._implied), 2)
+ self.assertTrue(spec in spec._implied)
+ self.assertTrue(Interface in spec._implied)
+ self.assertEqual(len(spec.dependents), 0)
+
+ def test_subscribe_first_time(self):
+ spec = self._makeOne()
+ dep = DummyDependent()
+ spec.subscribe(dep)
+ self.assertEqual(len(spec.dependents), 1)
+ self.assertEqual(spec.dependents[dep], 1)
+
+ def test_subscribe_again(self):
+ spec = self._makeOne()
+ dep = DummyDependent()
+ spec.subscribe(dep)
+ spec.subscribe(dep)
+ self.assertEqual(spec.dependents[dep], 2)
+
+ def test_unsubscribe_miss(self):
+ spec = self._makeOne()
+ dep = DummyDependent()
+ self.assertRaises(KeyError, spec.unsubscribe, dep)
+
+ def test_unsubscribe(self):
+ spec = self._makeOne()
+ dep = DummyDependent()
+ spec.subscribe(dep)
+ spec.subscribe(dep)
+ spec.unsubscribe(dep)
+ self.assertEqual(spec.dependents[dep], 1)
+ spec.unsubscribe(dep)
+ self.assertFalse(dep in spec.dependents)
+
+ def test___setBases_subscribes_bases_and_notifies_dependents(self):
+ from zope.interface.interface import Interface
+ spec = self._makeOne()
+ dep = DummyDependent()
+ spec.subscribe(dep)
+ class I(Interface):
+ pass
+ class J(Interface):
+ pass
+ spec.__bases__ = (I,)
+ self.assertEqual(dep._changed, [spec])
+ self.assertEqual(I.dependents[spec], 1)
+ spec.__bases__ = (J,)
+ self.assertEqual(I.dependents.get(spec), None)
+ self.assertEqual(J.dependents[spec], 1)
+
+ def test_changed_clears_volatiles_and_implied(self):
+ from zope.interface.interface import Interface
+ class I(Interface):
+ pass
+ spec = self._makeOne()
+ spec._v_attrs = 'Foo'
+ spec._implied[I] = ()
+ spec.changed(spec)
+ self.assertIsNone(spec._v_attrs)
+ self.assertFalse(I in spec._implied)
+
+ def test_interfaces_skips_already_seen(self):
+ from zope.interface.interface import Interface
+ class IFoo(Interface):
+ pass
+ spec = self._makeOne([IFoo, IFoo])
+ self.assertEqual(list(spec.interfaces()), [IFoo])
+
+ def test_extends_strict_wo_self(self):
+ from zope.interface.interface import Interface
+ class IFoo(Interface):
+ pass
+ spec = self._makeOne(IFoo)
+ self.assertFalse(spec.extends(IFoo, strict=True))
+
+ def test_extends_strict_w_self(self):
+ spec = self._makeOne()
+ self.assertFalse(spec.extends(spec, strict=True))
+
+ def test_extends_non_strict_w_self(self):
+ spec = self._makeOne()
+ self.assertTrue(spec.extends(spec, strict=False))
+
+ def test_get_hit_w__v_attrs(self):
+ spec = self._makeOne()
+ foo = object()
+ spec._v_attrs = {'foo': foo}
+ self.assertTrue(spec.get('foo') is foo)
+
+ def test_get_hit_from_base_wo__v_attrs(self):
+ from zope.interface.interface import Attribute
+ from zope.interface.interface import Interface
+ class IFoo(Interface):
+ foo = Attribute('foo')
+ class IBar(Interface):
+ bar = Attribute('bar')
+ spec = self._makeOne([IFoo, IBar])
+ self.assertTrue(spec.get('foo') is IFoo.get('foo'))
+ self.assertTrue(spec.get('bar') is IBar.get('bar'))
+
+ def test_multiple_inheritance_no_interfaces(self):
+ # If we extend an object that implements interfaces,
+ # plus one that doesn't, we do not interject `Interface`
+ # early in the resolution order. It stays at the end,
+ # like it should.
+ # See https://github.com/zopefoundation/zope.interface/issues/8
+ from zope.interface.interface import Interface
+ from zope.interface.declarations import implementer
+ from zope.interface.declarations import implementedBy
+
+ class IDefaultViewName(Interface):
+ pass
+
+ class Context(object):
+ pass
+
+ class RDBModel(Context):
+ pass
+
+ class IOther(Interface):
+ pass
+
+ @implementer(IOther)
+ class OtherBase(object):
+ pass
+
+ class Model(OtherBase, Context):
+ pass
+
+ self.assertEqual(
+ implementedBy(Model).__sro__,
+ (
+ implementedBy(Model),
+ implementedBy(OtherBase),
+ IOther,
+ implementedBy(Context),
+ implementedBy(object),
+ Interface, # This used to be wrong, it used to be 2 too high.
+ )
+ )
+
+
+class InterfaceClassTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.interface import InterfaceClass
+ return InterfaceClass
+
+ def _makeOne(self, name='ITest', bases=(), attrs=None, __doc__=None,
+ __module__=None):
+ return self._getTargetClass()(name, bases, attrs, __doc__, __module__)
+
+ def test_ctor_defaults(self):
+ klass = self._getTargetClass()
+ inst = klass('ITesting')
+ self.assertEqual(inst.__name__, 'ITesting')
+ self.assertEqual(inst.__doc__, '')
+ self.assertEqual(inst.__bases__, ())
+ self.assertEqual(inst.getBases(), ())
+
+ def test_ctor_bad_bases(self):
+ klass = self._getTargetClass()
+ self.assertRaises(TypeError, klass, 'ITesting', (object(),))
+
+ def test_ctor_w_attrs_attrib_methods(self):
+ from zope.interface.interface import Attribute
+ from zope.interface.interface import fromFunction
+ def _bar():
+ """DOCSTRING"""
+ ATTRS = {'foo': Attribute('Foo', ''),
+ 'bar': fromFunction(_bar),
+ }
+ klass = self._getTargetClass()
+ inst = klass('ITesting', attrs=ATTRS)
+ self.assertEqual(inst.__name__, 'ITesting')
+ self.assertEqual(inst.__doc__, '')
+ self.assertEqual(inst.__bases__, ())
+ self.assertEqual(inst.names(), ATTRS.keys())
+
+ def test_ctor_attrs_w___locals__(self):
+ ATTRS = {'__locals__': {}}
+ klass = self._getTargetClass()
+ inst = klass('ITesting', attrs=ATTRS)
+ self.assertEqual(inst.__name__, 'ITesting')
+ self.assertEqual(inst.__doc__, '')
+ self.assertEqual(inst.__bases__, ())
+ self.assertEqual(list(inst.names()), [])
+
+ def test_ctor_attrs_w___annotations__(self):
+ ATTRS = {'__annotations__': {}}
+ klass = self._getTargetClass()
+ inst = klass('ITesting', attrs=ATTRS)
+ self.assertEqual(inst.__name__, 'ITesting')
+ self.assertEqual(inst.__doc__, '')
+ self.assertEqual(inst.__bases__, ())
+ self.assertEqual(list(inst.names()), [])
+
+ def test_ctor_attrs_w__decorator_non_return(self):
+ from zope.interface.interface import _decorator_non_return
+ ATTRS = {'dropme': _decorator_non_return}
+ klass = self._getTargetClass()
+ inst = klass('ITesting', attrs=ATTRS)
+ self.assertEqual(inst.__name__, 'ITesting')
+ self.assertEqual(inst.__doc__, '')
+ self.assertEqual(inst.__bases__, ())
+ self.assertEqual(list(inst.names()), [])
+
+ def test_ctor_attrs_w_invalid_attr_type(self):
+ from zope.interface.exceptions import InvalidInterface
+ ATTRS = {'invalid': object()}
+ klass = self._getTargetClass()
+ self.assertRaises(InvalidInterface, klass, 'ITesting', attrs=ATTRS)
+
+ def test_ctor_w_explicit___doc__(self):
+ ATTRS = {'__doc__': 'ATTR'}
+ klass = self._getTargetClass()
+ inst = klass('ITesting', attrs=ATTRS, __doc__='EXPLICIT')
+ self.assertEqual(inst.__doc__, 'EXPLICIT')
+
+ def test_interfaces(self):
+ iface = self._makeOne()
+ self.assertEqual(list(iface.interfaces()), [iface])
+
+ def test_getBases(self):
+ iface = self._makeOne()
+ sub = self._makeOne('ISub', bases=(iface,))
+ self.assertEqual(sub.getBases(), (iface,))
+
+ def test_isEqualOrExtendedBy_identity(self):
+ iface = self._makeOne()
+ self.assertTrue(iface.isEqualOrExtendedBy(iface))
+
+ def test_isEqualOrExtendedBy_subiface(self):
+ iface = self._makeOne()
+ sub = self._makeOne('ISub', bases=(iface,))
+ self.assertTrue(iface.isEqualOrExtendedBy(sub))
+ self.assertFalse(sub.isEqualOrExtendedBy(iface))
+
+ def test_isEqualOrExtendedBy_unrelated(self):
+ one = self._makeOne('One')
+ another = self._makeOne('Another')
+ self.assertFalse(one.isEqualOrExtendedBy(another))
+ self.assertFalse(another.isEqualOrExtendedBy(one))
+
+ def test_names_w_all_False_ignores_bases(self):
+ from zope.interface.interface import Attribute
+ from zope.interface.interface import fromFunction
+ def _bar():
+ """DOCSTRING"""
+ BASE_ATTRS = {'foo': Attribute('Foo', ''),
+ 'bar': fromFunction(_bar),
+ }
+ DERIVED_ATTRS = {'baz': Attribute('Baz', ''),
+ }
+ base = self._makeOne('IBase', attrs=BASE_ATTRS)
+ derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+ self.assertEqual(sorted(derived.names(all=False)), ['baz'])
+
+ def test_names_w_all_True_no_bases(self):
+ from zope.interface.interface import Attribute
+ from zope.interface.interface import fromFunction
+ def _bar():
+ """DOCSTRING"""
+ ATTRS = {'foo': Attribute('Foo', ''),
+ 'bar': fromFunction(_bar),
+ }
+ one = self._makeOne(attrs=ATTRS)
+ self.assertEqual(sorted(one.names(all=True)), ['bar', 'foo'])
+
+ def test_names_w_all_True_w_bases_simple(self):
+ from zope.interface.interface import Attribute
+ from zope.interface.interface import fromFunction
+ def _bar():
+ """DOCSTRING"""
+ BASE_ATTRS = {'foo': Attribute('Foo', ''),
+ 'bar': fromFunction(_bar),
+ }
+ DERIVED_ATTRS = {'baz': Attribute('Baz', ''),
+ }
+ base = self._makeOne('IBase', attrs=BASE_ATTRS)
+ derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+ self.assertEqual(sorted(derived.names(all=True)), ['bar', 'baz', 'foo'])
+
+ def test_names_w_all_True_bases_w_same_names(self):
+ from zope.interface.interface import Attribute
+ from zope.interface.interface import fromFunction
+ def _bar():
+ """DOCSTRING"""
+ def _foo():
+ """DOCSTRING"""
+ BASE_ATTRS = {'foo': Attribute('Foo', ''),
+ 'bar': fromFunction(_bar),
+ }
+ DERIVED_ATTRS = {'foo': fromFunction(_foo),
+ 'baz': Attribute('Baz', ''),
+ }
+ base = self._makeOne('IBase', attrs=BASE_ATTRS)
+ derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+ self.assertEqual(sorted(derived.names(all=True)), ['bar', 'baz', 'foo'])
+
+ def test___iter__(self):
+ from zope.interface.interface import Attribute
+ from zope.interface.interface import fromFunction
+ def _bar():
+ """DOCSTRING"""
+ def _foo():
+ """DOCSTRING"""
+ BASE_ATTRS = {'foo': Attribute('Foo', ''),
+ 'bar': fromFunction(_bar),
+ }
+ DERIVED_ATTRS = {'foo': fromFunction(_foo),
+ 'baz': Attribute('Baz', ''),
+ }
+ base = self._makeOne('IBase', attrs=BASE_ATTRS)
+ derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+ self.assertEqual(sorted(derived), ['bar', 'baz', 'foo'])
+
+ def test_namesAndDescriptions_w_all_False_ignores_bases(self):
+ from zope.interface.interface import Attribute
+ from zope.interface.interface import fromFunction
+ def _bar():
+ """DOCSTRING"""
+ BASE_ATTRS = {'foo': Attribute('Foo', ''),
+ 'bar': fromFunction(_bar),
+ }
+ DERIVED_ATTRS = {'baz': Attribute('Baz', ''),
+ }
+ base = self._makeOne('IBase', attrs=BASE_ATTRS)
+ derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+ self.assertEqual(sorted(derived.namesAndDescriptions(all=False)),
+ [('baz', DERIVED_ATTRS['baz']),
+ ])
+
+ def test_namesAndDescriptions_w_all_True_no_bases(self):
+ from zope.interface.interface import Attribute
+ from zope.interface.interface import fromFunction
+ def _bar():
+ """DOCSTRING"""
+ ATTRS = {'foo': Attribute('Foo', ''),
+ 'bar': fromFunction(_bar),
+ }
+ one = self._makeOne(attrs=ATTRS)
+ self.assertEqual(sorted(one.namesAndDescriptions(all=False)),
+ [('bar', ATTRS['bar']),
+ ('foo', ATTRS['foo']),
+ ])
+
+ def test_namesAndDescriptions_w_all_True_simple(self):
+ from zope.interface.interface import Attribute
+ from zope.interface.interface import fromFunction
+ def _bar():
+ """DOCSTRING"""
+ BASE_ATTRS = {'foo': Attribute('Foo', ''),
+ 'bar': fromFunction(_bar),
+ }
+ DERIVED_ATTRS = {'baz': Attribute('Baz', ''),
+ }
+ base = self._makeOne('IBase', attrs=BASE_ATTRS)
+ derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+ self.assertEqual(sorted(derived.namesAndDescriptions(all=True)),
+ [('bar', BASE_ATTRS['bar']),
+ ('baz', DERIVED_ATTRS['baz']),
+ ('foo', BASE_ATTRS['foo']),
+ ])
+
+ def test_namesAndDescriptions_w_all_True_bases_w_same_names(self):
+ from zope.interface.interface import Attribute
+ from zope.interface.interface import fromFunction
+ def _bar():
+ """DOCSTRING"""
+ def _foo():
+ """DOCSTRING"""
+ BASE_ATTRS = {'foo': Attribute('Foo', ''),
+ 'bar': fromFunction(_bar),
+ }
+ DERIVED_ATTRS = {'foo': fromFunction(_foo),
+ 'baz': Attribute('Baz', ''),
+ }
+ base = self._makeOne('IBase', attrs=BASE_ATTRS)
+ derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+ self.assertEqual(sorted(derived.namesAndDescriptions(all=True)),
+ [('bar', BASE_ATTRS['bar']),
+ ('baz', DERIVED_ATTRS['baz']),
+ ('foo', DERIVED_ATTRS['foo']),
+ ])
+
+ def test_getDescriptionFor_miss(self):
+ one = self._makeOne()
+ self.assertRaises(KeyError, one.getDescriptionFor, 'nonesuch')
+
+ def test_getDescriptionFor_hit(self):
+ from zope.interface.interface import Attribute
+ from zope.interface.interface import fromFunction
+ def _bar():
+ """DOCSTRING"""
+ ATTRS = {'foo': Attribute('Foo', ''),
+ 'bar': fromFunction(_bar),
+ }
+ one = self._makeOne(attrs=ATTRS)
+ self.assertEqual(one.getDescriptionFor('foo'), ATTRS['foo'])
+ self.assertEqual(one.getDescriptionFor('bar'), ATTRS['bar'])
+
+ def test___getitem___miss(self):
+ one = self._makeOne()
+ def _test():
+ return one['nonesuch']
+ self.assertRaises(KeyError, _test)
+
+ def test___getitem___hit(self):
+ from zope.interface.interface import Attribute
+ from zope.interface.interface import fromFunction
+ def _bar():
+ """DOCSTRING"""
+ ATTRS = {'foo': Attribute('Foo', ''),
+ 'bar': fromFunction(_bar),
+ }
+ one = self._makeOne(attrs=ATTRS)
+ self.assertEqual(one['foo'], ATTRS['foo'])
+ self.assertEqual(one['bar'], ATTRS['bar'])
+
+ def test___contains___miss(self):
+ one = self._makeOne()
+ self.assertFalse('nonesuch' in one)
+
+ def test___contains___hit(self):
+ from zope.interface.interface import Attribute
+ from zope.interface.interface import fromFunction
+ def _bar():
+ """DOCSTRING"""
+ ATTRS = {'foo': Attribute('Foo', ''),
+ 'bar': fromFunction(_bar),
+ }
+ one = self._makeOne(attrs=ATTRS)
+ self.assertTrue('foo' in one)
+ self.assertTrue('bar' in one)
+
+ def test_direct_miss(self):
+ one = self._makeOne()
+ self.assertEqual(one.direct('nonesuch'), None)
+
+ def test_direct_hit_local_miss_bases(self):
+ from zope.interface.interface import Attribute
+ from zope.interface.interface import fromFunction
+ def _bar():
+ """DOCSTRING"""
+ def _foo():
+ """DOCSTRING"""
+ BASE_ATTRS = {'foo': Attribute('Foo', ''),
+ 'bar': fromFunction(_bar),
+ }
+ DERIVED_ATTRS = {'foo': fromFunction(_foo),
+ 'baz': Attribute('Baz', ''),
+ }
+ base = self._makeOne('IBase', attrs=BASE_ATTRS)
+ derived = self._makeOne('IDerived', bases=(base,), attrs=DERIVED_ATTRS)
+ self.assertEqual(derived.direct('foo'), DERIVED_ATTRS['foo'])
+ self.assertEqual(derived.direct('baz'), DERIVED_ATTRS['baz'])
+ self.assertEqual(derived.direct('bar'), None)
+
+ def test_queryDescriptionFor_miss(self):
+ iface = self._makeOne()
+ self.assertEqual(iface.queryDescriptionFor('nonesuch'), None)
+
+ def test_queryDescriptionFor_hit(self):
+ from zope.interface import Attribute
+ ATTRS = {'attr': Attribute('Title', 'Description')}
+ iface = self._makeOne(attrs=ATTRS)
+ self.assertEqual(iface.queryDescriptionFor('attr'), ATTRS['attr'])
+
+ def test_validateInvariants_pass(self):
+ _called_with = []
+ def _passable(*args, **kw):
+ _called_with.append((args, kw))
+ return True
+ iface = self._makeOne()
+ obj = object()
+ iface.setTaggedValue('invariants', [_passable])
+ self.assertEqual(iface.validateInvariants(obj), None)
+ self.assertEqual(_called_with, [((obj,), {})])
+
+ def test_validateInvariants_fail_wo_errors_passed(self):
+ from zope.interface.exceptions import Invalid
+ _passable_called_with = []
+ def _passable(*args, **kw):
+ _passable_called_with.append((args, kw))
+ return True
+ _fail_called_with = []
+ def _fail(*args, **kw):
+ _fail_called_with.append((args, kw))
+ raise Invalid
+ iface = self._makeOne()
+ obj = object()
+ iface.setTaggedValue('invariants', [_passable, _fail])
+ self.assertRaises(Invalid, iface.validateInvariants, obj)
+ self.assertEqual(_passable_called_with, [((obj,), {})])
+ self.assertEqual(_fail_called_with, [((obj,), {})])
+
+ def test_validateInvariants_fail_w_errors_passed(self):
+ from zope.interface.exceptions import Invalid
+ _errors = []
+ _fail_called_with = []
+ def _fail(*args, **kw):
+ _fail_called_with.append((args, kw))
+ raise Invalid
+ iface = self._makeOne()
+ obj = object()
+ iface.setTaggedValue('invariants', [_fail])
+ self.assertRaises(Invalid, iface.validateInvariants, obj, _errors)
+ self.assertEqual(_fail_called_with, [((obj,), {})])
+ self.assertEqual(len(_errors), 1)
+ self.assertTrue(isinstance(_errors[0], Invalid))
+
+ def test_validateInvariants_fail_in_base_wo_errors_passed(self):
+ from zope.interface.exceptions import Invalid
+ _passable_called_with = []
+ def _passable(*args, **kw):
+ _passable_called_with.append((args, kw))
+ return True
+ _fail_called_with = []
+ def _fail(*args, **kw):
+ _fail_called_with.append((args, kw))
+ raise Invalid
+ base = self._makeOne('IBase')
+ derived = self._makeOne('IDerived', (base,))
+ obj = object()
+ base.setTaggedValue('invariants', [_fail])
+ derived.setTaggedValue('invariants', [_passable])
+ self.assertRaises(Invalid, derived.validateInvariants, obj)
+ self.assertEqual(_passable_called_with, [((obj,), {})])
+ self.assertEqual(_fail_called_with, [((obj,), {})])
+
+ def test_validateInvariants_fail_in_base_w_errors_passed(self):
+ from zope.interface.exceptions import Invalid
+ _errors = []
+ _passable_called_with = []
+ def _passable(*args, **kw):
+ _passable_called_with.append((args, kw))
+ return True
+ _fail_called_with = []
+ def _fail(*args, **kw):
+ _fail_called_with.append((args, kw))
+ raise Invalid
+ base = self._makeOne('IBase')
+ derived = self._makeOne('IDerived', (base,))
+ obj = object()
+ base.setTaggedValue('invariants', [_fail])
+ derived.setTaggedValue('invariants', [_passable])
+ self.assertRaises(Invalid, derived.validateInvariants, obj, _errors)
+ self.assertEqual(_passable_called_with, [((obj,), {})])
+ self.assertEqual(_fail_called_with, [((obj,), {})])
+ self.assertEqual(len(_errors), 1)
+ self.assertTrue(isinstance(_errors[0], Invalid))
+
+ def test_validateInvariants_inherited_not_called_multiple_times(self):
+ _passable_called_with = []
+
+ def _passable(*args, **kw):
+ _passable_called_with.append((args, kw))
+ return True
+
+ obj = object()
+ base = self._makeOne('IBase')
+ base.setTaggedValue('invariants', [_passable])
+ derived = self._makeOne('IDerived', (base,))
+ derived.validateInvariants(obj)
+ self.assertEqual(1, len(_passable_called_with))
+
+ def test___reduce__(self):
+ iface = self._makeOne('PickleMe')
+ self.assertEqual(iface.__reduce__(), 'PickleMe')
+
+ def test___hash___normal(self):
+ iface = self._makeOne('HashMe')
+ self.assertEqual(hash(iface),
+ hash((('HashMe',
+ '__tests__.tests.test_interface'))))
+
+ def test___hash___missing_required_attrs(self):
+ class Derived(self._getTargetClass()):
+ def __init__(self): # pylint:disable=super-init-not-called
+ pass # Don't call base class.
+ derived = Derived()
+ with self.assertRaises(AttributeError):
+ hash(derived)
+
+ def test_comparison_with_None(self):
+ # pylint:disable=singleton-comparison,misplaced-comparison-constant
+ iface = self._makeOne()
+ self.assertTrue(iface < None)
+ self.assertTrue(iface <= None)
+ self.assertFalse(iface == None)
+ self.assertTrue(iface != None)
+ self.assertFalse(iface >= None)
+ self.assertFalse(iface > None)
+
+ self.assertFalse(None < iface)
+ self.assertFalse(None <= iface)
+ self.assertFalse(None == iface)
+ self.assertTrue(None != iface)
+ self.assertTrue(None >= iface)
+ self.assertTrue(None > iface)
+
+ def test_comparison_with_same_instance(self):
+ # pylint:disable=comparison-with-itself
+ iface = self._makeOne()
+
+ self.assertFalse(iface < iface)
+ self.assertTrue(iface <= iface)
+ self.assertTrue(iface == iface)
+ self.assertFalse(iface != iface)
+ self.assertTrue(iface >= iface)
+ self.assertFalse(iface > iface)
+
+ def test_comparison_with_same_named_instance_in_other_module(self):
+
+ one = self._makeOne('IName', __module__='__tests__.tests.one')
+ other = self._makeOne('IName', __module__='__tests__.tests.other')
+
+ self.assertTrue(one < other)
+ self.assertFalse(other < one)
+ self.assertTrue(one <= other)
+ self.assertFalse(other <= one)
+ self.assertFalse(one == other)
+ self.assertFalse(other == one)
+ self.assertTrue(one != other)
+ self.assertTrue(other != one)
+ self.assertFalse(one >= other)
+ self.assertTrue(other >= one)
+ self.assertFalse(one > other)
+ self.assertTrue(other > one)
+
+ def test_assignment_to__class__(self):
+ # https://github.com/zopefoundation/zope.interface/issues/6
+ class MyException(Exception):
+ pass
+
+ class MyInterfaceClass(self._getTargetClass()):
+ def __call__(self, target):
+ raise MyException(target)
+
+ IFoo = self._makeOne('IName')
+ self.assertIsInstance(IFoo, self._getTargetClass())
+ self.assertIs(type(IFoo), self._getTargetClass())
+
+ with self.assertRaises(TypeError):
+ IFoo(1)
+
+ IFoo.__class__ = MyInterfaceClass
+ self.assertIsInstance(IFoo, MyInterfaceClass)
+ self.assertIs(type(IFoo), MyInterfaceClass)
+
+ with self.assertRaises(MyException):
+ IFoo(1)
+
+ def test_assignment_to__class__2(self):
+ # https://github.com/zopefoundation/zope.interface/issues/6
+ # This is essentially a transcription of the
+ # test presented in the bug report.
+ from zope.interface import Interface
+ class MyInterfaceClass(self._getTargetClass()):
+ def __call__(self, *args):
+ return args
+
+ IFoo = MyInterfaceClass('IFoo', (Interface,))
+ self.assertEqual(IFoo(1), (1,))
+
+ class IBar(IFoo):
+ pass
+
+ self.assertEqual(IBar(1), (1,))
+
+ class ISpam(Interface):
+ pass
+
+ with self.assertRaises(TypeError):
+ ISpam()
+
+ ISpam.__class__ = MyInterfaceClass
+ self.assertEqual(ISpam(1), (1,))
+
+ def test__module__is_readonly(self):
+ inst = self._makeOne()
+ with self.assertRaises((AttributeError, TypeError)):
+ # CPython 2.7 raises TypeError. Everything else
+ # raises AttributeError.
+ inst.__module__ = 'different.module'
+
+
+class InterfaceTests(unittest.TestCase):
+
+ def test_attributes_link_to_interface(self):
+ from zope.interface import Interface
+ from zope.interface import Attribute
+
+ class I1(Interface):
+ attr = Attribute("My attr")
+
+ self.assertTrue(I1['attr'].interface is I1)
+
+ def test_methods_link_to_interface(self):
+ from zope.interface import Interface
+
+ class I1(Interface):
+
+ def method(foo, bar, bingo):
+ "A method"
+
+ self.assertTrue(I1['method'].interface is I1)
+
+ def test_classImplements_simple(self):
+ from zope.interface import Interface
+ from zope.interface import implementedBy
+ from zope.interface import providedBy
+
+ class ICurrent(Interface):
+ def method1(a, b):
+ """docstring"""
+ def method2(a, b):
+ """docstring"""
+
+ class IOther(Interface):
+ pass
+
+ class Current(object):
+ __implemented__ = ICurrent
+ def method1(self, a, b):
+ raise NotImplementedError()
+ def method2(self, a, b):
+ raise NotImplementedError()
+
+ current = Current()
+
+ self.assertTrue(ICurrent.implementedBy(Current))
+ self.assertFalse(IOther.implementedBy(Current))
+ self.assertEqual(ICurrent, ICurrent)
+ self.assertTrue(ICurrent in implementedBy(Current))
+ self.assertFalse(IOther in implementedBy(Current))
+ self.assertTrue(ICurrent in providedBy(current))
+ self.assertFalse(IOther in providedBy(current))
+
+ def test_classImplements_base_not_derived(self):
+ from zope.interface import Interface
+ from zope.interface import implementedBy
+ from zope.interface import providedBy
+ class IBase(Interface):
+ def method():
+ """docstring"""
+ class IDerived(IBase):
+ pass
+ class Current():
+ __implemented__ = IBase
+ def method(self):
+ raise NotImplementedError()
+ current = Current()
+
+ self.assertTrue(IBase.implementedBy(Current))
+ self.assertFalse(IDerived.implementedBy(Current))
+ self.assertTrue(IBase in implementedBy(Current))
+ self.assertFalse(IDerived in implementedBy(Current))
+ self.assertTrue(IBase in providedBy(current))
+ self.assertFalse(IDerived in providedBy(current))
+
+ def test_classImplements_base_and_derived(self):
+ from zope.interface import Interface
+ from zope.interface import implementedBy
+ from zope.interface import providedBy
+
+ class IBase(Interface):
+ def method():
+ """docstring"""
+
+ class IDerived(IBase):
+ pass
+
+ class Current(object):
+ __implemented__ = IDerived
+ def method(self):
+ raise NotImplementedError()
+
+ current = Current()
+
+ self.assertTrue(IBase.implementedBy(Current))
+ self.assertTrue(IDerived.implementedBy(Current))
+ self.assertFalse(IBase in implementedBy(Current))
+ self.assertTrue(IBase in implementedBy(Current).flattened())
+ self.assertTrue(IDerived in implementedBy(Current))
+ self.assertFalse(IBase in providedBy(current))
+ self.assertTrue(IBase in providedBy(current).flattened())
+ self.assertTrue(IDerived in providedBy(current))
+
+ def test_classImplements_multiple(self):
+ from zope.interface import Interface
+ from zope.interface import implementedBy
+ from zope.interface import providedBy
+
+ class ILeft(Interface):
+ def method():
+ """docstring"""
+
+ class IRight(ILeft):
+ pass
+
+ class Left(object):
+ __implemented__ = ILeft
+
+ def method(self):
+ raise NotImplementedError()
+
+ class Right(object):
+ __implemented__ = IRight
+
+ class Ambi(Left, Right):
+ pass
+
+ ambi = Ambi()
+
+ self.assertTrue(ILeft.implementedBy(Ambi))
+ self.assertTrue(IRight.implementedBy(Ambi))
+ self.assertTrue(ILeft in implementedBy(Ambi))
+ self.assertTrue(IRight in implementedBy(Ambi))
+ self.assertTrue(ILeft in providedBy(ambi))
+ self.assertTrue(IRight in providedBy(ambi))
+
+ def test_classImplements_multiple_w_explict_implements(self):
+ from zope.interface import Interface
+ from zope.interface import implementedBy
+ from zope.interface import providedBy
+
+ class ILeft(Interface):
+
+ def method():
+ """docstring"""
+
+ class IRight(ILeft):
+ pass
+
+ class IOther(Interface):
+ pass
+
+ class Left():
+ __implemented__ = ILeft
+
+ def method(self):
+ raise NotImplementedError()
+
+ class Right(object):
+ __implemented__ = IRight
+
+ class Other(object):
+ __implemented__ = IOther
+
+ class Mixed(Left, Right):
+ __implemented__ = Left.__implemented__, Other.__implemented__
+
+ mixed = Mixed()
+
+ self.assertTrue(ILeft.implementedBy(Mixed))
+ self.assertFalse(IRight.implementedBy(Mixed))
+ self.assertTrue(IOther.implementedBy(Mixed))
+ self.assertTrue(ILeft in implementedBy(Mixed))
+ self.assertFalse(IRight in implementedBy(Mixed))
+ self.assertTrue(IOther in implementedBy(Mixed))
+ self.assertTrue(ILeft in providedBy(mixed))
+ self.assertFalse(IRight in providedBy(mixed))
+ self.assertTrue(IOther in providedBy(mixed))
+
+ def testInterfaceExtendsInterface(self):
+ from zope.interface import Interface
+
+ new = Interface.__class__
+ FunInterface = new('FunInterface')
+ BarInterface = new('BarInterface', (FunInterface,))
+ BobInterface = new('BobInterface')
+ BazInterface = new('BazInterface', (BobInterface, BarInterface,))
+
+ self.assertTrue(BazInterface.extends(BobInterface))
+ self.assertTrue(BazInterface.extends(BarInterface))
+ self.assertTrue(BazInterface.extends(FunInterface))
+ self.assertFalse(BobInterface.extends(FunInterface))
+ self.assertFalse(BobInterface.extends(BarInterface))
+ self.assertTrue(BarInterface.extends(FunInterface))
+ self.assertFalse(BarInterface.extends(BazInterface))
+
+ def test_verifyClass(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ from zope.interface.verify import verifyClass
+
+
+ class ICheckMe(Interface):
+ attr = Attribute(u'My attr')
+
+ def method():
+ "A method"
+
+ class CheckMe(object):
+ __implemented__ = ICheckMe
+ attr = 'value'
+
+ def method(self):
+ raise NotImplementedError()
+
+ self.assertTrue(verifyClass(ICheckMe, CheckMe))
+
+ def test_verifyObject(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ from zope.interface.verify import verifyObject
+
+
+ class ICheckMe(Interface):
+ attr = Attribute(u'My attr')
+
+ def method():
+ "A method"
+
+ class CheckMe(object):
+ __implemented__ = ICheckMe
+ attr = 'value'
+
+ def method(self):
+ raise NotImplementedError()
+
+ check_me = CheckMe()
+
+ self.assertTrue(verifyObject(ICheckMe, check_me))
+
+ def test_interface_object_provides_Interface(self):
+ from zope.interface import Interface
+
+ class AnInterface(Interface):
+ pass
+
+ self.assertTrue(Interface.providedBy(AnInterface))
+
+ def test_names_simple(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+
+
+ class ISimple(Interface):
+ attr = Attribute(u'My attr')
+
+ def method():
+ """docstring"""
+
+ self.assertEqual(sorted(ISimple.names()), ['attr', 'method'])
+
+ def test_names_derived(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+
+
+ class IBase(Interface):
+ attr = Attribute(u'My attr')
+
+ def method():
+ """docstring"""
+
+ class IDerived(IBase):
+ attr2 = Attribute(u'My attr2')
+
+ def method():
+ """docstring"""
+
+ def method2():
+ """docstring"""
+
+ self.assertEqual(sorted(IDerived.names()),
+ ['attr2', 'method', 'method2'])
+ self.assertEqual(sorted(IDerived.names(all=True)),
+ ['attr', 'attr2', 'method', 'method2'])
+
+ def test_namesAndDescriptions_simple(self):
+ from zope.interface import Attribute
+ from zope.interface.interface import Method
+ from zope.interface import Interface
+
+
+ class ISimple(Interface):
+ attr = Attribute(u'My attr')
+
+ def method():
+ "My method"
+
+ name_values = sorted(ISimple.namesAndDescriptions())
+
+ self.assertEqual(len(name_values), 2)
+ self.assertEqual(name_values[0][0], 'attr')
+ self.assertTrue(isinstance(name_values[0][1], Attribute))
+ self.assertEqual(name_values[0][1].__name__, 'attr')
+ self.assertEqual(name_values[0][1].__doc__, 'My attr')
+ self.assertEqual(name_values[1][0], 'method')
+ self.assertTrue(isinstance(name_values[1][1], Method))
+ self.assertEqual(name_values[1][1].__name__, 'method')
+ self.assertEqual(name_values[1][1].__doc__, 'My method')
+
+ def test_namesAndDescriptions_derived(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ from zope.interface.interface import Method
+
+
+ class IBase(Interface):
+ attr = Attribute(u'My attr')
+
+ def method():
+ "My method"
+
+ class IDerived(IBase):
+ attr2 = Attribute(u'My attr2')
+
+ def method():
+ "My method, overridden"
+
+ def method2():
+ "My method2"
+
+ name_values = sorted(IDerived.namesAndDescriptions())
+
+ self.assertEqual(len(name_values), 3)
+ self.assertEqual(name_values[0][0], 'attr2')
+ self.assertTrue(isinstance(name_values[0][1], Attribute))
+ self.assertEqual(name_values[0][1].__name__, 'attr2')
+ self.assertEqual(name_values[0][1].__doc__, 'My attr2')
+ self.assertEqual(name_values[1][0], 'method')
+ self.assertTrue(isinstance(name_values[1][1], Method))
+ self.assertEqual(name_values[1][1].__name__, 'method')
+ self.assertEqual(name_values[1][1].__doc__, 'My method, overridden')
+ self.assertEqual(name_values[2][0], 'method2')
+ self.assertTrue(isinstance(name_values[2][1], Method))
+ self.assertEqual(name_values[2][1].__name__, 'method2')
+ self.assertEqual(name_values[2][1].__doc__, 'My method2')
+
+ name_values = sorted(IDerived.namesAndDescriptions(all=True))
+
+ self.assertEqual(len(name_values), 4)
+ self.assertEqual(name_values[0][0], 'attr')
+ self.assertTrue(isinstance(name_values[0][1], Attribute))
+ self.assertEqual(name_values[0][1].__name__, 'attr')
+ self.assertEqual(name_values[0][1].__doc__, 'My attr')
+ self.assertEqual(name_values[1][0], 'attr2')
+ self.assertTrue(isinstance(name_values[1][1], Attribute))
+ self.assertEqual(name_values[1][1].__name__, 'attr2')
+ self.assertEqual(name_values[1][1].__doc__, 'My attr2')
+ self.assertEqual(name_values[2][0], 'method')
+ self.assertTrue(isinstance(name_values[2][1], Method))
+ self.assertEqual(name_values[2][1].__name__, 'method')
+ self.assertEqual(name_values[2][1].__doc__, 'My method, overridden')
+ self.assertEqual(name_values[3][0], 'method2')
+ self.assertTrue(isinstance(name_values[3][1], Method))
+ self.assertEqual(name_values[3][1].__name__, 'method2')
+ self.assertEqual(name_values[3][1].__doc__, 'My method2')
+
+ def test_getDescriptionFor_nonesuch_no_default(self):
+ from zope.interface import Interface
+
+ class IEmpty(Interface):
+ pass
+
+ self.assertRaises(KeyError, IEmpty.getDescriptionFor, 'nonesuch')
+
+ def test_getDescriptionFor_simple(self):
+ from zope.interface import Attribute
+ from zope.interface.interface import Method
+ from zope.interface import Interface
+
+
+ class ISimple(Interface):
+ attr = Attribute(u'My attr')
+
+ def method():
+ "My method"
+
+ a_desc = ISimple.getDescriptionFor('attr')
+ self.assertTrue(isinstance(a_desc, Attribute))
+ self.assertEqual(a_desc.__name__, 'attr')
+ self.assertEqual(a_desc.__doc__, 'My attr')
+
+ m_desc = ISimple.getDescriptionFor('method')
+ self.assertTrue(isinstance(m_desc, Method))
+ self.assertEqual(m_desc.__name__, 'method')
+ self.assertEqual(m_desc.__doc__, 'My method')
+
+ def test_getDescriptionFor_derived(self):
+ from zope.interface import Attribute
+ from zope.interface.interface import Method
+ from zope.interface import Interface
+
+
+ class IBase(Interface):
+ attr = Attribute(u'My attr')
+
+ def method():
+ "My method"
+
+ class IDerived(IBase):
+ attr2 = Attribute(u'My attr2')
+
+ def method():
+ "My method, overridden"
+
+ def method2():
+ "My method2"
+
+ a_desc = IDerived.getDescriptionFor('attr')
+ self.assertTrue(isinstance(a_desc, Attribute))
+ self.assertEqual(a_desc.__name__, 'attr')
+ self.assertEqual(a_desc.__doc__, 'My attr')
+
+ m_desc = IDerived.getDescriptionFor('method')
+ self.assertTrue(isinstance(m_desc, Method))
+ self.assertEqual(m_desc.__name__, 'method')
+ self.assertEqual(m_desc.__doc__, 'My method, overridden')
+
+ a2_desc = IDerived.getDescriptionFor('attr2')
+ self.assertTrue(isinstance(a2_desc, Attribute))
+ self.assertEqual(a2_desc.__name__, 'attr2')
+ self.assertEqual(a2_desc.__doc__, 'My attr2')
+
+ m2_desc = IDerived.getDescriptionFor('method2')
+ self.assertTrue(isinstance(m2_desc, Method))
+ self.assertEqual(m2_desc.__name__, 'method2')
+ self.assertEqual(m2_desc.__doc__, 'My method2')
+
+ def test___getitem__nonesuch(self):
+ from zope.interface import Interface
+
+ class IEmpty(Interface):
+ pass
+
+ self.assertRaises(KeyError, IEmpty.__getitem__, 'nonesuch')
+
+ def test___getitem__simple(self):
+ from zope.interface import Attribute
+ from zope.interface.interface import Method
+ from zope.interface import Interface
+
+
+ class ISimple(Interface):
+ attr = Attribute(u'My attr')
+
+ def method():
+ "My method"
+
+ a_desc = ISimple['attr']
+ self.assertTrue(isinstance(a_desc, Attribute))
+ self.assertEqual(a_desc.__name__, 'attr')
+ self.assertEqual(a_desc.__doc__, 'My attr')
+
+ m_desc = ISimple['method']
+ self.assertTrue(isinstance(m_desc, Method))
+ self.assertEqual(m_desc.__name__, 'method')
+ self.assertEqual(m_desc.__doc__, 'My method')
+
+ def test___getitem___derived(self):
+ from zope.interface import Attribute
+ from zope.interface.interface import Method
+ from zope.interface import Interface
+
+
+ class IBase(Interface):
+ attr = Attribute(u'My attr')
+
+ def method():
+ "My method"
+
+ class IDerived(IBase):
+ attr2 = Attribute(u'My attr2')
+
+ def method():
+ "My method, overridden"
+
+ def method2():
+ "My method2"
+
+ a_desc = IDerived['attr']
+ self.assertTrue(isinstance(a_desc, Attribute))
+ self.assertEqual(a_desc.__name__, 'attr')
+ self.assertEqual(a_desc.__doc__, 'My attr')
+
+ m_desc = IDerived['method']
+ self.assertTrue(isinstance(m_desc, Method))
+ self.assertEqual(m_desc.__name__, 'method')
+ self.assertEqual(m_desc.__doc__, 'My method, overridden')
+
+ a2_desc = IDerived['attr2']
+ self.assertTrue(isinstance(a2_desc, Attribute))
+ self.assertEqual(a2_desc.__name__, 'attr2')
+ self.assertEqual(a2_desc.__doc__, 'My attr2')
+
+ m2_desc = IDerived['method2']
+ self.assertTrue(isinstance(m2_desc, Method))
+ self.assertEqual(m2_desc.__name__, 'method2')
+ self.assertEqual(m2_desc.__doc__, 'My method2')
+
+ def test___contains__nonesuch(self):
+ from zope.interface import Interface
+
+ class IEmpty(Interface):
+ pass
+
+ self.assertFalse('nonesuch' in IEmpty)
+
+ def test___contains__simple(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+
+
+ class ISimple(Interface):
+ attr = Attribute(u'My attr')
+
+ def method():
+ "My method"
+
+ self.assertTrue('attr' in ISimple)
+ self.assertTrue('method' in ISimple)
+
+ def test___contains__derived(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+
+
+ class IBase(Interface):
+ attr = Attribute(u'My attr')
+
+ def method():
+ "My method"
+
+ class IDerived(IBase):
+ attr2 = Attribute(u'My attr2')
+
+ def method():
+ "My method, overridden"
+
+ def method2():
+ "My method2"
+
+ self.assertTrue('attr' in IDerived)
+ self.assertTrue('method' in IDerived)
+ self.assertTrue('attr2' in IDerived)
+ self.assertTrue('method2' in IDerived)
+
+ def test___iter__empty(self):
+ from zope.interface import Interface
+
+ class IEmpty(Interface):
+ pass
+
+ self.assertEqual(list(IEmpty), [])
+
+ def test___iter__simple(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+
+
+ class ISimple(Interface):
+ attr = Attribute(u'My attr')
+
+ def method():
+ "My method"
+
+ self.assertEqual(sorted(list(ISimple)), ['attr', 'method'])
+
+ def test___iter__derived(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+
+
+ class IBase(Interface):
+ attr = Attribute(u'My attr')
+
+ def method():
+ "My method"
+
+ class IDerived(IBase):
+ attr2 = Attribute(u'My attr2')
+
+ def method():
+ "My method, overridden"
+
+ def method2():
+ "My method2"
+
+ self.assertEqual(sorted(list(IDerived)),
+ ['attr', 'attr2', 'method', 'method2'])
+
+ def test_function_attributes_become_tagged_values(self):
+ from zope.interface import Interface
+
+ class ITagMe(Interface):
+ def method():
+ """docstring"""
+ method.optional = 1
+
+ method = ITagMe['method']
+ self.assertEqual(method.getTaggedValue('optional'), 1)
+
+ def test___doc___non_element(self):
+ from zope.interface import Interface
+
+ class IHaveADocString(Interface):
+ "xxx"
+
+ self.assertEqual(IHaveADocString.__doc__, "xxx")
+ self.assertEqual(list(IHaveADocString), [])
+
+ def test___doc___as_element(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+
+ class IHaveADocString(Interface):
+ "xxx"
+ __doc__ = Attribute('the doc')
+
+ self.assertEqual(IHaveADocString.__doc__, "")
+ self.assertEqual(list(IHaveADocString), ['__doc__'])
+
+ def _errorsEqual(self, has_invariant, error_len, error_msgs, iface):
+ from zope.interface.exceptions import Invalid
+ self.assertRaises(Invalid, iface.validateInvariants, has_invariant)
+ e = []
+ try:
+ iface.validateInvariants(has_invariant, e)
+ self.fail("validateInvariants should always raise")
+ except Invalid as error:
+ self.assertEqual(error.args[0], e)
+
+ self.assertEqual(len(e), error_len)
+ msgs = [error.args[0] for error in e]
+ msgs.sort()
+ for msg in msgs:
+ self.assertEqual(msg, error_msgs.pop(0))
+
+ def test_invariant_simple(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ from zope.interface import directlyProvides
+ from zope.interface import invariant
+
+ class IInvariant(Interface):
+ foo = Attribute('foo')
+ bar = Attribute('bar; must eval to Boolean True if foo does')
+ invariant(_ifFooThenBar)
+
+ class HasInvariant(object):
+ pass
+
+ # set up
+ has_invariant = HasInvariant()
+ directlyProvides(has_invariant, IInvariant)
+
+ # the tests
+ self.assertEqual(IInvariant.getTaggedValue('invariants'),
+ [_ifFooThenBar])
+ self.assertEqual(IInvariant.validateInvariants(has_invariant), None)
+ has_invariant.bar = 27
+ self.assertEqual(IInvariant.validateInvariants(has_invariant), None)
+ has_invariant.foo = 42
+ self.assertEqual(IInvariant.validateInvariants(has_invariant), None)
+ del has_invariant.bar
+ self._errorsEqual(has_invariant, 1, ['If Foo, then Bar!'],
+ IInvariant)
+
+ def test_invariant_nested(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ from zope.interface import directlyProvides
+ from zope.interface import invariant
+
+ class IInvariant(Interface):
+ foo = Attribute('foo')
+ bar = Attribute('bar; must eval to Boolean True if foo does')
+ invariant(_ifFooThenBar)
+
+ class ISubInvariant(IInvariant):
+ invariant(_barGreaterThanFoo)
+
+ class HasInvariant(object):
+ pass
+
+ # nested interfaces with invariants:
+ self.assertEqual(ISubInvariant.getTaggedValue('invariants'),
+ [_barGreaterThanFoo])
+ has_invariant = HasInvariant()
+ directlyProvides(has_invariant, ISubInvariant)
+ has_invariant.foo = 42
+ # even though the interface has changed, we should still only have one
+ # error.
+ self._errorsEqual(has_invariant, 1, ['If Foo, then Bar!'],
+ ISubInvariant)
+ # however, if we set foo to 0 (Boolean False) and bar to a negative
+ # number then we'll get the new error
+ has_invariant.foo = 2
+ has_invariant.bar = 1
+ self._errorsEqual(has_invariant, 1,
+ ['Please, Boo MUST be greater than Foo!'],
+ ISubInvariant)
+ # and if we set foo to a positive number and boo to 0, we'll
+ # get both errors!
+ has_invariant.foo = 1
+ has_invariant.bar = 0
+ self._errorsEqual(has_invariant, 2,
+ ['If Foo, then Bar!',
+ 'Please, Boo MUST be greater than Foo!'],
+ ISubInvariant)
+ # for a happy ending, we'll make the invariants happy
+ has_invariant.foo = 1
+ has_invariant.bar = 2
+ self.assertEqual(IInvariant.validateInvariants(has_invariant), None)
+
+ def test_invariant_mutandis(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ from zope.interface import directlyProvides
+ from zope.interface import invariant
+
+ class IInvariant(Interface):
+ foo = Attribute('foo')
+ bar = Attribute('bar; must eval to Boolean True if foo does')
+ invariant(_ifFooThenBar)
+
+ class HasInvariant(object):
+ pass
+
+ # now we'll do two invariants on the same interface,
+ # just to make sure that a small
+ # multi-invariant interface is at least minimally tested.
+ has_invariant = HasInvariant()
+ directlyProvides(has_invariant, IInvariant)
+ has_invariant.foo = 42
+
+ # if you really need to mutate, then this would be the way to do it.
+ # Probably a bad idea, though. :-)
+ old_invariants = IInvariant.getTaggedValue('invariants')
+ invariants = old_invariants[:]
+ invariants.append(_barGreaterThanFoo)
+ IInvariant.setTaggedValue('invariants', invariants)
+
+ # even though the interface has changed, we should still only have one
+ # error.
+ self._errorsEqual(has_invariant, 1, ['If Foo, then Bar!'],
+ IInvariant)
+ # however, if we set foo to 0 (Boolean False) and bar to a negative
+ # number then we'll get the new error
+ has_invariant.foo = 2
+ has_invariant.bar = 1
+ self._errorsEqual(has_invariant, 1,
+ ['Please, Boo MUST be greater than Foo!'], IInvariant)
+ # and if we set foo to a positive number and boo to 0, we'll
+ # get both errors!
+ has_invariant.foo = 1
+ has_invariant.bar = 0
+ self._errorsEqual(has_invariant, 2,
+ ['If Foo, then Bar!',
+ 'Please, Boo MUST be greater than Foo!'],
+ IInvariant)
+ # for another happy ending, we'll make the invariants happy again
+ has_invariant.foo = 1
+ has_invariant.bar = 2
+ self.assertEqual(IInvariant.validateInvariants(has_invariant), None)
+ # clean up
+ IInvariant.setTaggedValue('invariants', old_invariants)
+
+ def test___doc___element(self):
+ from zope.interface import Interface
+ from zope.interface import Attribute
+ class IDocstring(Interface):
+ "xxx"
+
+ self.assertEqual(IDocstring.__doc__, "xxx")
+ self.assertEqual(list(IDocstring), [])
+
+ class IDocstringAndAttribute(Interface):
+ "xxx"
+
+ __doc__ = Attribute('the doc')
+
+ self.assertEqual(IDocstringAndAttribute.__doc__, "")
+ self.assertEqual(list(IDocstringAndAttribute), ['__doc__'])
+
+ @_skip_under_py3k
+ def testIssue228(self):
+ # Test for http://collector.zope.org/Zope3-dev/228
+ # Old style classes don't have a '__class__' attribute
+ # No old style classes in Python 3, so the test becomes moot.
+ from zope.interface import Interface
+
+ class I(Interface):
+ "xxx"
+
+ class OldStyle:
+ __providedBy__ = None
+
+ self.assertRaises(AttributeError, I.providedBy, OldStyle)
+
+ def test_invariant_as_decorator(self):
+ from zope.interface import Interface
+ from zope.interface import Attribute
+ from zope.interface import implementer
+ from zope.interface import invariant
+ from zope.interface.exceptions import Invalid
+
+ class IRange(Interface):
+ min = Attribute("Lower bound")
+ max = Attribute("Upper bound")
+
+ @invariant
+ def range_invariant(ob):
+ if ob.max < ob.min:
+ raise Invalid('max < min')
+
+ @implementer(IRange)
+ class Range(object):
+
+ def __init__(self, min, max):
+ self.min, self.max = min, max
+
+ IRange.validateInvariants(Range(1, 2))
+ IRange.validateInvariants(Range(1, 1))
+ try:
+ IRange.validateInvariants(Range(2, 1))
+ except Invalid as e:
+ self.assertEqual(str(e), 'max < min')
+
+ def test_taggedValue(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ from zope.interface import taggedValue
+
+ class ITagged(Interface):
+ foo = Attribute('foo')
+ bar = Attribute('bar; must eval to Boolean True if foo does')
+ taggedValue('qux', 'Spam')
+
+ class IDerived(ITagged):
+ taggedValue('qux', 'Spam Spam')
+ taggedValue('foo', 'bar')
+
+ class IDerived2(IDerived):
+ pass
+
+ self.assertEqual(ITagged.getTaggedValue('qux'), 'Spam')
+ self.assertRaises(KeyError, ITagged.getTaggedValue, 'foo')
+ self.assertEqual(list(ITagged.getTaggedValueTags()), ['qux'])
+
+ self.assertEqual(IDerived2.getTaggedValue('qux'), 'Spam Spam')
+ self.assertEqual(IDerived2.getTaggedValue('foo'), 'bar')
+ self.assertEqual(set(IDerived2.getTaggedValueTags()), set(['qux', 'foo']))
+
+ def _make_taggedValue_tree(self, base):
+ from zope.interface import taggedValue
+ from zope.interface import Attribute
+ O = base
+ class F(O):
+ taggedValue('tag', 'F')
+ tag = Attribute('F')
+ class E(O):
+ taggedValue('tag', 'E')
+ tag = Attribute('E')
+ class D(O):
+ taggedValue('tag', 'D')
+ tag = Attribute('D')
+ class C(D, F):
+ taggedValue('tag', 'C')
+ tag = Attribute('C')
+ class B(D, E):
+ pass
+ class A(B, C):
+ pass
+
+ return A
+
+ def test_getTaggedValue_follows__iro__(self):
+ # And not just looks at __bases__.
+ # https://github.com/zopefoundation/zope.interface/issues/190
+ from zope.interface import Interface
+
+ # First, confirm that looking at a true class
+ # hierarchy follows the __mro__.
+ class_A = self._make_taggedValue_tree(object)
+ self.assertEqual(class_A.tag.__name__, 'C')
+
+ # Now check that Interface does, both for attributes...
+ iface_A = self._make_taggedValue_tree(Interface)
+ self.assertEqual(iface_A['tag'].__name__, 'C')
+ # ... and for tagged values.
+ self.assertEqual(iface_A.getTaggedValue('tag'), 'C')
+ self.assertEqual(iface_A.queryTaggedValue('tag'), 'C')
+ # Of course setting something lower overrides it.
+ assert iface_A.__bases__[0].__name__ == 'B'
+ iface_A.__bases__[0].setTaggedValue('tag', 'B')
+ self.assertEqual(iface_A.getTaggedValue('tag'), 'B')
+
+ def test_getDirectTaggedValue_ignores__iro__(self):
+ # https://github.com/zopefoundation/zope.interface/issues/190
+ from zope.interface import Interface
+
+ A = self._make_taggedValue_tree(Interface)
+ self.assertIsNone(A.queryDirectTaggedValue('tag'))
+ self.assertEqual([], list(A.getDirectTaggedValueTags()))
+
+ with self.assertRaises(KeyError):
+ A.getDirectTaggedValue('tag')
+
+ A.setTaggedValue('tag', 'A')
+ self.assertEqual(A.queryDirectTaggedValue('tag'), 'A')
+ self.assertEqual(A.getDirectTaggedValue('tag'), 'A')
+ self.assertEqual(['tag'], list(A.getDirectTaggedValueTags()))
+
+ assert A.__bases__[1].__name__ == 'C'
+ C = A.__bases__[1]
+ self.assertEqual(C.queryDirectTaggedValue('tag'), 'C')
+ self.assertEqual(C.getDirectTaggedValue('tag'), 'C')
+ self.assertEqual(['tag'], list(C.getDirectTaggedValueTags()))
+
+ def test_description_cache_management(self):
+ # See https://bugs.launchpad.net/zope.interface/+bug/185974
+ # There was a bug where the cache used by Specification.get() was not
+ # cleared when the bases were changed.
+ from zope.interface import Interface
+ from zope.interface import Attribute
+
+ class I1(Interface):
+ a = Attribute('a')
+
+ class I2(I1):
+ pass
+
+ class I3(I2):
+ pass
+
+ self.assertTrue(I3.get('a') is I1.get('a'))
+
+ I2.__bases__ = (Interface,)
+ self.assertTrue(I3.get('a') is None)
+
+ def test___call___defers_to___conform___(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class I(Interface):
+ pass
+
+ @implementer(I)
+ class C(object):
+ def __conform__(self, proto):
+ return 0
+
+ self.assertEqual(I(C()), 0)
+
+ def test___call___object_implements(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class I(Interface):
+ pass
+
+ @implementer(I)
+ class C(object):
+ pass
+
+ c = C()
+ self.assertTrue(I(c) is c)
+
+ def test___call___miss_wo_alternate(self):
+ from zope.interface import Interface
+
+ class I(Interface):
+ pass
+
+ class C(object):
+ pass
+
+ c = C()
+ self.assertRaises(TypeError, I, c)
+
+ def test___call___miss_w_alternate(self):
+ from zope.interface import Interface
+
+ class I(Interface):
+ pass
+
+ class C(object):
+ pass
+
+ c = C()
+ self.assertTrue(I(c, self) is self)
+
+ def test___call___w_adapter_hook(self):
+ from zope.interface import Interface
+ from zope.interface.interface import adapter_hooks
+
+ def _miss(iface, obj):
+ pass
+
+ def _hit(iface, obj):
+ return self
+
+ class I(Interface):
+ pass
+
+ class C(object):
+ pass
+
+ c = C()
+
+ old_adapter_hooks = adapter_hooks[:]
+ adapter_hooks[:] = [_miss, _hit]
+ try:
+ self.assertTrue(I(c) is self)
+ 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__ can ignore the fact that the object provides
+ # the interface if it chooses.
+ self.assertEqual(42, I(O()))
+
+ def test___call___w_overridden_adapt_and_conform(self):
+ # Conform is first, taking precedence over __adapt__,
+ # *if* it returns non-None
+ from zope.interface import Interface
+ from zope.interface import interfacemethod
+ from zope.interface import implementer
+
+ class IAdapt(Interface):
+ @interfacemethod
+ def __adapt__(self, obj):
+ return 42
+
+ class ISimple(Interface):
+ """Nothing special."""
+
+ @implementer(IAdapt)
+ class Conform24(object):
+ def __conform__(self, iface):
+ return 24
+
+ @implementer(IAdapt)
+ class ConformNone(object):
+ def __conform__(self, iface):
+ return None
+
+ self.assertEqual(42, IAdapt(object()))
+
+ self.assertEqual(24, ISimple(Conform24()))
+ self.assertEqual(24, IAdapt(Conform24()))
+
+ with self.assertRaises(TypeError):
+ ISimple(ConformNone())
+
+ self.assertEqual(42, IAdapt(ConformNone()))
+
+
+ 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):
+
+ DEFAULT_NAME = 'TestAttribute'
+
+ def _getTargetClass(self):
+ from zope.interface.interface import Attribute
+ return Attribute
+
+ def test__repr__w_interface(self):
+ method = self._makeOne()
+ method.interface = type(self)
+ r = repr(method)
+ self.assertTrue(r.startswith('<zope.interface.interface.Attribute object at'), r)
+ self.assertTrue(r.endswith(' ' + __name__ + '.AttributeTests.TestAttribute>'), r)
+
+ def test__repr__wo_interface(self):
+ method = self._makeOne()
+ r = repr(method)
+ self.assertTrue(r.startswith('<zope.interface.interface.Attribute object at'), r)
+ self.assertTrue(r.endswith(' TestAttribute>'), r)
+
+ def test__str__w_interface(self):
+ method = self._makeOne()
+ method.interface = type(self)
+ r = str(method)
+ self.assertEqual(r, __name__ + '.AttributeTests.TestAttribute')
+
+ def test__str__wo_interface(self):
+ method = self._makeOne()
+ r = str(method)
+ self.assertEqual(r, 'TestAttribute')
+
+
+class MethodTests(AttributeTests):
+
+ DEFAULT_NAME = 'TestMethod'
+
+ def _getTargetClass(self):
+ from zope.interface.interface import Method
+ return Method
+
+ def test_optional_as_property(self):
+ method = self._makeOne()
+ self.assertEqual(method.optional, {})
+ method.optional = {'foo': 'bar'}
+ self.assertEqual(method.optional, {'foo': 'bar'})
+ del method.optional
+ self.assertEqual(method.optional, {})
+
+ def test___call___raises_BrokenImplementation(self):
+ from zope.interface.exceptions import BrokenImplementation
+ method = self._makeOne()
+ try:
+ method()
+ except BrokenImplementation as e:
+ self.assertEqual(e.interface, None)
+ self.assertEqual(e.name, self.DEFAULT_NAME)
+ else:
+ self.fail('__call__ should raise BrokenImplementation')
+
+ def test_getSignatureInfo_bare(self):
+ method = self._makeOne()
+ info = method.getSignatureInfo()
+ self.assertEqual(list(info['positional']), [])
+ self.assertEqual(list(info['required']), [])
+ self.assertEqual(info['optional'], {})
+ self.assertEqual(info['varargs'], None)
+ self.assertEqual(info['kwargs'], None)
+
+ def test_getSignatureString_bare(self):
+ method = self._makeOne()
+ self.assertEqual(method.getSignatureString(), '()')
+
+ def test_getSignatureString_w_only_required(self):
+ method = self._makeOne()
+ method.positional = method.required = ['foo']
+ self.assertEqual(method.getSignatureString(), '(foo)')
+
+ def test_getSignatureString_w_optional(self):
+ method = self._makeOne()
+ method.positional = method.required = ['foo']
+ method.optional = {'foo': 'bar'}
+ self.assertEqual(method.getSignatureString(), "(foo='bar')")
+
+ def test_getSignatureString_w_varargs(self):
+ method = self._makeOne()
+ method.varargs = 'args'
+ self.assertEqual(method.getSignatureString(), "(*args)")
+
+ def test_getSignatureString_w_kwargs(self):
+ method = self._makeOne()
+ method.kwargs = 'kw'
+ self.assertEqual(method.getSignatureString(), "(**kw)")
+
+ def test__repr__w_interface(self):
+ method = self._makeOne()
+ method.kwargs = 'kw'
+ method.interface = type(self)
+ r = repr(method)
+ self.assertTrue(r.startswith('<zope.interface.interface.Method object at'), r)
+ self.assertTrue(r.endswith(' ' + __name__ + '.MethodTests.TestMethod(**kw)>'), r)
+
+ def test__repr__wo_interface(self):
+ method = self._makeOne()
+ method.kwargs = 'kw'
+ r = repr(method)
+ self.assertTrue(r.startswith('<zope.interface.interface.Method object at'), r)
+ self.assertTrue(r.endswith(' TestMethod(**kw)>'), r)
+
+ def test__str__w_interface(self):
+ method = self._makeOne()
+ method.kwargs = 'kw'
+ method.interface = type(self)
+ r = str(method)
+ self.assertEqual(r, __name__ + '.MethodTests.TestMethod(**kw)')
+
+ def test__str__wo_interface(self):
+ method = self._makeOne()
+ method.kwargs = 'kw'
+ r = str(method)
+ self.assertEqual(r, 'TestMethod(**kw)')
+
+
+class Test_fromFunction(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.interface.interface import fromFunction
+ return fromFunction(*args, **kw)
+
+ def test_bare(self):
+ def _func():
+ "DOCSTRING"
+ method = self._callFUT(_func)
+ self.assertEqual(method.getName(), '_func')
+ self.assertEqual(method.getDoc(), 'DOCSTRING')
+ self.assertEqual(method.interface, None)
+ self.assertEqual(list(method.getTaggedValueTags()), [])
+ info = method.getSignatureInfo()
+ self.assertEqual(list(info['positional']), [])
+ self.assertEqual(list(info['required']), [])
+ self.assertEqual(info['optional'], {})
+ self.assertEqual(info['varargs'], None)
+ self.assertEqual(info['kwargs'], None)
+
+ def test_w_interface(self):
+ from zope.interface.interface import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ def _func():
+ "DOCSTRING"
+ method = self._callFUT(_func, interface=IFoo)
+ self.assertEqual(method.interface, IFoo)
+
+ def test_w_name(self):
+ def _func():
+ "DOCSTRING"
+ method = self._callFUT(_func, name='anotherName')
+ self.assertEqual(method.getName(), 'anotherName')
+
+ def test_w_only_required(self):
+ def _func(foo):
+ "DOCSTRING"
+ method = self._callFUT(_func)
+ info = method.getSignatureInfo()
+ self.assertEqual(list(info['positional']), ['foo'])
+ self.assertEqual(list(info['required']), ['foo'])
+ self.assertEqual(info['optional'], {})
+ self.assertEqual(info['varargs'], None)
+ self.assertEqual(info['kwargs'], None)
+
+ def test_w_optional(self):
+ def _func(foo='bar'):
+ "DOCSTRING"
+ method = self._callFUT(_func)
+ info = method.getSignatureInfo()
+ self.assertEqual(list(info['positional']), ['foo'])
+ self.assertEqual(list(info['required']), [])
+ self.assertEqual(info['optional'], {'foo': 'bar'})
+ self.assertEqual(info['varargs'], None)
+ self.assertEqual(info['kwargs'], None)
+
+ def test_w_optional_self(self):
+ # This is a weird case, trying to cover the following code in
+ # FUT::
+ #
+ # nr = na-len(defaults)
+ # if nr < 0:
+ # defaults=defaults[-nr:]
+ # nr = 0
+ def _func(self='bar'):
+ "DOCSTRING"
+ method = self._callFUT(_func, imlevel=1)
+ info = method.getSignatureInfo()
+ self.assertEqual(list(info['positional']), [])
+ self.assertEqual(list(info['required']), [])
+ self.assertEqual(info['optional'], {})
+ self.assertEqual(info['varargs'], None)
+ self.assertEqual(info['kwargs'], None)
+
+ def test_w_varargs(self):
+ def _func(*args):
+ "DOCSTRING"
+ method = self._callFUT(_func)
+ info = method.getSignatureInfo()
+ self.assertEqual(list(info['positional']), [])
+ self.assertEqual(list(info['required']), [])
+ self.assertEqual(info['optional'], {})
+ self.assertEqual(info['varargs'], 'args')
+ self.assertEqual(info['kwargs'], None)
+
+ def test_w_kwargs(self):
+ def _func(**kw):
+ "DOCSTRING"
+ method = self._callFUT(_func)
+ info = method.getSignatureInfo()
+ self.assertEqual(list(info['positional']), [])
+ self.assertEqual(list(info['required']), [])
+ self.assertEqual(info['optional'], {})
+ self.assertEqual(info['varargs'], None)
+ self.assertEqual(info['kwargs'], 'kw')
+
+ def test_full_spectrum(self):
+ def _func(foo, bar='baz', *args, **kw): # pylint:disable=keyword-arg-before-vararg
+ "DOCSTRING"
+ method = self._callFUT(_func)
+ info = method.getSignatureInfo()
+ self.assertEqual(list(info['positional']), ['foo', 'bar'])
+ self.assertEqual(list(info['required']), ['foo'])
+ self.assertEqual(info['optional'], {'bar': 'baz'})
+ self.assertEqual(info['varargs'], 'args')
+ self.assertEqual(info['kwargs'], 'kw')
+
+
+class Test_fromMethod(unittest.TestCase):
+
+ def _callFUT(self, *args, **kw):
+ from zope.interface.interface import fromMethod
+ return fromMethod(*args, **kw)
+
+ def test_no_args(self):
+ class Foo(object):
+ def bar(self):
+ "DOCSTRING"
+ method = self._callFUT(Foo.bar)
+ self.assertEqual(method.getName(), 'bar')
+ self.assertEqual(method.getDoc(), 'DOCSTRING')
+ self.assertEqual(method.interface, None)
+ self.assertEqual(list(method.getTaggedValueTags()), [])
+ info = method.getSignatureInfo()
+ self.assertEqual(list(info['positional']), [])
+ self.assertEqual(list(info['required']), [])
+ self.assertEqual(info['optional'], {})
+ self.assertEqual(info['varargs'], None)
+ self.assertEqual(info['kwargs'], None)
+
+ def test_full_spectrum(self):
+ class Foo(object):
+ def bar(self, foo, bar='baz', *args, **kw): # pylint:disable=keyword-arg-before-vararg
+ "DOCSTRING"
+ method = self._callFUT(Foo.bar)
+ info = method.getSignatureInfo()
+ self.assertEqual(list(info['positional']), ['foo', 'bar'])
+ self.assertEqual(list(info['required']), ['foo'])
+ self.assertEqual(info['optional'], {'bar': 'baz'})
+ self.assertEqual(info['varargs'], 'args')
+ self.assertEqual(info['kwargs'], 'kw')
+
+ def test_w_non_method(self):
+ def foo():
+ "DOCSTRING"
+ method = self._callFUT(foo)
+ self.assertEqual(method.getName(), 'foo')
+ self.assertEqual(method.getDoc(), 'DOCSTRING')
+ self.assertEqual(method.interface, None)
+ self.assertEqual(list(method.getTaggedValueTags()), [])
+ info = method.getSignatureInfo()
+ self.assertEqual(list(info['positional']), [])
+ self.assertEqual(list(info['required']), [])
+ self.assertEqual(info['optional'], {})
+ self.assertEqual(info['varargs'], None)
+ self.assertEqual(info['kwargs'], None)
+
+class DummyDependent(object):
+
+ def __init__(self):
+ self._changed = []
+
+ def changed(self, originally_changed):
+ self._changed.append(originally_changed)
+
+
+def _barGreaterThanFoo(obj):
+ from zope.interface.exceptions import Invalid
+ foo = getattr(obj, 'foo', None)
+ bar = getattr(obj, 'bar', None)
+ if foo is not None and isinstance(foo, type(bar)):
+ # type checking should be handled elsewhere (like, say,
+ # schema); these invariants should be intra-interface
+ # constraints. This is a hacky way to do it, maybe, but you
+ # get the idea
+ if not bar > foo:
+ raise Invalid('Please, Boo MUST be greater than Foo!')
+
+def _ifFooThenBar(obj):
+ from zope.interface.exceptions import Invalid
+ if getattr(obj, 'foo', None) and not getattr(obj, 'bar', None):
+ raise Invalid('If Foo, then Bar!')
+
+
+class _Monkey(object):
+ # context-manager for replacing module names in the scope of a test.
+ def __init__(self, module, **kw):
+ self.module = module
+ self.to_restore = {key: getattr(module, key) for key in kw}
+ for key, value in kw.items():
+ setattr(module, key, value)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ for key, value in self.to_restore.items():
+ setattr(self.module, key, value)
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/test_interfaces.py b/contrib/python/zope.interface/py2/zope/interface/tests/test_interfaces.py
new file mode 100644
index 0000000000..3f9a504361
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/test_interfaces.py
@@ -0,0 +1,128 @@
+import unittest
+
+
+class _ConformsToIObjectEvent(object):
+
+ def _makeOne(self, target=None):
+ if target is None:
+ target = object()
+ return self._getTargetClass()(target)
+
+ def test_class_conforms_to_IObjectEvent(self):
+ from zope.interface.interfaces import IObjectEvent
+ from zope.interface.verify import verifyClass
+ verifyClass(IObjectEvent, self._getTargetClass())
+
+ def test_instance_conforms_to_IObjectEvent(self):
+ from zope.interface.interfaces import IObjectEvent
+ from zope.interface.verify import verifyObject
+ verifyObject(IObjectEvent, self._makeOne())
+
+
+class _ConformsToIRegistrationEvent(_ConformsToIObjectEvent):
+
+ def test_class_conforms_to_IRegistrationEvent(self):
+ from zope.interface.interfaces import IRegistrationEvent
+ from zope.interface.verify import verifyClass
+ verifyClass(IRegistrationEvent, self._getTargetClass())
+
+ def test_instance_conforms_to_IRegistrationEvent(self):
+ from zope.interface.interfaces import IRegistrationEvent
+ from zope.interface.verify import verifyObject
+ verifyObject(IRegistrationEvent, self._makeOne())
+
+
+class ObjectEventTests(unittest.TestCase, _ConformsToIObjectEvent):
+
+ def _getTargetClass(self):
+ from zope.interface.interfaces import ObjectEvent
+ return ObjectEvent
+
+ def test_ctor(self):
+ target = object()
+ event = self._makeOne(target)
+ self.assertTrue(event.object is target)
+
+
+class RegistrationEventTests(unittest.TestCase,
+ _ConformsToIRegistrationEvent):
+
+ def _getTargetClass(self):
+ from zope.interface.interfaces import RegistrationEvent
+ return RegistrationEvent
+
+ def test___repr__(self):
+ target = object()
+ event = self._makeOne(target)
+ r = repr(event)
+ self.assertEqual(r.splitlines(),
+ ['RegistrationEvent event:', repr(target)])
+
+
+class RegisteredTests(unittest.TestCase,
+ _ConformsToIRegistrationEvent):
+
+ def _getTargetClass(self):
+ from zope.interface.interfaces import Registered
+ return Registered
+
+ def test_class_conforms_to_IRegistered(self):
+ from zope.interface.interfaces import IRegistered
+ from zope.interface.verify import verifyClass
+ verifyClass(IRegistered, self._getTargetClass())
+
+ def test_instance_conforms_to_IRegistered(self):
+ from zope.interface.interfaces import IRegistered
+ from zope.interface.verify import verifyObject
+ verifyObject(IRegistered, self._makeOne())
+
+
+class UnregisteredTests(unittest.TestCase,
+ _ConformsToIRegistrationEvent):
+
+ def _getTargetClass(self):
+ from zope.interface.interfaces import Unregistered
+ return Unregistered
+
+ def test_class_conforms_to_IUnregistered(self):
+ from zope.interface.interfaces import IUnregistered
+ from zope.interface.verify import verifyClass
+ verifyClass(IUnregistered, self._getTargetClass())
+
+ def test_instance_conforms_to_IUnregistered(self):
+ from zope.interface.interfaces import IUnregistered
+ from zope.interface.verify import verifyObject
+ verifyObject(IUnregistered, self._makeOne())
+
+
+class InterfaceClassTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.interface import InterfaceClass
+ return InterfaceClass
+
+ def _getTargetInterface(self):
+ from zope.interface.interfaces import IInterface
+ return IInterface
+
+ def _makeOne(self):
+ from zope.interface.interface import Interface
+ return Interface
+
+ def test_class_conforms(self):
+ from zope.interface.verify import verifyClass
+ verifyClass(self._getTargetInterface(), self._getTargetClass())
+
+ def test_instance_conforms(self):
+ from zope.interface.verify import verifyObject
+ verifyObject(self._getTargetInterface(), self._makeOne())
+
+ def test_instance_consistent__iro__(self):
+ from zope.interface import ro
+ self.assertTrue(ro.is_consistent(self._getTargetInterface()))
+
+ def test_class_consistent__iro__(self):
+ from zope.interface import ro
+ from zope.interface import implementedBy
+
+ self.assertTrue(ro.is_consistent(implementedBy(self._getTargetClass())))
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/test_odd_declarations.py b/contrib/python/zope.interface/py2/zope/interface/tests/test_odd_declarations.py
new file mode 100644
index 0000000000..8a5753aca8
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/test_odd_declarations.py
@@ -0,0 +1,268 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Test interface declarations against ExtensionClass-like classes.
+
+These tests are to make sure we do something sane in the presence of
+classic ExtensionClass classes and instances.
+"""
+import unittest
+
+from . import odd
+from zope.interface import Interface
+from zope.interface import implementer
+from zope.interface import directlyProvides
+from zope.interface import providedBy
+from zope.interface import directlyProvidedBy
+from zope.interface import classImplements
+from zope.interface import classImplementsOnly
+from zope.interface import implementedBy
+from zope.interface._compat import _skip_under_py3k
+
+class I1(Interface): pass
+class I2(Interface): pass
+class I3(Interface): pass
+class I31(I3): pass
+class I4(Interface): pass
+class I5(Interface): pass
+
+class Odd(object):
+ pass
+Odd = odd.MetaClass('Odd', Odd.__bases__, {})
+
+
+class B(Odd): __implemented__ = I2
+
+
+# TODO: We are going to need more magic to make classProvides work with odd
+# classes. This will work in the next iteration. For now, we'll use
+# a different mechanism.
+
+# from zope.interface import classProvides
+class A(Odd):
+ pass
+classImplements(A, I1)
+
+class C(A, B):
+ pass
+classImplements(C, I31)
+
+
+class Test(unittest.TestCase):
+
+ def test_ObjectSpecification(self):
+ c = C()
+ directlyProvides(c, I4)
+ self.assertEqual([i.getName() for i in providedBy(c)],
+ ['I4', 'I31', 'I1', 'I2']
+ )
+ self.assertEqual([i.getName() for i in providedBy(c).flattened()],
+ ['I4', 'I31', 'I3', 'I1', 'I2', 'Interface']
+ )
+ self.assertTrue(I1 in providedBy(c))
+ self.assertFalse(I3 in providedBy(c))
+ self.assertTrue(providedBy(c).extends(I3))
+ self.assertTrue(providedBy(c).extends(I31))
+ self.assertFalse(providedBy(c).extends(I5))
+
+ class COnly(A, B):
+ pass
+ classImplementsOnly(COnly, I31)
+
+ class D(COnly):
+ pass
+ classImplements(D, I5)
+
+ classImplements(D, I5)
+
+ c = D()
+ directlyProvides(c, I4)
+ self.assertEqual([i.getName() for i in providedBy(c)],
+ ['I4', 'I5', 'I31'])
+ self.assertEqual([i.getName() for i in providedBy(c).flattened()],
+ ['I4', 'I5', 'I31', 'I3', 'Interface'])
+ self.assertFalse(I1 in providedBy(c))
+ self.assertFalse(I3 in providedBy(c))
+ self.assertTrue(providedBy(c).extends(I3))
+ self.assertFalse(providedBy(c).extends(I1))
+ self.assertTrue(providedBy(c).extends(I31))
+ self.assertTrue(providedBy(c).extends(I5))
+
+ class COnly(A, B): __implemented__ = I31
+ class D(COnly):
+ pass
+ classImplements(D, I5)
+
+ classImplements(D, I5)
+ c = D()
+ directlyProvides(c, I4)
+ self.assertEqual([i.getName() for i in providedBy(c)],
+ ['I4', 'I5', 'I31'])
+ self.assertEqual([i.getName() for i in providedBy(c).flattened()],
+ ['I4', 'I5', 'I31', 'I3', 'Interface'])
+ self.assertFalse(I1 in providedBy(c))
+ self.assertFalse(I3 in providedBy(c))
+ self.assertTrue(providedBy(c).extends(I3))
+ self.assertFalse(providedBy(c).extends(I1))
+ self.assertTrue(providedBy(c).extends(I31))
+ self.assertTrue(providedBy(c).extends(I5))
+
+ def test_classImplements(self):
+
+ @implementer(I3)
+ class A(Odd):
+ pass
+
+ @implementer(I4)
+ class B(Odd):
+ pass
+
+ class C(A, B):
+ pass
+ classImplements(C, I1, I2)
+ self.assertEqual([i.getName() for i in implementedBy(C)],
+ ['I1', 'I2', 'I3', 'I4'])
+ classImplements(C, I5)
+ self.assertEqual([i.getName() for i in implementedBy(C)],
+ ['I1', 'I2', 'I5', 'I3', 'I4'])
+
+ def test_classImplementsOnly(self):
+ @implementer(I3)
+ class A(Odd):
+ pass
+
+ @implementer(I4)
+ class B(Odd):
+ pass
+
+ class C(A, B):
+ pass
+ classImplementsOnly(C, I1, I2)
+ self.assertEqual([i.__name__ for i in implementedBy(C)],
+ ['I1', 'I2'])
+
+
+ def test_directlyProvides(self):
+ class IA1(Interface): pass
+ class IA2(Interface): pass
+ class IB(Interface): pass
+ class IC(Interface): pass
+ class A(Odd):
+ pass
+ classImplements(A, IA1, IA2)
+
+ class B(Odd):
+ pass
+ classImplements(B, IB)
+
+ class C(A, B):
+ pass
+ classImplements(C, IC)
+
+
+ ob = C()
+ directlyProvides(ob, I1, I2)
+ self.assertTrue(I1 in providedBy(ob))
+ self.assertTrue(I2 in providedBy(ob))
+ self.assertTrue(IA1 in providedBy(ob))
+ self.assertTrue(IA2 in providedBy(ob))
+ self.assertTrue(IB in providedBy(ob))
+ self.assertTrue(IC in providedBy(ob))
+
+ directlyProvides(ob, directlyProvidedBy(ob)-I2)
+ self.assertTrue(I1 in providedBy(ob))
+ self.assertFalse(I2 in providedBy(ob))
+ self.assertFalse(I2 in providedBy(ob))
+ directlyProvides(ob, directlyProvidedBy(ob), I2)
+ self.assertTrue(I2 in providedBy(ob))
+
+ @_skip_under_py3k
+ def test_directlyProvides_fails_for_odd_class(self):
+ self.assertRaises(TypeError, directlyProvides, C, I5)
+
+ # see above
+ #def TODO_test_classProvides_fails_for_odd_class(self):
+ # try:
+ # class A(Odd):
+ # classProvides(I1)
+ # except TypeError:
+ # pass # Success
+ # self.assert_(False,
+ # "Shouldn't be able to use directlyProvides on odd class."
+ # )
+
+ def test_implementedBy(self):
+ class I2(I1): pass
+
+ class C1(Odd):
+ pass
+ classImplements(C1, I2)
+
+ class C2(C1):
+ pass
+ classImplements(C2, I3)
+
+ self.assertEqual([i.getName() for i in implementedBy(C2)],
+ ['I3', 'I2'])
+
+ def test_odd_metaclass_that_doesnt_subclass_type(self):
+ # This was originally a doctest in odd.py.
+ # It verifies that the metaclass the rest of these tests use
+ # works as expected.
+
+ # This is used for testing support for ExtensionClass in new interfaces.
+
+ class A(object):
+ a = 1
+
+ A = odd.MetaClass('A', A.__bases__, A.__dict__)
+
+ class B(object):
+ b = 1
+
+ B = odd.MetaClass('B', B.__bases__, B.__dict__)
+
+ class C(A, B):
+ pass
+
+ self.assertEqual(C.__bases__, (A, B))
+
+ a = A()
+ aa = A()
+ self.assertEqual(a.a, 1)
+ self.assertEqual(aa.a, 1)
+
+ aa.a = 2
+ self.assertEqual(a.a, 1)
+ self.assertEqual(aa.a, 2)
+
+ c = C()
+ self.assertEqual(c.a, 1)
+ self.assertEqual(c.b, 1)
+
+ c.b = 2
+ self.assertEqual(c.b, 2)
+
+ C.c = 1
+ self.assertEqual(c.c, 1)
+ c.c
+
+ try:
+ from types import ClassType
+ except ImportError:
+ pass
+ else:
+ # This test only makes sense under Python 2.x
+ assert not isinstance(C, (type, ClassType))
+
+ self.assertIs(C.__class__.__class__, C.__class__)
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/test_registry.py b/contrib/python/zope.interface/py2/zope/interface/tests/test_registry.py
new file mode 100644
index 0000000000..81bb58a8f2
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/test_registry.py
@@ -0,0 +1,3057 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002, 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Component Registry Tests"""
+# pylint:disable=protected-access
+import unittest
+
+from zope.interface import Interface
+from zope.interface.adapter import VerifyingAdapterRegistry
+
+from zope.interface.registry import Components
+
+class ComponentsTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ return Components
+
+ def _makeOne(self, name='test', *args, **kw):
+ return self._getTargetClass()(name, *args, **kw)
+
+ def _wrapEvents(self):
+ from zope.interface import registry
+ _events = []
+ def _notify(*args, **kw):
+ _events.append((args, kw))
+ _monkey = _Monkey(registry, notify=_notify)
+ return _monkey, _events
+
+ def test_ctor_no_bases(self):
+ from zope.interface.adapter import AdapterRegistry
+ comp = self._makeOne('testing')
+ self.assertEqual(comp.__name__, 'testing')
+ self.assertEqual(comp.__bases__, ())
+ self.assertTrue(isinstance(comp.adapters, AdapterRegistry))
+ self.assertTrue(isinstance(comp.utilities, AdapterRegistry))
+ self.assertEqual(comp.adapters.__bases__, ())
+ self.assertEqual(comp.utilities.__bases__, ())
+ self.assertEqual(comp._utility_registrations, {})
+ self.assertEqual(comp._adapter_registrations, {})
+ self.assertEqual(comp._subscription_registrations, [])
+ self.assertEqual(comp._handler_registrations, [])
+
+ def test_ctor_w_base(self):
+ base = self._makeOne('base')
+ comp = self._makeOne('testing', (base,))
+ self.assertEqual(comp.__name__, 'testing')
+ self.assertEqual(comp.__bases__, (base,))
+ self.assertEqual(comp.adapters.__bases__, (base.adapters,))
+ self.assertEqual(comp.utilities.__bases__, (base.utilities,))
+
+ def test___repr__(self):
+ comp = self._makeOne('testing')
+ self.assertEqual(repr(comp), '<Components testing>')
+
+ # test _init_registries / _init_registrations via only caller, __init__.
+
+ def test_assign_to___bases__(self):
+ base1 = self._makeOne('base1')
+ base2 = self._makeOne('base2')
+ comp = self._makeOne()
+ comp.__bases__ = (base1, base2)
+ self.assertEqual(comp.__bases__, (base1, base2))
+ self.assertEqual(comp.adapters.__bases__,
+ (base1.adapters, base2.adapters))
+ self.assertEqual(comp.utilities.__bases__,
+ (base1.utilities, base2.utilities))
+
+ def test_registerUtility_with_component_name(self):
+ from zope.interface.declarations import named, InterfaceClass
+
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+
+ @named(u'foo')
+ class Foo(object):
+ pass
+ foo = Foo()
+ _info = u'info'
+
+ comp = self._makeOne()
+ comp.registerUtility(foo, ifoo, info=_info)
+ self.assertEqual(
+ comp._utility_registrations[ifoo, u'foo'],
+ (foo, _info, None))
+
+ def test_registerUtility_both_factory_and_component(self):
+ def _factory():
+ raise NotImplementedError()
+ _to_reg = object()
+ comp = self._makeOne()
+ self.assertRaises(TypeError, comp.registerUtility,
+ component=_to_reg, factory=_factory)
+
+ def test_registerUtility_w_component(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Registered
+ from zope.interface.registry import UtilityRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name = u'name'
+ _to_reg = object()
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerUtility(_to_reg, ifoo, _name, _info)
+ self.assertTrue(comp.utilities._adapters[0][ifoo][_name] is _to_reg)
+ self.assertEqual(comp._utility_registrations[ifoo, _name],
+ (_to_reg, _info, None))
+ self.assertEqual(comp.utilities._subscribers[0][ifoo][''], (_to_reg,))
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Registered))
+ self.assertTrue(isinstance(event.object, UtilityRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertTrue(event.object.name is _name)
+ self.assertTrue(event.object.component is _to_reg)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is None)
+
+ def test_registerUtility_w_factory(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Registered
+ from zope.interface.registry import UtilityRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name = u'name'
+ _to_reg = object()
+ def _factory():
+ return _to_reg
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerUtility(None, ifoo, _name, _info, factory=_factory)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Registered))
+ self.assertTrue(isinstance(event.object, UtilityRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertTrue(event.object.name is _name)
+ self.assertTrue(event.object.component is _to_reg)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is _factory)
+
+ def test_registerUtility_no_provided_available(self):
+ class Foo(object):
+ pass
+
+ _info = u'info'
+ _name = u'name'
+ _to_reg = Foo()
+ comp = self._makeOne()
+ self.assertRaises(TypeError,
+ comp.registerUtility, _to_reg, None, _name, _info)
+
+ def test_registerUtility_wo_provided(self):
+ from zope.interface.declarations import directlyProvides
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Registered
+ from zope.interface.registry import UtilityRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ class Foo(object):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name = u'name'
+ _to_reg = Foo()
+ directlyProvides(_to_reg, ifoo)
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerUtility(_to_reg, None, _name, _info)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Registered))
+ self.assertTrue(isinstance(event.object, UtilityRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertTrue(event.object.name is _name)
+ self.assertTrue(event.object.component is _to_reg)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is None)
+
+ def test_registerUtility_duplicates_existing_reg(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name = u'name'
+ _to_reg = object()
+ comp = self._makeOne()
+ comp.registerUtility(_to_reg, ifoo, _name, _info)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerUtility(_to_reg, ifoo, _name, _info)
+ self.assertEqual(len(_events), 0)
+
+ def test_registerUtility_w_different_info(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info1 = u'info1'
+ _info2 = u'info2'
+ _name = u'name'
+ _to_reg = object()
+ comp = self._makeOne()
+ comp.registerUtility(_to_reg, ifoo, _name, _info1)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerUtility(_to_reg, ifoo, _name, _info2)
+ self.assertEqual(len(_events), 2) # unreg, reg
+ self.assertEqual(comp._utility_registrations[(ifoo, _name)],
+ (_to_reg, _info2, None)) # replaced
+ self.assertEqual(comp.utilities._subscribers[0][ifoo][u''],
+ (_to_reg,))
+
+ def test_registerUtility_w_different_names_same_component(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name1 = u'name1'
+ _name2 = u'name2'
+ _other_reg = object()
+ _to_reg = object()
+ comp = self._makeOne()
+ comp.registerUtility(_other_reg, ifoo, _name1, _info)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerUtility(_to_reg, ifoo, _name2, _info)
+ self.assertEqual(len(_events), 1) # reg
+ self.assertEqual(comp._utility_registrations[(ifoo, _name1)],
+ (_other_reg, _info, None))
+ self.assertEqual(comp._utility_registrations[(ifoo, _name2)],
+ (_to_reg, _info, None))
+ self.assertEqual(comp.utilities._subscribers[0][ifoo][u''],
+ (_other_reg, _to_reg,))
+
+ def test_registerUtility_replaces_existing_reg(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Unregistered
+ from zope.interface.interfaces import Registered
+ from zope.interface.registry import UtilityRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name = u'name'
+ _before, _after = object(), object()
+ comp = self._makeOne()
+ comp.registerUtility(_before, ifoo, _name, _info)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerUtility(_after, ifoo, _name, _info)
+ self.assertEqual(len(_events), 2)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Unregistered))
+ self.assertTrue(isinstance(event.object, UtilityRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertTrue(event.object.name is _name)
+ self.assertTrue(event.object.component is _before)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is None)
+ args, kw = _events[1]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Registered))
+ self.assertTrue(isinstance(event.object, UtilityRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertTrue(event.object.name is _name)
+ self.assertTrue(event.object.component is _after)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is None)
+
+ def test_registerUtility_w_existing_subscr(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name1 = u'name1'
+ _name2 = u'name2'
+ _to_reg = object()
+ comp = self._makeOne()
+ comp.registerUtility(_to_reg, ifoo, _name1, _info)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerUtility(_to_reg, ifoo, _name2, _info)
+ self.assertEqual(comp.utilities._subscribers[0][ifoo][''], (_to_reg,))
+
+ def test_registerUtility_wo_event(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name = u'name'
+ _to_reg = object()
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerUtility(_to_reg, ifoo, _name, _info, False)
+ self.assertEqual(len(_events), 0)
+
+ def test_registerUtility_changes_object_identity_after(self):
+ # If a subclass changes the identity of the _utility_registrations,
+ # the cache is updated and the right thing still happens.
+ class CompThatChangesAfter1Reg(self._getTargetClass()):
+ reg_count = 0
+ def registerUtility(self, *args):
+ self.reg_count += 1
+ super(CompThatChangesAfter1Reg, self).registerUtility(*args)
+ if self.reg_count == 1:
+ self._utility_registrations = dict(self._utility_registrations)
+
+ comp = CompThatChangesAfter1Reg()
+ comp.registerUtility(object(), Interface)
+
+ self.assertEqual(len(list(comp.registeredUtilities())), 1)
+
+ class IFoo(Interface):
+ pass
+
+ comp.registerUtility(object(), IFoo)
+ self.assertEqual(len(list(comp.registeredUtilities())), 2)
+
+ def test_registerUtility_changes_object_identity_before(self):
+ # If a subclass changes the identity of the _utility_registrations,
+ # the cache is updated and the right thing still happens.
+ class CompThatChangesAfter2Reg(self._getTargetClass()):
+ reg_count = 0
+ def registerUtility(self, *args):
+ self.reg_count += 1
+ if self.reg_count == 2:
+ self._utility_registrations = dict(self._utility_registrations)
+
+ super(CompThatChangesAfter2Reg, self).registerUtility(*args)
+
+ comp = CompThatChangesAfter2Reg()
+ comp.registerUtility(object(), Interface)
+
+ self.assertEqual(len(list(comp.registeredUtilities())), 1)
+
+ class IFoo(Interface):
+ pass
+
+ comp.registerUtility(object(), IFoo)
+ self.assertEqual(len(list(comp.registeredUtilities())), 2)
+
+
+ class IBar(Interface):
+ pass
+
+ comp.registerUtility(object(), IBar)
+ self.assertEqual(len(list(comp.registeredUtilities())), 3)
+
+
+ def test_unregisterUtility_neither_factory_nor_component_nor_provided(self):
+ comp = self._makeOne()
+ self.assertRaises(TypeError, comp.unregisterUtility,
+ component=None, provided=None, factory=None)
+
+ def test_unregisterUtility_both_factory_and_component(self):
+ def _factory():
+ raise NotImplementedError()
+ _to_reg = object()
+ comp = self._makeOne()
+ self.assertRaises(TypeError, comp.unregisterUtility,
+ component=_to_reg, factory=_factory)
+
+ def test_unregisterUtility_w_component_miss(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _name = u'name'
+ _to_reg = object()
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterUtility(_to_reg, ifoo, _name)
+ self.assertFalse(unreg)
+ self.assertFalse(_events)
+
+ def test_unregisterUtility_w_component(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Unregistered
+ from zope.interface.registry import UtilityRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _name = u'name'
+ _to_reg = object()
+ comp = self._makeOne()
+ comp.registerUtility(_to_reg, ifoo, _name)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterUtility(_to_reg, ifoo, _name)
+ self.assertTrue(unreg)
+ self.assertFalse(comp.utilities._adapters) # all erased
+ self.assertFalse((ifoo, _name) in comp._utility_registrations)
+ self.assertFalse(comp.utilities._subscribers)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Unregistered))
+ self.assertTrue(isinstance(event.object, UtilityRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertTrue(event.object.name is _name)
+ self.assertTrue(event.object.component is _to_reg)
+ self.assertTrue(event.object.factory is None)
+
+ def test_unregisterUtility_w_factory(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Unregistered
+ from zope.interface.registry import UtilityRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name = u'name'
+ _to_reg = object()
+ def _factory():
+ return _to_reg
+ comp = self._makeOne()
+ comp.registerUtility(None, ifoo, _name, _info, factory=_factory)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterUtility(None, ifoo, _name, factory=_factory)
+ self.assertTrue(unreg)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Unregistered))
+ self.assertTrue(isinstance(event.object, UtilityRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertTrue(event.object.name is _name)
+ self.assertTrue(event.object.component is _to_reg)
+ self.assertTrue(event.object.factory is _factory)
+
+ def test_unregisterUtility_wo_explicit_provided(self):
+ from zope.interface.declarations import directlyProvides
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Unregistered
+ from zope.interface.registry import UtilityRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ class Foo(object):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name = u'name'
+ _to_reg = Foo()
+ directlyProvides(_to_reg, ifoo)
+ comp = self._makeOne()
+ comp.registerUtility(_to_reg, ifoo, _name, _info)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterUtility(_to_reg, None, _name)
+ self.assertTrue(unreg)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Unregistered))
+ self.assertTrue(isinstance(event.object, UtilityRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertTrue(event.object.name is _name)
+ self.assertTrue(event.object.component is _to_reg)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is None)
+
+ def test_unregisterUtility_wo_component_or_factory(self):
+ from zope.interface.declarations import directlyProvides
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Unregistered
+ from zope.interface.registry import UtilityRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ class Foo(object):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name = u'name'
+ _to_reg = Foo()
+ directlyProvides(_to_reg, ifoo)
+ comp = self._makeOne()
+ comp.registerUtility(_to_reg, ifoo, _name, _info)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ # Just pass the interface / name
+ unreg = comp.unregisterUtility(provided=ifoo, name=_name)
+ self.assertTrue(unreg)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Unregistered))
+ self.assertTrue(isinstance(event.object, UtilityRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertTrue(event.object.name is _name)
+ self.assertTrue(event.object.component is _to_reg)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is None)
+
+ def test_unregisterUtility_w_existing_subscr(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name1 = u'name1'
+ _name2 = u'name2'
+ _to_reg = object()
+ comp = self._makeOne()
+ comp.registerUtility(_to_reg, ifoo, _name1, _info)
+ comp.registerUtility(_to_reg, ifoo, _name2, _info)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.unregisterUtility(_to_reg, ifoo, _name2)
+ self.assertEqual(comp.utilities._subscribers[0][ifoo][''], (_to_reg,))
+
+ def test_unregisterUtility_w_existing_subscr_non_hashable(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name1 = u'name1'
+ _name2 = u'name2'
+ _to_reg = dict()
+ comp = self._makeOne()
+ comp.registerUtility(_to_reg, ifoo, _name1, _info)
+ comp.registerUtility(_to_reg, ifoo, _name2, _info)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.unregisterUtility(_to_reg, ifoo, _name2)
+ self.assertEqual(comp.utilities._subscribers[0][ifoo][''], (_to_reg,))
+
+ def test_unregisterUtility_w_existing_subscr_non_hashable_fresh_cache(self):
+ # We correctly populate the cache of registrations if it has gone away
+ # (for example, the Components was unpickled)
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.registry import _UtilityRegistrations
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name1 = u'name1'
+ _name2 = u'name2'
+ _to_reg = dict()
+ comp = self._makeOne()
+ comp.registerUtility(_to_reg, ifoo, _name1, _info)
+ comp.registerUtility(_to_reg, ifoo, _name2, _info)
+
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.unregisterUtility(_to_reg, ifoo, _name2)
+ self.assertEqual(comp.utilities._subscribers[0][ifoo][''], (_to_reg,))
+
+ def test_unregisterUtility_w_existing_subscr_non_hashable_reinitted(self):
+ # We correctly populate the cache of registrations if the base objects change
+ # out from under us
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name1 = u'name1'
+ _name2 = u'name2'
+ _to_reg = dict()
+ comp = self._makeOne()
+ comp.registerUtility(_to_reg, ifoo, _name1, _info)
+ comp.registerUtility(_to_reg, ifoo, _name2, _info)
+
+ # zope.component.testing does this
+ comp.__init__('base')
+
+ comp.registerUtility(_to_reg, ifoo, _name2, _info)
+
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ # Nothing to do, but we don't break either
+ comp.unregisterUtility(_to_reg, ifoo, _name2)
+ self.assertEqual(0, len(comp.utilities._subscribers))
+
+ def test_unregisterUtility_w_existing_subscr_other_component(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name1 = u'name1'
+ _name2 = u'name2'
+ _other_reg = object()
+ _to_reg = object()
+ comp = self._makeOne()
+ comp.registerUtility(_other_reg, ifoo, _name1, _info)
+ comp.registerUtility(_to_reg, ifoo, _name2, _info)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.unregisterUtility(_to_reg, ifoo, _name2)
+ self.assertEqual(comp.utilities._subscribers[0][ifoo][''],
+ (_other_reg,))
+
+ def test_unregisterUtility_w_existing_subscr_other_component_mixed_hash(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name1 = u'name1'
+ _name2 = u'name2'
+ # First register something hashable
+ _other_reg = object()
+ # Then it transfers to something unhashable
+ _to_reg = dict()
+ comp = self._makeOne()
+ comp.registerUtility(_other_reg, ifoo, _name1, _info)
+ comp.registerUtility(_to_reg, ifoo, _name2, _info)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.unregisterUtility(_to_reg, ifoo, _name2)
+ self.assertEqual(comp.utilities._subscribers[0][ifoo][''],
+ (_other_reg,))
+
+ def test_registeredUtilities_empty(self):
+ comp = self._makeOne()
+ self.assertEqual(list(comp.registeredUtilities()), [])
+
+ def test_registeredUtilities_notempty(self):
+ from zope.interface.declarations import InterfaceClass
+
+ from zope.interface.registry import UtilityRegistration
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name1 = u'name1'
+ _name2 = u'name2'
+ _to_reg = object()
+ comp = self._makeOne()
+ comp.registerUtility(_to_reg, ifoo, _name1, _info)
+ comp.registerUtility(_to_reg, ifoo, _name2, _info)
+ reg = sorted(comp.registeredUtilities(), key=lambda r: r.name)
+ self.assertEqual(len(reg), 2)
+ self.assertTrue(isinstance(reg[0], UtilityRegistration))
+ self.assertTrue(reg[0].registry is comp)
+ self.assertTrue(reg[0].provided is ifoo)
+ self.assertTrue(reg[0].name is _name1)
+ self.assertTrue(reg[0].component is _to_reg)
+ self.assertTrue(reg[0].info is _info)
+ self.assertTrue(reg[0].factory is None)
+ self.assertTrue(isinstance(reg[1], UtilityRegistration))
+ self.assertTrue(reg[1].registry is comp)
+ self.assertTrue(reg[1].provided is ifoo)
+ self.assertTrue(reg[1].name is _name2)
+ self.assertTrue(reg[1].component is _to_reg)
+ self.assertTrue(reg[1].info is _info)
+ self.assertTrue(reg[1].factory is None)
+
+ def test_queryUtility_miss_no_default(self):
+ from zope.interface.declarations import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ comp = self._makeOne()
+ self.assertTrue(comp.queryUtility(ifoo) is None)
+
+ def test_queryUtility_miss_w_default(self):
+ from zope.interface.declarations import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ comp = self._makeOne()
+ _default = object()
+ self.assertTrue(comp.queryUtility(ifoo, default=_default) is _default)
+
+ def test_queryUtility_hit(self):
+ from zope.interface.declarations import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _to_reg = object()
+ comp = self._makeOne()
+ comp.registerUtility(_to_reg, ifoo)
+ self.assertTrue(comp.queryUtility(ifoo) is _to_reg)
+
+ def test_getUtility_miss(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import ComponentLookupError
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ comp = self._makeOne()
+ self.assertRaises(ComponentLookupError, comp.getUtility, ifoo)
+
+ def test_getUtility_hit(self):
+ from zope.interface.declarations import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _to_reg = object()
+ comp = self._makeOne()
+ comp.registerUtility(_to_reg, ifoo)
+ self.assertTrue(comp.getUtility(ifoo) is _to_reg)
+
+ def test_getUtilitiesFor_miss(self):
+ from zope.interface.declarations import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ comp = self._makeOne()
+ self.assertEqual(list(comp.getUtilitiesFor(ifoo)), [])
+
+ def test_getUtilitiesFor_hit(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _name1 = u'name1'
+ _name2 = u'name2'
+ _to_reg = object()
+ comp = self._makeOne()
+ comp.registerUtility(_to_reg, ifoo, name=_name1)
+ comp.registerUtility(_to_reg, ifoo, name=_name2)
+ self.assertEqual(sorted(comp.getUtilitiesFor(ifoo)),
+ [(_name1, _to_reg), (_name2, _to_reg)])
+
+ def test_getAllUtilitiesRegisteredFor_miss(self):
+ from zope.interface.declarations import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ comp = self._makeOne()
+ self.assertEqual(list(comp.getAllUtilitiesRegisteredFor(ifoo)), [])
+
+ def test_getAllUtilitiesRegisteredFor_hit(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _name1 = u'name1'
+ _name2 = u'name2'
+ _to_reg = object()
+ comp = self._makeOne()
+ comp.registerUtility(_to_reg, ifoo, name=_name1)
+ comp.registerUtility(_to_reg, ifoo, name=_name2)
+ self.assertEqual(list(comp.getAllUtilitiesRegisteredFor(ifoo)),
+ [_to_reg])
+
+ def test_registerAdapter_with_component_name(self):
+ from zope.interface.declarations import named, InterfaceClass
+
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+
+ @named(u'foo')
+ class Foo(object):
+ pass
+ _info = u'info'
+
+ comp = self._makeOne()
+ comp.registerAdapter(Foo, (ibar,), ifoo, info=_info)
+
+ self.assertEqual(
+ comp._adapter_registrations[(ibar,), ifoo, u'foo'],
+ (Foo, _info))
+
+ def test_registerAdapter_w_explicit_provided_and_required(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Registered
+ from zope.interface.registry import AdapterRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ _info = u'info'
+ _name = u'name'
+
+ def _factory(context):
+ raise NotImplementedError()
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerAdapter(_factory, (ibar,), ifoo, _name, _info)
+ self.assertTrue(comp.adapters._adapters[1][ibar][ifoo][_name]
+ is _factory)
+ self.assertEqual(comp._adapter_registrations[(ibar,), ifoo, _name],
+ (_factory, _info))
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Registered))
+ self.assertTrue(isinstance(event.object, AdapterRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertEqual(event.object.required, (ibar,))
+ self.assertTrue(event.object.name is _name)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is _factory)
+
+ def test_registerAdapter_no_provided_available(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+
+ ibar = IFoo('IBar')
+ _info = u'info'
+ _name = u'name'
+
+ class _Factory(object):
+ pass
+
+ comp = self._makeOne()
+ self.assertRaises(TypeError, comp.registerAdapter, _Factory, (ibar,),
+ name=_name, info=_info)
+
+ def test_registerAdapter_wo_explicit_provided(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ from zope.interface.interfaces import Registered
+ from zope.interface.registry import AdapterRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ _info = u'info'
+ _name = u'name'
+ _to_reg = object()
+
+ @implementer(ifoo)
+ class _Factory(object):
+ pass
+
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerAdapter(_Factory, (ibar,), name=_name, info=_info)
+ self.assertTrue(comp.adapters._adapters[1][ibar][ifoo][_name]
+ is _Factory)
+ self.assertEqual(comp._adapter_registrations[(ibar,), ifoo, _name],
+ (_Factory, _info))
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Registered))
+ self.assertTrue(isinstance(event.object, AdapterRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertEqual(event.object.required, (ibar,))
+ self.assertTrue(event.object.name is _name)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is _Factory)
+
+ def test_registerAdapter_no_required_available(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+
+ _info = u'info'
+ _name = u'name'
+ class _Factory(object):
+ pass
+
+ comp = self._makeOne()
+ self.assertRaises(TypeError, comp.registerAdapter, _Factory,
+ provided=ifoo, name=_name, info=_info)
+
+ def test_registerAdapter_w_invalid_required(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ _info = u'info'
+ _name = u'name'
+ class _Factory(object):
+ pass
+ comp = self._makeOne()
+ self.assertRaises(TypeError, comp.registerAdapter, _Factory,
+ ibar, provided=ifoo, name=_name, info=_info)
+
+ def test_registerAdapter_w_required_containing_None(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interface import Interface
+ from zope.interface.interfaces import Registered
+ from zope.interface.registry import AdapterRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _name = u'name'
+ class _Factory(object):
+ pass
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerAdapter(_Factory, [None], provided=ifoo,
+ name=_name, info=_info)
+ self.assertTrue(comp.adapters._adapters[1][Interface][ifoo][_name]
+ is _Factory)
+ self.assertEqual(comp._adapter_registrations[(Interface,), ifoo, _name],
+ (_Factory, _info))
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Registered))
+ self.assertTrue(isinstance(event.object, AdapterRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertEqual(event.object.required, (Interface,))
+ self.assertTrue(event.object.name is _name)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is _Factory)
+
+ def test_registerAdapter_w_required_containing_class(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ from zope.interface.declarations import implementedBy
+ from zope.interface.interfaces import Registered
+ from zope.interface.registry import AdapterRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ _info = u'info'
+ _name = u'name'
+ class _Factory(object):
+ pass
+
+ @implementer(ibar)
+ class _Context(object):
+ pass
+ _ctx_impl = implementedBy(_Context)
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerAdapter(_Factory, [_Context], provided=ifoo,
+ name=_name, info=_info)
+ self.assertTrue(comp.adapters._adapters[1][_ctx_impl][ifoo][_name]
+ is _Factory)
+ self.assertEqual(comp._adapter_registrations[(_ctx_impl,), ifoo, _name],
+ (_Factory, _info))
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Registered))
+ self.assertTrue(isinstance(event.object, AdapterRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertEqual(event.object.required, (_ctx_impl,))
+ self.assertTrue(event.object.name is _name)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is _Factory)
+
+ def test_registerAdapter_w_required_containing_junk(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+
+ _info = u'info'
+ _name = u'name'
+ class _Factory(object):
+ pass
+ comp = self._makeOne()
+ self.assertRaises(TypeError, comp.registerAdapter, _Factory, [object()],
+ provided=ifoo, name=_name, info=_info)
+
+ def test_registerAdapter_wo_explicit_required(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Registered
+ from zope.interface.registry import AdapterRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ _info = u'info'
+ _name = u'name'
+ class _Factory(object):
+ __component_adapts__ = (ibar,)
+
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerAdapter(_Factory, provided=ifoo, name=_name,
+ info=_info)
+ self.assertTrue(comp.adapters._adapters[1][ibar][ifoo][_name]
+ is _Factory)
+ self.assertEqual(comp._adapter_registrations[(ibar,), ifoo, _name],
+ (_Factory, _info))
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Registered))
+ self.assertTrue(isinstance(event.object, AdapterRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertEqual(event.object.required, (ibar,))
+ self.assertTrue(event.object.name is _name)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is _Factory)
+
+ def test_registerAdapter_wo_event(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ _info = u'info'
+ _name = u'name'
+
+ def _factory(context):
+ raise NotImplementedError()
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerAdapter(_factory, (ibar,), ifoo, _name, _info,
+ event=False)
+ self.assertEqual(len(_events), 0)
+
+ def test_unregisterAdapter_neither_factory_nor_provided(self):
+ comp = self._makeOne()
+ self.assertRaises(TypeError, comp.unregisterAdapter,
+ factory=None, provided=None)
+
+ def test_unregisterAdapter_neither_factory_nor_required(self):
+ from zope.interface.declarations import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ comp = self._makeOne()
+ self.assertRaises(TypeError, comp.unregisterAdapter,
+ factory=None, provided=ifoo, required=None)
+
+ def test_unregisterAdapter_miss(self):
+ from zope.interface.declarations import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ class _Factory(object):
+ pass
+
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterAdapter(_Factory, (ibar,), ifoo)
+ self.assertFalse(unreg)
+
+ def test_unregisterAdapter_hit_w_explicit_provided_and_required(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Unregistered
+ from zope.interface.registry import AdapterRegistration
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ class _Factory(object):
+ pass
+
+ comp = self._makeOne()
+ comp.registerAdapter(_Factory, (ibar,), ifoo)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterAdapter(_Factory, (ibar,), ifoo)
+ self.assertTrue(unreg)
+ self.assertFalse(comp.adapters._adapters)
+ self.assertFalse(comp._adapter_registrations)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Unregistered))
+ self.assertTrue(isinstance(event.object, AdapterRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertEqual(event.object.required, (ibar,))
+ self.assertEqual(event.object.name, '')
+ self.assertEqual(event.object.info, '')
+ self.assertTrue(event.object.factory is _Factory)
+
+ def test_unregisterAdapter_wo_explicit_provided(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ from zope.interface.interfaces import Unregistered
+ from zope.interface.registry import AdapterRegistration
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ @implementer(ifoo)
+ class _Factory(object):
+ pass
+
+ comp = self._makeOne()
+ comp.registerAdapter(_Factory, (ibar,), ifoo)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterAdapter(_Factory, (ibar,))
+ self.assertTrue(unreg)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Unregistered))
+ self.assertTrue(isinstance(event.object, AdapterRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertEqual(event.object.required, (ibar,))
+ self.assertEqual(event.object.name, '')
+ self.assertEqual(event.object.info, '')
+ self.assertTrue(event.object.factory is _Factory)
+
+ def test_unregisterAdapter_wo_explicit_required(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Unregistered
+ from zope.interface.registry import AdapterRegistration
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ class _Factory(object):
+ __component_adapts__ = (ibar,)
+
+ comp = self._makeOne()
+ comp.registerAdapter(_Factory, (ibar,), ifoo)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterAdapter(_Factory, provided=ifoo)
+ self.assertTrue(unreg)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Unregistered))
+ self.assertTrue(isinstance(event.object, AdapterRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertEqual(event.object.required, (ibar,))
+ self.assertEqual(event.object.name, '')
+ self.assertEqual(event.object.info, '')
+ self.assertTrue(event.object.factory is _Factory)
+
+ def test_registeredAdapters_empty(self):
+ comp = self._makeOne()
+ self.assertEqual(list(comp.registeredAdapters()), [])
+
+ def test_registeredAdapters_notempty(self):
+ from zope.interface.declarations import InterfaceClass
+
+ from zope.interface.registry import AdapterRegistration
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IFoo')
+ _info = u'info'
+ _name1 = u'name1'
+ _name2 = u'name2'
+ class _Factory(object):
+ pass
+
+ comp = self._makeOne()
+ comp.registerAdapter(_Factory, (ibar,), ifoo, _name1, _info)
+ comp.registerAdapter(_Factory, (ibar,), ifoo, _name2, _info)
+ reg = sorted(comp.registeredAdapters(), key=lambda r: r.name)
+ self.assertEqual(len(reg), 2)
+ self.assertTrue(isinstance(reg[0], AdapterRegistration))
+ self.assertTrue(reg[0].registry is comp)
+ self.assertTrue(reg[0].provided is ifoo)
+ self.assertEqual(reg[0].required, (ibar,))
+ self.assertTrue(reg[0].name is _name1)
+ self.assertTrue(reg[0].info is _info)
+ self.assertTrue(reg[0].factory is _Factory)
+ self.assertTrue(isinstance(reg[1], AdapterRegistration))
+ self.assertTrue(reg[1].registry is comp)
+ self.assertTrue(reg[1].provided is ifoo)
+ self.assertEqual(reg[1].required, (ibar,))
+ self.assertTrue(reg[1].name is _name2)
+ self.assertTrue(reg[1].info is _info)
+ self.assertTrue(reg[1].factory is _Factory)
+
+ def test_queryAdapter_miss_no_default(self):
+ from zope.interface.declarations import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ comp = self._makeOne()
+ _context = object()
+ self.assertTrue(comp.queryAdapter(_context, ifoo) is None)
+
+ def test_queryAdapter_miss_w_default(self):
+ from zope.interface.declarations import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ comp = self._makeOne()
+ _context = object()
+ _default = object()
+ self.assertTrue(
+ comp.queryAdapter(_context, ifoo, default=_default) is _default)
+
+ def test_queryAdapter_hit(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ class _Factory(object):
+ def __init__(self, context):
+ self.context = context
+ @implementer(ibar)
+ class _Context(object):
+ pass
+ _context = _Context()
+ comp = self._makeOne()
+ comp.registerAdapter(_Factory, (ibar,), ifoo)
+ adapter = comp.queryAdapter(_context, ifoo)
+ self.assertTrue(isinstance(adapter, _Factory))
+ self.assertTrue(adapter.context is _context)
+
+ def test_getAdapter_miss(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ from zope.interface.interfaces import ComponentLookupError
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ @implementer(ibar)
+ class _Context(object):
+ pass
+ _context = _Context()
+ comp = self._makeOne()
+ self.assertRaises(ComponentLookupError,
+ comp.getAdapter, _context, ifoo)
+
+ def test_getAdapter_hit(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ class _Factory(object):
+ def __init__(self, context):
+ self.context = context
+ @implementer(ibar)
+ class _Context(object):
+ pass
+ _context = _Context()
+ comp = self._makeOne()
+ comp.registerAdapter(_Factory, (ibar,), ifoo)
+ adapter = comp.getAdapter(_context, ifoo)
+ self.assertIsInstance(adapter, _Factory)
+ self.assertIs(adapter.context, _context)
+
+ def test_getAdapter_hit_super(self):
+ from zope.interface import Interface
+ from zope.interface.declarations import implementer
+
+ class IBase(Interface):
+ pass
+
+ class IDerived(IBase):
+ pass
+
+ class IFoo(Interface):
+ pass
+
+ @implementer(IBase)
+ class Base(object):
+ pass
+
+ @implementer(IDerived)
+ class Derived(Base):
+ pass
+
+ class AdapterBase(object):
+ def __init__(self, context):
+ self.context = context
+
+ class AdapterDerived(object):
+ def __init__(self, context):
+ self.context = context
+
+ comp = self._makeOne()
+ comp.registerAdapter(AdapterDerived, (IDerived,), IFoo)
+ comp.registerAdapter(AdapterBase, (IBase,), IFoo)
+ self._should_not_change(comp)
+
+ derived = Derived()
+ adapter = comp.getAdapter(derived, IFoo)
+ self.assertIsInstance(adapter, AdapterDerived)
+ self.assertIs(adapter.context, derived)
+
+ supe = super(Derived, derived)
+ adapter = comp.getAdapter(supe, IFoo)
+ self.assertIsInstance(adapter, AdapterBase)
+ self.assertIs(adapter.context, derived)
+
+ def test_getAdapter_hit_super_when_parent_implements_interface_diamond(self):
+ from zope.interface import Interface
+ from zope.interface.declarations import implementer
+
+ class IBase(Interface):
+ pass
+
+ class IDerived(IBase):
+ pass
+
+ class IFoo(Interface):
+ pass
+
+ class Base(object):
+ pass
+
+ class Child1(Base):
+ pass
+
+ @implementer(IBase)
+ class Child2(Base):
+ pass
+
+ @implementer(IDerived)
+ class Derived(Child1, Child2):
+ pass
+
+ class AdapterBase(object):
+ def __init__(self, context):
+ self.context = context
+
+ class AdapterDerived(object):
+ def __init__(self, context):
+ self.context = context
+
+ comp = self._makeOne()
+ comp.registerAdapter(AdapterDerived, (IDerived,), IFoo)
+ comp.registerAdapter(AdapterBase, (IBase,), IFoo)
+ self._should_not_change(comp)
+
+ derived = Derived()
+ adapter = comp.getAdapter(derived, IFoo)
+ self.assertIsInstance(adapter, AdapterDerived)
+ self.assertIs(adapter.context, derived)
+
+ supe = super(Derived, derived)
+ adapter = comp.getAdapter(supe, IFoo)
+ self.assertIsInstance(adapter, AdapterBase)
+ self.assertIs(adapter.context, derived)
+
+ def test_queryMultiAdapter_miss(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ ibaz = IFoo('IBaz')
+ @implementer(ibar)
+ class _Context1(object):
+ pass
+ @implementer(ibaz)
+ class _Context2(object):
+ pass
+ _context1 = _Context1()
+ _context2 = _Context2()
+ comp = self._makeOne()
+ self.assertEqual(comp.queryMultiAdapter((_context1, _context2), ifoo),
+ None)
+
+ def test_queryMultiAdapter_miss_w_default(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ ibaz = IFoo('IBaz')
+ @implementer(ibar)
+ class _Context1(object):
+ pass
+ @implementer(ibaz)
+ class _Context2(object):
+ pass
+ _context1 = _Context1()
+ _context2 = _Context2()
+ _default = object()
+ comp = self._makeOne()
+ self.assertTrue(
+ comp.queryMultiAdapter((_context1, _context2), ifoo,
+ default=_default) is _default)
+
+ def test_queryMultiAdapter_hit(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ ibaz = IFoo('IBaz')
+ @implementer(ibar)
+ class _Context1(object):
+ pass
+ @implementer(ibaz)
+ class _Context2(object):
+ pass
+ _context1 = _Context1()
+ _context2 = _Context2()
+ class _Factory(object):
+ def __init__(self, context1, context2):
+ self.context = context1, context2
+ comp = self._makeOne()
+ comp.registerAdapter(_Factory, (ibar, ibaz), ifoo)
+ adapter = comp.queryMultiAdapter((_context1, _context2), ifoo)
+ self.assertTrue(isinstance(adapter, _Factory))
+ self.assertEqual(adapter.context, (_context1, _context2))
+
+ def test_getMultiAdapter_miss(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ from zope.interface.interfaces import ComponentLookupError
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ ibaz = IFoo('IBaz')
+ @implementer(ibar)
+ class _Context1(object):
+ pass
+ @implementer(ibaz)
+ class _Context2(object):
+ pass
+ _context1 = _Context1()
+ _context2 = _Context2()
+ comp = self._makeOne()
+ self.assertRaises(ComponentLookupError,
+ comp.getMultiAdapter, (_context1, _context2), ifoo)
+
+ def test_getMultiAdapter_hit(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ ibaz = IFoo('IBaz')
+ @implementer(ibar)
+ class _Context1(object):
+ pass
+ @implementer(ibaz)
+ class _Context2(object):
+ pass
+ _context1 = _Context1()
+ _context2 = _Context2()
+ class _Factory(object):
+ def __init__(self, context1, context2):
+ self.context = context1, context2
+ comp = self._makeOne()
+ comp.registerAdapter(_Factory, (ibar, ibaz), ifoo)
+ adapter = comp.getMultiAdapter((_context1, _context2), ifoo)
+ self.assertTrue(isinstance(adapter, _Factory))
+ self.assertEqual(adapter.context, (_context1, _context2))
+
+ def _should_not_change(self, comp):
+ # Be sure that none of the underlying structures
+ # get told that they have changed during this process
+ # because that invalidates caches.
+ def no_changes(*args):
+ self.fail("Nothing should get changed")
+ comp.changed = no_changes
+ comp.adapters.changed = no_changes
+ comp.adapters._v_lookup.changed = no_changes
+
+ def test_getMultiAdapter_hit_super(self):
+ from zope.interface import Interface
+ from zope.interface.declarations import implementer
+
+ class IBase(Interface):
+ pass
+
+ class IDerived(IBase):
+ pass
+
+ class IFoo(Interface):
+ pass
+
+ @implementer(IBase)
+ class Base(object):
+ pass
+
+ @implementer(IDerived)
+ class Derived(Base):
+ pass
+
+ class AdapterBase(object):
+ def __init__(self, context1, context2):
+ self.context1 = context1
+ self.context2 = context2
+
+ class AdapterDerived(AdapterBase):
+ pass
+
+ comp = self._makeOne()
+ comp.registerAdapter(AdapterDerived, (IDerived, IDerived), IFoo)
+ comp.registerAdapter(AdapterBase, (IBase, IDerived), IFoo)
+ self._should_not_change(comp)
+
+ derived = Derived()
+ adapter = comp.getMultiAdapter((derived, derived), IFoo)
+ self.assertIsInstance(adapter, AdapterDerived)
+ self.assertIs(adapter.context1, derived)
+ self.assertIs(adapter.context2, derived)
+
+ supe = super(Derived, derived)
+ adapter = comp.getMultiAdapter((supe, derived), IFoo)
+ self.assertIsInstance(adapter, AdapterBase)
+ self.assertNotIsInstance(adapter, AdapterDerived)
+ self.assertIs(adapter.context1, derived)
+ self.assertIs(adapter.context2, derived)
+
+ def test_getAdapters_empty(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ ibaz = IFoo('IBaz')
+ @implementer(ibar)
+ class _Context1(object):
+ pass
+ @implementer(ibaz)
+ class _Context2(object):
+ pass
+ _context1 = _Context1()
+ _context2 = _Context2()
+ comp = self._makeOne()
+ self.assertEqual(
+ list(comp.getAdapters((_context1, _context2), ifoo)), [])
+
+ def test_getAdapters_factory_returns_None(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ ibaz = IFoo('IBaz')
+ @implementer(ibar)
+ class _Context1(object):
+ pass
+ @implementer(ibaz)
+ class _Context2(object):
+ pass
+ _context1 = _Context1()
+ _context2 = _Context2()
+ comp = self._makeOne()
+ _called_with = []
+ def _side_effect_only(context1, context2):
+ _called_with.append((context1, context2))
+ return None
+ comp.registerAdapter(_side_effect_only, (ibar, ibaz), ifoo)
+ self.assertEqual(
+ list(comp.getAdapters((_context1, _context2), ifoo)), [])
+ self.assertEqual(_called_with, [(_context1, _context2)])
+
+ def test_getAdapters_non_empty(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ ibaz = IFoo('IBaz')
+ @implementer(ibar)
+ class _Context1(object):
+ pass
+ @implementer(ibaz)
+ class _Context2(object):
+ pass
+ _context1 = _Context1()
+ _context2 = _Context2()
+ class _Factory1(object):
+ def __init__(self, context1, context2):
+ self.context = context1, context2
+ class _Factory2(object):
+ def __init__(self, context1, context2):
+ self.context = context1, context2
+ _name1 = u'name1'
+ _name2 = u'name2'
+ comp = self._makeOne()
+ comp.registerAdapter(_Factory1, (ibar, ibaz), ifoo, name=_name1)
+ comp.registerAdapter(_Factory2, (ibar, ibaz), ifoo, name=_name2)
+ found = sorted(comp.getAdapters((_context1, _context2), ifoo))
+ self.assertEqual(len(found), 2)
+ self.assertEqual(found[0][0], _name1)
+ self.assertTrue(isinstance(found[0][1], _Factory1))
+ self.assertEqual(found[1][0], _name2)
+ self.assertTrue(isinstance(found[1][1], _Factory2))
+
+ def test_registerSubscriptionAdapter_w_nonblank_name(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ _name = u'name'
+ _info = u'info'
+ def _factory(context):
+ raise NotImplementedError()
+
+ comp = self._makeOne()
+ self.assertRaises(TypeError, comp.registerSubscriptionAdapter,
+ _factory, (ibar,), ifoo, _name, _info)
+
+ def test_registerSubscriptionAdapter_w_explicit_provided_and_required(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Registered
+ from zope.interface.registry import SubscriptionRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ _blank = u''
+ _info = u'info'
+ def _factory(context):
+ raise NotImplementedError()
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerSubscriptionAdapter(_factory, (ibar,), ifoo,
+ info=_info)
+ reg = comp.adapters._subscribers[1][ibar][ifoo][_blank]
+ self.assertEqual(len(reg), 1)
+ self.assertTrue(reg[0] is _factory)
+ self.assertEqual(comp._subscription_registrations,
+ [((ibar,), ifoo, _blank, _factory, _info)])
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Registered))
+ self.assertTrue(isinstance(event.object, SubscriptionRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertEqual(event.object.required, (ibar,))
+ self.assertEqual(event.object.name, _blank)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is _factory)
+
+ def test_registerSubscriptionAdapter_wo_explicit_provided(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ from zope.interface.interfaces import Registered
+ from zope.interface.registry import SubscriptionRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ _info = u'info'
+ _blank = u''
+
+ @implementer(ifoo)
+ class _Factory(object):
+ pass
+
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerSubscriptionAdapter(_Factory, (ibar,), info=_info)
+ reg = comp.adapters._subscribers[1][ibar][ifoo][_blank]
+ self.assertEqual(len(reg), 1)
+ self.assertTrue(reg[0] is _Factory)
+ self.assertEqual(comp._subscription_registrations,
+ [((ibar,), ifoo, _blank, _Factory, _info)])
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Registered))
+ self.assertTrue(isinstance(event.object, SubscriptionRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertEqual(event.object.required, (ibar,))
+ self.assertEqual(event.object.name, _blank)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is _Factory)
+
+ def test_registerSubscriptionAdapter_wo_explicit_required(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Registered
+ from zope.interface.registry import SubscriptionRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ _info = u'info'
+ _blank = u''
+ class _Factory(object):
+ __component_adapts__ = (ibar,)
+
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerSubscriptionAdapter(
+ _Factory, provided=ifoo, info=_info)
+ reg = comp.adapters._subscribers[1][ibar][ifoo][_blank]
+ self.assertEqual(len(reg), 1)
+ self.assertTrue(reg[0] is _Factory)
+ self.assertEqual(comp._subscription_registrations,
+ [((ibar,), ifoo, _blank, _Factory, _info)])
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Registered))
+ self.assertTrue(isinstance(event.object, SubscriptionRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertEqual(event.object.required, (ibar,))
+ self.assertEqual(event.object.name, _blank)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is _Factory)
+
+ def test_registerSubscriptionAdapter_wo_event(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ _blank = u''
+ _info = u'info'
+
+ def _factory(context):
+ raise NotImplementedError()
+
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerSubscriptionAdapter(_factory, (ibar,), ifoo,
+ info=_info, event=False)
+ self.assertEqual(len(_events), 0)
+
+ def test_registeredSubscriptionAdapters_empty(self):
+ comp = self._makeOne()
+ self.assertEqual(list(comp.registeredSubscriptionAdapters()), [])
+
+ def test_registeredSubscriptionAdapters_notempty(self):
+ from zope.interface.declarations import InterfaceClass
+
+ from zope.interface.registry import SubscriptionRegistration
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IFoo')
+ _info = u'info'
+ _blank = u''
+ class _Factory(object):
+ pass
+
+ comp = self._makeOne()
+ comp.registerSubscriptionAdapter(_Factory, (ibar,), ifoo, info=_info)
+ comp.registerSubscriptionAdapter(_Factory, (ibar,), ifoo, info=_info)
+ reg = list(comp.registeredSubscriptionAdapters())
+ self.assertEqual(len(reg), 2)
+ self.assertTrue(isinstance(reg[0], SubscriptionRegistration))
+ self.assertTrue(reg[0].registry is comp)
+ self.assertTrue(reg[0].provided is ifoo)
+ self.assertEqual(reg[0].required, (ibar,))
+ self.assertEqual(reg[0].name, _blank)
+ self.assertTrue(reg[0].info is _info)
+ self.assertTrue(reg[0].factory is _Factory)
+ self.assertTrue(isinstance(reg[1], SubscriptionRegistration))
+ self.assertTrue(reg[1].registry is comp)
+ self.assertTrue(reg[1].provided is ifoo)
+ self.assertEqual(reg[1].required, (ibar,))
+ self.assertEqual(reg[1].name, _blank)
+ self.assertTrue(reg[1].info is _info)
+ self.assertTrue(reg[1].factory is _Factory)
+
+ def test_unregisterSubscriptionAdapter_w_nonblank_name(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ _nonblank = u'nonblank'
+ comp = self._makeOne()
+ self.assertRaises(TypeError, comp.unregisterSubscriptionAdapter,
+ required=ifoo, provided=ibar, name=_nonblank)
+
+ def test_unregisterSubscriptionAdapter_neither_factory_nor_provided(self):
+ comp = self._makeOne()
+ self.assertRaises(TypeError, comp.unregisterSubscriptionAdapter,
+ factory=None, provided=None)
+
+ def test_unregisterSubscriptionAdapter_neither_factory_nor_required(self):
+ from zope.interface.declarations import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ comp = self._makeOne()
+ self.assertRaises(TypeError, comp.unregisterSubscriptionAdapter,
+ factory=None, provided=ifoo, required=None)
+
+ def test_unregisterSubscriptionAdapter_miss(self):
+ from zope.interface.declarations import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ class _Factory(object):
+ pass
+
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterSubscriptionAdapter(_Factory, (ibar,), ifoo)
+ self.assertFalse(unreg)
+ self.assertFalse(_events)
+
+ def test_unregisterSubscriptionAdapter_hit_wo_factory(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Unregistered
+ from zope.interface.registry import SubscriptionRegistration
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ class _Factory(object):
+ pass
+
+ comp = self._makeOne()
+ comp.registerSubscriptionAdapter(_Factory, (ibar,), ifoo)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterSubscriptionAdapter(None, (ibar,), ifoo)
+ self.assertTrue(unreg)
+ self.assertFalse(comp.adapters._subscribers)
+ self.assertFalse(comp._subscription_registrations)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Unregistered))
+ self.assertTrue(isinstance(event.object, SubscriptionRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertEqual(event.object.required, (ibar,))
+ self.assertEqual(event.object.name, '')
+ self.assertEqual(event.object.info, '')
+ self.assertTrue(event.object.factory is None)
+
+ def test_unregisterSubscriptionAdapter_hit_w_factory(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Unregistered
+ from zope.interface.registry import SubscriptionRegistration
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ class _Factory(object):
+ pass
+
+ comp = self._makeOne()
+ comp.registerSubscriptionAdapter(_Factory, (ibar,), ifoo)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterSubscriptionAdapter(_Factory, (ibar,), ifoo)
+ self.assertTrue(unreg)
+ self.assertFalse(comp.adapters._subscribers)
+ self.assertFalse(comp._subscription_registrations)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Unregistered))
+ self.assertTrue(isinstance(event.object, SubscriptionRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertEqual(event.object.required, (ibar,))
+ self.assertEqual(event.object.name, '')
+ self.assertEqual(event.object.info, '')
+ self.assertTrue(event.object.factory is _Factory)
+
+ def test_unregisterSubscriptionAdapter_wo_explicit_provided(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ from zope.interface.interfaces import Unregistered
+ from zope.interface.registry import SubscriptionRegistration
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ @implementer(ifoo)
+ class _Factory(object):
+ pass
+
+ comp = self._makeOne()
+ comp.registerSubscriptionAdapter(_Factory, (ibar,), ifoo)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterSubscriptionAdapter(_Factory, (ibar,))
+ self.assertTrue(unreg)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Unregistered))
+ self.assertTrue(isinstance(event.object, SubscriptionRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertEqual(event.object.required, (ibar,))
+ self.assertEqual(event.object.name, '')
+ self.assertEqual(event.object.info, '')
+ self.assertTrue(event.object.factory is _Factory)
+
+ def test_unregisterSubscriptionAdapter_wo_explicit_required(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Unregistered
+ from zope.interface.registry import SubscriptionRegistration
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ class _Factory(object):
+ __component_adapts__ = (ibar,)
+
+ comp = self._makeOne()
+ comp.registerSubscriptionAdapter(_Factory, (ibar,), ifoo)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterSubscriptionAdapter(_Factory, provided=ifoo)
+ self.assertTrue(unreg)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Unregistered))
+ self.assertTrue(isinstance(event.object, SubscriptionRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertTrue(event.object.provided is ifoo)
+ self.assertEqual(event.object.required, (ibar,))
+ self.assertEqual(event.object.name, '')
+ self.assertEqual(event.object.info, '')
+ self.assertTrue(event.object.factory is _Factory)
+
+ def test_subscribers_empty(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ comp = self._makeOne()
+ @implementer(ibar)
+ class Bar(object):
+ pass
+ bar = Bar()
+ self.assertEqual(list(comp.subscribers((bar,), ifoo)), [])
+
+ def test_subscribers_non_empty(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ class _Factory(object):
+ __component_adapts__ = (ibar,)
+ def __init__(self, context):
+ self._context = context
+ class _Derived(_Factory):
+ pass
+ comp = self._makeOne()
+ comp.registerSubscriptionAdapter(_Factory, (ibar,), ifoo)
+ comp.registerSubscriptionAdapter(_Derived, (ibar,), ifoo)
+ @implementer(ibar)
+ class Bar(object):
+ pass
+ bar = Bar()
+ subscribers = comp.subscribers((bar,), ifoo)
+ def _klassname(x):
+ return x.__class__.__name__
+ subscribers = sorted(subscribers, key=_klassname)
+ self.assertEqual(len(subscribers), 2)
+ self.assertTrue(isinstance(subscribers[0], _Derived))
+ self.assertTrue(isinstance(subscribers[1], _Factory))
+
+ def test_registerHandler_w_nonblank_name(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _nonblank = u'nonblank'
+ comp = self._makeOne()
+ def _factory(context):
+ raise NotImplementedError()
+
+ self.assertRaises(TypeError, comp.registerHandler, _factory,
+ required=ifoo, name=_nonblank)
+
+ def test_registerHandler_w_explicit_required(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Registered
+ from zope.interface.registry import HandlerRegistration
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _blank = u''
+ _info = u'info'
+ def _factory(context):
+ raise NotImplementedError()
+
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerHandler(_factory, (ifoo,), info=_info)
+ reg = comp.adapters._subscribers[1][ifoo][None][_blank]
+ self.assertEqual(len(reg), 1)
+ self.assertTrue(reg[0] is _factory)
+ self.assertEqual(comp._handler_registrations,
+ [((ifoo,), _blank, _factory, _info)])
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Registered))
+ self.assertTrue(isinstance(event.object, HandlerRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertEqual(event.object.required, (ifoo,))
+ self.assertEqual(event.object.name, _blank)
+ self.assertTrue(event.object.info is _info)
+ self.assertTrue(event.object.factory is _factory)
+
+ def test_registerHandler_wo_explicit_required_no_event(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _info = u'info'
+ _blank = u''
+ class _Factory(object):
+ __component_adapts__ = (ifoo,)
+ pass
+
+ comp = self._makeOne()
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ comp.registerHandler(_Factory, info=_info, event=False)
+ reg = comp.adapters._subscribers[1][ifoo][None][_blank]
+ self.assertEqual(len(reg), 1)
+ self.assertTrue(reg[0] is _Factory)
+ self.assertEqual(comp._handler_registrations,
+ [((ifoo,), _blank, _Factory, _info)])
+ self.assertEqual(len(_events), 0)
+
+ def test_registeredHandlers_empty(self):
+ comp = self._makeOne()
+ self.assertFalse(list(comp.registeredHandlers()))
+
+ def test_registeredHandlers_non_empty(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.registry import HandlerRegistration
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ def _factory1(context):
+ raise NotImplementedError()
+ def _factory2(context):
+ raise NotImplementedError()
+ comp = self._makeOne()
+ comp.registerHandler(_factory1, (ifoo,))
+ comp.registerHandler(_factory2, (ifoo,))
+ def _factory_name(x):
+ return x.factory.__code__.co_name
+ subscribers = sorted(comp.registeredHandlers(), key=_factory_name)
+ self.assertEqual(len(subscribers), 2)
+ self.assertTrue(isinstance(subscribers[0], HandlerRegistration))
+ self.assertEqual(subscribers[0].required, (ifoo,))
+ self.assertEqual(subscribers[0].name, '')
+ self.assertEqual(subscribers[0].factory, _factory1)
+ self.assertEqual(subscribers[0].info, '')
+ self.assertTrue(isinstance(subscribers[1], HandlerRegistration))
+ self.assertEqual(subscribers[1].required, (ifoo,))
+ self.assertEqual(subscribers[1].name, '')
+ self.assertEqual(subscribers[1].factory, _factory2)
+ self.assertEqual(subscribers[1].info, '')
+
+ def test_unregisterHandler_w_nonblank_name(self):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _nonblank = u'nonblank'
+ comp = self._makeOne()
+ self.assertRaises(TypeError, comp.unregisterHandler,
+ required=(ifoo,), name=_nonblank)
+
+ def test_unregisterHandler_neither_factory_nor_required(self):
+ comp = self._makeOne()
+ self.assertRaises(TypeError, comp.unregisterHandler)
+
+ def test_unregisterHandler_miss(self):
+ from zope.interface.declarations import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ comp = self._makeOne()
+ unreg = comp.unregisterHandler(required=(ifoo,))
+ self.assertFalse(unreg)
+
+ def test_unregisterHandler_hit_w_factory_and_explicit_provided(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Unregistered
+ from zope.interface.registry import HandlerRegistration
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ comp = self._makeOne()
+ def _factory(context):
+ raise NotImplementedError()
+ comp = self._makeOne()
+ comp.registerHandler(_factory, (ifoo,))
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterHandler(_factory, (ifoo,))
+ self.assertTrue(unreg)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Unregistered))
+ self.assertTrue(isinstance(event.object, HandlerRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertEqual(event.object.required, (ifoo,))
+ self.assertEqual(event.object.name, '')
+ self.assertTrue(event.object.factory is _factory)
+
+ def test_unregisterHandler_hit_w_only_explicit_provided(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Unregistered
+ from zope.interface.registry import HandlerRegistration
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ comp = self._makeOne()
+ def _factory(context):
+ raise NotImplementedError()
+ comp = self._makeOne()
+ comp.registerHandler(_factory, (ifoo,))
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterHandler(required=(ifoo,))
+ self.assertTrue(unreg)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Unregistered))
+ self.assertTrue(isinstance(event.object, HandlerRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertEqual(event.object.required, (ifoo,))
+ self.assertEqual(event.object.name, '')
+ self.assertTrue(event.object.factory is None)
+
+ def test_unregisterHandler_wo_explicit_required(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.interfaces import Unregistered
+ from zope.interface.registry import HandlerRegistration
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ class _Factory(object):
+ __component_adapts__ = (ifoo,)
+
+ comp = self._makeOne()
+ comp.registerHandler(_Factory)
+ _monkey, _events = self._wrapEvents()
+ with _monkey:
+ unreg = comp.unregisterHandler(_Factory)
+ self.assertTrue(unreg)
+ self.assertEqual(len(_events), 1)
+ args, kw = _events[0]
+ event, = args
+ self.assertEqual(kw, {})
+ self.assertTrue(isinstance(event, Unregistered))
+ self.assertTrue(isinstance(event.object, HandlerRegistration))
+ self.assertTrue(event.object.registry is comp)
+ self.assertEqual(event.object.required, (ifoo,))
+ self.assertEqual(event.object.name, '')
+ self.assertEqual(event.object.info, '')
+ self.assertTrue(event.object.factory is _Factory)
+
+ def test_handle_empty(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ comp = self._makeOne()
+ @implementer(ifoo)
+ class Bar(object):
+ pass
+ bar = Bar()
+ comp.handle((bar,)) # doesn't raise
+
+ def test_handle_non_empty(self):
+ from zope.interface.declarations import InterfaceClass
+ from zope.interface.declarations import implementer
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ _called_1 = []
+ def _factory_1(context):
+ _called_1.append(context)
+ _called_2 = []
+ def _factory_2(context):
+ _called_2.append(context)
+ comp = self._makeOne()
+ comp.registerHandler(_factory_1, (ifoo,))
+ comp.registerHandler(_factory_2, (ifoo,))
+ @implementer(ifoo)
+ class Bar(object):
+ pass
+ bar = Bar()
+ comp.handle(bar)
+ self.assertEqual(_called_1, [bar])
+ self.assertEqual(_called_2, [bar])
+
+ def test_register_unregister_identical_objects_provided(self, identical=True):
+ # https://github.com/zopefoundation/zope.interface/issues/227
+ class IFoo(Interface):
+ pass
+
+ comp = self._makeOne()
+ first = object()
+ second = first if identical else object()
+
+ comp.registerUtility(first, provided=IFoo)
+ comp.registerUtility(second, provided=IFoo, name='bar')
+
+ self.assertEqual(len(comp.utilities._subscribers), 1)
+ self.assertEqual(comp.utilities._subscribers, [{
+ IFoo: {'': (first, ) if identical else (first, second)}
+ }])
+ self.assertEqual(comp.utilities._provided, {
+ IFoo: 3 if identical else 4
+ })
+
+ res = comp.unregisterUtility(first, provided=IFoo)
+ self.assertTrue(res)
+ res = comp.unregisterUtility(second, provided=IFoo, name='bar')
+ self.assertTrue(res)
+
+ self.assertEqual(comp.utilities._provided, {})
+ self.assertEqual(len(comp.utilities._subscribers), 0)
+
+ def test_register_unregister_nonequal_objects_provided(self):
+ self.test_register_unregister_identical_objects_provided(identical=False)
+
+ def test_rebuildUtilityRegistryFromLocalCache(self):
+ class IFoo(Interface):
+ "Does nothing"
+
+ class UtilityImplementingFoo(object):
+ "Does nothing"
+
+ comps = self._makeOne()
+
+ for i in range(30):
+ comps.registerUtility(UtilityImplementingFoo(), IFoo, name=u'%s' % (i,))
+
+ orig_generation = comps.utilities._generation
+
+ orig_adapters = comps.utilities._adapters
+ self.assertEqual(len(orig_adapters), 1)
+ self.assertEqual(len(orig_adapters[0]), 1)
+ self.assertEqual(len(orig_adapters[0][IFoo]), 30)
+
+ orig_subscribers = comps.utilities._subscribers
+ self.assertEqual(len(orig_subscribers), 1)
+ self.assertEqual(len(orig_subscribers[0]), 1)
+ self.assertEqual(len(orig_subscribers[0][IFoo]), 1)
+ self.assertEqual(len(orig_subscribers[0][IFoo][u'']), 30)
+
+ # Blow a bunch of them away, creating artificial corruption
+ new_adapters = comps.utilities._adapters = type(orig_adapters)()
+ new_adapters.append({})
+ d = new_adapters[0][IFoo] = {}
+ for name in range(10):
+ name = type(u'')(str(name))
+ d[name] = orig_adapters[0][IFoo][name]
+
+ self.assertNotEqual(orig_adapters, new_adapters)
+
+ new_subscribers = comps.utilities._subscribers = type(orig_subscribers)()
+ new_subscribers.append({})
+ d = new_subscribers[0][IFoo] = {}
+ d[u''] = ()
+
+ for name in range(5, 12): # 12 - 5 = 7
+ name = type(u'')(str(name))
+ comp = orig_adapters[0][IFoo][name]
+ d[u''] += (comp,)
+
+ # We can preflight (by default) and nothing changes
+ rebuild_results_preflight = comps.rebuildUtilityRegistryFromLocalCache()
+
+ self.assertEqual(comps.utilities._generation, orig_generation)
+ self.assertEqual(rebuild_results_preflight, {
+ 'did_not_register': 10,
+ 'needed_registered': 20,
+
+ 'did_not_subscribe': 7,
+ 'needed_subscribed': 23,
+ })
+
+ # Now for real
+ rebuild_results = comps.rebuildUtilityRegistryFromLocalCache(rebuild=True)
+
+ # The generation only got incremented once
+ self.assertEqual(comps.utilities._generation, orig_generation + 1)
+ # The result was the same
+ self.assertEqual(rebuild_results_preflight, rebuild_results)
+ self.assertEqual(new_adapters, orig_adapters)
+ self.assertEqual(
+ len(new_subscribers[0][IFoo][u'']),
+ len(orig_subscribers[0][IFoo][u'']))
+
+ for orig_subscriber in orig_subscribers[0][IFoo][u'']:
+ self.assertIn(orig_subscriber, new_subscribers[0][IFoo][u''])
+
+ # Preflighting, rebuilding again produce no changes.
+ preflight_after = comps.rebuildUtilityRegistryFromLocalCache()
+ self.assertEqual(preflight_after, {
+ 'did_not_register': 30,
+ 'needed_registered': 0,
+
+ 'did_not_subscribe': 30,
+ 'needed_subscribed': 0,
+ })
+
+ rebuild_after = comps.rebuildUtilityRegistryFromLocalCache(rebuild=True)
+ self.assertEqual(rebuild_after, preflight_after)
+ self.assertEqual(comps.utilities._generation, orig_generation + 1)
+
+
+class UnhashableComponentsTests(ComponentsTests):
+
+ def _getTargetClass(self):
+ # Mimic what pyramid does to create an unhashable
+ # registry
+ class Components(super(UnhashableComponentsTests, self)._getTargetClass(), dict):
+ pass
+ return Components
+
+# Test _getUtilityProvided, _getAdapterProvided, _getAdapterRequired via their
+# callers (Component.registerUtility, Component.registerAdapter).
+
+
+class UtilityRegistrationTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.registry import UtilityRegistration
+ return UtilityRegistration
+
+ def _makeOne(self, component=None, factory=None):
+ from zope.interface.declarations import InterfaceClass
+
+ class InterfaceClassSubclass(InterfaceClass):
+ pass
+
+ ifoo = InterfaceClassSubclass('IFoo')
+ class _Registry(object):
+ def __repr__(self):
+ return '_REGISTRY'
+ registry = _Registry()
+ name = u'name'
+ doc = 'DOCSTRING'
+ klass = self._getTargetClass()
+ return (klass(registry, ifoo, name, component, doc, factory),
+ registry,
+ name,
+ )
+
+ def test_class_conforms_to_IUtilityRegistration(self):
+ from zope.interface.verify import verifyClass
+ from zope.interface.interfaces import IUtilityRegistration
+ verifyClass(IUtilityRegistration, self._getTargetClass())
+
+ def test_instance_conforms_to_IUtilityRegistration(self):
+ from zope.interface.verify import verifyObject
+ from zope.interface.interfaces import IUtilityRegistration
+ ur, _, _ = self._makeOne()
+ verifyObject(IUtilityRegistration, ur)
+
+ def test___repr__(self):
+ class _Component(object):
+ __name__ = 'TEST'
+ _component = _Component()
+ ur, _registry, _name = self._makeOne(_component)
+ self.assertEqual(repr(ur),
+ "UtilityRegistration(_REGISTRY, IFoo, %r, TEST, None, 'DOCSTRING')"
+ % (_name))
+
+ def test___repr___provided_wo_name(self):
+ class _Component(object):
+ def __repr__(self):
+ return 'TEST'
+ _component = _Component()
+ ur, _registry, _name = self._makeOne(_component)
+ ur.provided = object()
+ self.assertEqual(repr(ur),
+ "UtilityRegistration(_REGISTRY, None, %r, TEST, None, 'DOCSTRING')"
+ % (_name))
+
+ def test___repr___component_wo_name(self):
+ class _Component(object):
+ def __repr__(self):
+ return 'TEST'
+ _component = _Component()
+ ur, _registry, _name = self._makeOne(_component)
+ ur.provided = object()
+ self.assertEqual(repr(ur),
+ "UtilityRegistration(_REGISTRY, None, %r, TEST, None, 'DOCSTRING')"
+ % (_name))
+
+ def test___hash__(self):
+ _component = object()
+ ur, _registry, _name = self._makeOne(_component)
+ self.assertEqual(ur.__hash__(), id(ur))
+
+ def test___eq___identity(self):
+ _component = object()
+ ur, _registry, _name = self._makeOne(_component)
+ self.assertTrue(ur == ur)
+
+ def test___eq___hit(self):
+ _component = object()
+ ur, _registry, _name = self._makeOne(_component)
+ ur2, _, _ = self._makeOne(_component)
+ self.assertTrue(ur == ur2)
+
+ def test___eq___miss(self):
+ _component = object()
+ _component2 = object()
+ ur, _registry, _name = self._makeOne(_component)
+ ur2, _, _ = self._makeOne(_component2)
+ self.assertFalse(ur == ur2)
+
+ def test___ne___identity(self):
+ _component = object()
+ ur, _registry, _name = self._makeOne(_component)
+ self.assertFalse(ur != ur)
+
+ def test___ne___hit(self):
+ _component = object()
+ ur, _registry, _name = self._makeOne(_component)
+ ur2, _, _ = self._makeOne(_component)
+ self.assertFalse(ur != ur2)
+
+ def test___ne___miss(self):
+ _component = object()
+ _component2 = object()
+ ur, _registry, _name = self._makeOne(_component)
+ ur2, _, _ = self._makeOne(_component2)
+ self.assertTrue(ur != ur2)
+
+ def test___lt___identity(self):
+ _component = object()
+ ur, _registry, _name = self._makeOne(_component)
+ self.assertFalse(ur < ur)
+
+ def test___lt___hit(self):
+ _component = object()
+ ur, _registry, _name = self._makeOne(_component)
+ ur2, _, _ = self._makeOne(_component)
+ self.assertFalse(ur < ur2)
+
+ def test___lt___miss(self):
+ _component = object()
+ _component2 = object()
+ ur, _registry, _name = self._makeOne(_component)
+ ur2, _, _ = self._makeOne(_component2)
+ ur2.name = _name + '2'
+ self.assertTrue(ur < ur2)
+
+ def test___le___identity(self):
+ _component = object()
+ ur, _registry, _name = self._makeOne(_component)
+ self.assertTrue(ur <= ur)
+
+ def test___le___hit(self):
+ _component = object()
+ ur, _registry, _name = self._makeOne(_component)
+ ur2, _, _ = self._makeOne(_component)
+ self.assertTrue(ur <= ur2)
+
+ def test___le___miss(self):
+ _component = object()
+ _component2 = object()
+ ur, _registry, _name = self._makeOne(_component)
+ ur2, _, _ = self._makeOne(_component2)
+ ur2.name = _name + '2'
+ self.assertTrue(ur <= ur2)
+
+ def test___gt___identity(self):
+ _component = object()
+ ur, _registry, _name = self._makeOne(_component)
+ self.assertFalse(ur > ur)
+
+ def test___gt___hit(self):
+ _component = object()
+ _component2 = object()
+ ur, _registry, _name = self._makeOne(_component)
+ ur2, _, _ = self._makeOne(_component2)
+ ur2.name = _name + '2'
+ self.assertTrue(ur2 > ur)
+
+ def test___gt___miss(self):
+ _component = object()
+ ur, _registry, _name = self._makeOne(_component)
+ ur2, _, _ = self._makeOne(_component)
+ self.assertFalse(ur2 > ur)
+
+ def test___ge___identity(self):
+ _component = object()
+ ur, _registry, _name = self._makeOne(_component)
+ self.assertTrue(ur >= ur)
+
+ def test___ge___miss(self):
+ _component = object()
+ _component2 = object()
+ ur, _registry, _name = self._makeOne(_component)
+ ur2, _, _ = self._makeOne(_component2)
+ ur2.name = _name + '2'
+ self.assertFalse(ur >= ur2)
+
+ def test___ge___hit(self):
+ _component = object()
+ ur, _registry, _name = self._makeOne(_component)
+ ur2, _, _ = self._makeOne(_component)
+ ur2.name = _name + '2'
+ self.assertTrue(ur2 >= ur)
+
+
+class AdapterRegistrationTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.registry import AdapterRegistration
+ return AdapterRegistration
+
+ def _makeOne(self, component=None):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ class _Registry(object):
+ def __repr__(self):
+ return '_REGISTRY'
+ registry = _Registry()
+ name = u'name'
+ doc = 'DOCSTRING'
+ klass = self._getTargetClass()
+ return (klass(registry, (ibar,), ifoo, name, component, doc),
+ registry,
+ name,
+ )
+
+ def test_class_conforms_to_IAdapterRegistration(self):
+ from zope.interface.verify import verifyClass
+ from zope.interface.interfaces import IAdapterRegistration
+ verifyClass(IAdapterRegistration, self._getTargetClass())
+
+ def test_instance_conforms_to_IAdapterRegistration(self):
+ from zope.interface.verify import verifyObject
+ from zope.interface.interfaces import IAdapterRegistration
+ ar, _, _ = self._makeOne()
+ verifyObject(IAdapterRegistration, ar)
+
+ def test___repr__(self):
+ class _Component(object):
+ __name__ = 'TEST'
+ _component = _Component()
+ ar, _registry, _name = self._makeOne(_component)
+ self.assertEqual(repr(ar),
+ ("AdapterRegistration(_REGISTRY, [IBar], IFoo, %r, TEST, "
+ + "'DOCSTRING')") % (_name))
+
+ def test___repr___provided_wo_name(self):
+ class _Component(object):
+ def __repr__(self):
+ return 'TEST'
+ _component = _Component()
+ ar, _registry, _name = self._makeOne(_component)
+ ar.provided = object()
+ self.assertEqual(repr(ar),
+ ("AdapterRegistration(_REGISTRY, [IBar], None, %r, TEST, "
+ + "'DOCSTRING')") % (_name))
+
+ def test___repr___component_wo_name(self):
+ class _Component(object):
+ def __repr__(self):
+ return 'TEST'
+ _component = _Component()
+ ar, _registry, _name = self._makeOne(_component)
+ ar.provided = object()
+ self.assertEqual(repr(ar),
+ ("AdapterRegistration(_REGISTRY, [IBar], None, %r, TEST, "
+ + "'DOCSTRING')") % (_name))
+
+ def test___hash__(self):
+ _component = object()
+ ar, _registry, _name = self._makeOne(_component)
+ self.assertEqual(ar.__hash__(), id(ar))
+
+ def test___eq___identity(self):
+ _component = object()
+ ar, _registry, _name = self._makeOne(_component)
+ self.assertTrue(ar == ar)
+
+ def test___eq___hit(self):
+ _component = object()
+ ar, _registry, _name = self._makeOne(_component)
+ ar2, _, _ = self._makeOne(_component)
+ self.assertTrue(ar == ar2)
+
+ def test___eq___miss(self):
+ _component = object()
+ _component2 = object()
+ ar, _registry, _name = self._makeOne(_component)
+ ar2, _, _ = self._makeOne(_component2)
+ self.assertFalse(ar == ar2)
+
+ def test___ne___identity(self):
+ _component = object()
+ ar, _registry, _name = self._makeOne(_component)
+ self.assertFalse(ar != ar)
+
+ def test___ne___miss(self):
+ _component = object()
+ ar, _registry, _name = self._makeOne(_component)
+ ar2, _, _ = self._makeOne(_component)
+ self.assertFalse(ar != ar2)
+
+ def test___ne___hit_component(self):
+ _component = object()
+ _component2 = object()
+ ar, _registry, _name = self._makeOne(_component)
+ ar2, _, _ = self._makeOne(_component2)
+ self.assertTrue(ar != ar2)
+
+ def test___ne___hit_provided(self):
+ from zope.interface.declarations import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ ibaz = IFoo('IBaz')
+ _component = object()
+ ar, _registry, _name = self._makeOne(_component)
+ ar2, _, _ = self._makeOne(_component)
+ ar2.provided = ibaz
+ self.assertTrue(ar != ar2)
+
+ def test___ne___hit_required(self):
+ from zope.interface.declarations import InterfaceClass
+ class IFoo(InterfaceClass):
+ pass
+ ibaz = IFoo('IBaz')
+ _component = object()
+ _component2 = object()
+ ar, _registry, _name = self._makeOne(_component)
+ ar2, _, _ = self._makeOne(_component2)
+ ar2.required = (ibaz,)
+ self.assertTrue(ar != ar2)
+
+ def test___lt___identity(self):
+ _component = object()
+ ar, _registry, _name = self._makeOne(_component)
+ self.assertFalse(ar < ar)
+
+ def test___lt___hit(self):
+ _component = object()
+ ar, _registry, _name = self._makeOne(_component)
+ ar2, _, _ = self._makeOne(_component)
+ self.assertFalse(ar < ar2)
+
+ def test___lt___miss(self):
+ _component = object()
+ _component2 = object()
+ ar, _registry, _name = self._makeOne(_component)
+ ar2, _, _ = self._makeOne(_component2)
+ ar2.name = _name + '2'
+ self.assertTrue(ar < ar2)
+
+ def test___le___identity(self):
+ _component = object()
+ ar, _registry, _name = self._makeOne(_component)
+ self.assertTrue(ar <= ar)
+
+ def test___le___hit(self):
+ _component = object()
+ ar, _registry, _name = self._makeOne(_component)
+ ar2, _, _ = self._makeOne(_component)
+ self.assertTrue(ar <= ar2)
+
+ def test___le___miss(self):
+ _component = object()
+ _component2 = object()
+ ar, _registry, _name = self._makeOne(_component)
+ ar2, _, _ = self._makeOne(_component2)
+ ar2.name = _name + '2'
+ self.assertTrue(ar <= ar2)
+
+ def test___gt___identity(self):
+ _component = object()
+ ar, _registry, _name = self._makeOne(_component)
+ self.assertFalse(ar > ar)
+
+ def test___gt___hit(self):
+ _component = object()
+ _component2 = object()
+ ar, _registry, _name = self._makeOne(_component)
+ ar2, _, _ = self._makeOne(_component2)
+ ar2.name = _name + '2'
+ self.assertTrue(ar2 > ar)
+
+ def test___gt___miss(self):
+ _component = object()
+ ar, _registry, _name = self._makeOne(_component)
+ ar2, _, _ = self._makeOne(_component)
+ self.assertFalse(ar2 > ar)
+
+ def test___ge___identity(self):
+ _component = object()
+ ar, _registry, _name = self._makeOne(_component)
+ self.assertTrue(ar >= ar)
+
+ def test___ge___miss(self):
+ _component = object()
+ _component2 = object()
+ ar, _registry, _name = self._makeOne(_component)
+ ar2, _, _ = self._makeOne(_component2)
+ ar2.name = _name + '2'
+ self.assertFalse(ar >= ar2)
+
+ def test___ge___hit(self):
+ _component = object()
+ ar, _registry, _name = self._makeOne(_component)
+ ar2, _, _ = self._makeOne(_component)
+ ar2.name = _name + '2'
+ self.assertTrue(ar2 >= ar)
+
+
+class SubscriptionRegistrationTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.registry import SubscriptionRegistration
+ return SubscriptionRegistration
+
+ def _makeOne(self, component=None):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ ibar = IFoo('IBar')
+ class _Registry(object):
+ def __repr__(self): # pragma: no cover
+ return '_REGISTRY'
+ registry = _Registry()
+ name = u'name'
+ doc = 'DOCSTRING'
+ klass = self._getTargetClass()
+ return (klass(registry, (ibar,), ifoo, name, component, doc),
+ registry,
+ name,
+ )
+
+ def test_class_conforms_to_ISubscriptionAdapterRegistration(self):
+ from zope.interface.verify import verifyClass
+ from zope.interface.interfaces import ISubscriptionAdapterRegistration
+ verifyClass(ISubscriptionAdapterRegistration, self._getTargetClass())
+
+ def test_instance_conforms_to_ISubscriptionAdapterRegistration(self):
+ from zope.interface.verify import verifyObject
+ from zope.interface.interfaces import ISubscriptionAdapterRegistration
+ sar, _, _ = self._makeOne()
+ verifyObject(ISubscriptionAdapterRegistration, sar)
+
+
+class HandlerRegistrationTests(unittest.TestCase):
+
+ def _getTargetClass(self):
+ from zope.interface.registry import HandlerRegistration
+ return HandlerRegistration
+
+ def _makeOne(self, component=None):
+ from zope.interface.declarations import InterfaceClass
+
+ class IFoo(InterfaceClass):
+ pass
+ ifoo = IFoo('IFoo')
+ class _Registry(object):
+ def __repr__(self):
+ return '_REGISTRY'
+ registry = _Registry()
+ name = u'name'
+ doc = 'DOCSTRING'
+ klass = self._getTargetClass()
+ return (klass(registry, (ifoo,), name, component, doc),
+ registry,
+ name,
+ )
+
+ def test_class_conforms_to_IHandlerRegistration(self):
+ from zope.interface.verify import verifyClass
+ from zope.interface.interfaces import IHandlerRegistration
+ verifyClass(IHandlerRegistration, self._getTargetClass())
+
+ def test_instance_conforms_to_IHandlerRegistration(self):
+ from zope.interface.verify import verifyObject
+ from zope.interface.interfaces import IHandlerRegistration
+ hr, _, _ = self._makeOne()
+ verifyObject(IHandlerRegistration, hr)
+
+ def test_properties(self):
+ def _factory(context):
+ raise NotImplementedError()
+ hr, _, _ = self._makeOne(_factory)
+ self.assertTrue(hr.handler is _factory)
+ self.assertTrue(hr.factory is hr.handler)
+ self.assertTrue(hr.provided is None)
+
+ def test___repr___factory_w_name(self):
+ class _Factory(object):
+ __name__ = 'TEST'
+ hr, _registry, _name = self._makeOne(_Factory())
+ self.assertEqual(repr(hr),
+ ("HandlerRegistration(_REGISTRY, [IFoo], %r, TEST, "
+ + "'DOCSTRING')") % (_name))
+
+ def test___repr___factory_wo_name(self):
+ class _Factory(object):
+ def __repr__(self):
+ return 'TEST'
+ hr, _registry, _name = self._makeOne(_Factory())
+ self.assertEqual(repr(hr),
+ ("HandlerRegistration(_REGISTRY, [IFoo], %r, TEST, "
+ + "'DOCSTRING')") % (_name))
+
+class PersistentAdapterRegistry(VerifyingAdapterRegistry):
+
+ def __getstate__(self):
+ state = self.__dict__.copy()
+ for k in list(state):
+ if k in self._delegated or k.startswith('_v'):
+ state.pop(k)
+ state.pop('ro', None)
+ return state
+
+ def __setstate__(self, state):
+ bases = state.pop('__bases__', ())
+ self.__dict__.update(state)
+ self._createLookup()
+ self.__bases__ = bases
+ self._v_lookup.changed(self)
+
+class PersistentComponents(Components):
+ # Mimic zope.component.persistentregistry.PersistentComponents:
+ # we should be picklalable, but not persistent.Persistent ourself.
+
+ def _init_registries(self):
+ self.adapters = PersistentAdapterRegistry()
+ self.utilities = PersistentAdapterRegistry()
+
+class PersistentDictComponents(PersistentComponents, dict):
+ # Like Pyramid's Registry, we subclass Components and dict
+ pass
+
+
+class PersistentComponentsDict(dict, PersistentComponents):
+ # Like the above, but inheritance is flipped
+ def __init__(self, name):
+ dict.__init__(self)
+ PersistentComponents.__init__(self, name)
+
+class TestPersistentComponents(unittest.TestCase):
+
+ def _makeOne(self):
+ return PersistentComponents('test')
+
+ def _check_equality_after_pickle(self, made):
+ pass
+
+ def test_pickles_empty(self):
+ import pickle
+ comp = self._makeOne()
+ pickle.dumps(comp)
+ comp2 = pickle.loads(pickle.dumps(comp))
+
+ self.assertEqual(comp2.__name__, 'test')
+
+ def test_pickles_with_utility_registration(self):
+ import pickle
+ comp = self._makeOne()
+ utility = object()
+ comp.registerUtility(
+ utility,
+ Interface)
+
+ self.assertIs(utility,
+ comp.getUtility(Interface))
+
+ comp2 = pickle.loads(pickle.dumps(comp))
+ self.assertEqual(comp2.__name__, 'test')
+
+ # The utility is still registered
+ self.assertIsNotNone(comp2.getUtility(Interface))
+
+ # We can register another one
+ comp2.registerUtility(
+ utility,
+ Interface)
+ self.assertIs(utility,
+ comp2.getUtility(Interface))
+
+ self._check_equality_after_pickle(comp2)
+
+
+class TestPersistentDictComponents(TestPersistentComponents):
+
+ def _getTargetClass(self):
+ return PersistentDictComponents
+
+ def _makeOne(self):
+ comp = self._getTargetClass()(name='test')
+ comp['key'] = 42
+ return comp
+
+ def _check_equality_after_pickle(self, made):
+ self.assertIn('key', made)
+ self.assertEqual(made['key'], 42)
+
+class TestPersistentComponentsDict(TestPersistentDictComponents):
+
+ def _getTargetClass(self):
+ return PersistentComponentsDict
+
+class _Monkey(object):
+ # context-manager for replacing module names in the scope of a test.
+ def __init__(self, module, **kw):
+ self.module = module
+ self.to_restore = dict([(key, getattr(module, key)) for key in kw])
+ for key, value in kw.items():
+ setattr(module, key, value)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ for key, value in self.to_restore.items():
+ setattr(self.module, key, value)
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/test_ro.py b/contrib/python/zope.interface/py2/zope/interface/tests/test_ro.py
new file mode 100644
index 0000000000..00cd49e974
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/test_ro.py
@@ -0,0 +1,235 @@
+##############################################################################
+#
+# Copyright (c) 2014 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Resolution ordering utility tests"""
+import unittest
+
+# pylint:disable=blacklisted-name,protected-access,attribute-defined-outside-init
+
+class Test__mergeOrderings(unittest.TestCase):
+
+ def _callFUT(self, orderings):
+ from zope.interface.ro import _legacy_mergeOrderings
+ return _legacy_mergeOrderings(orderings)
+
+ def test_empty(self):
+ self.assertEqual(self._callFUT([]), [])
+
+ def test_single(self):
+ self.assertEqual(self._callFUT(['a', 'b', 'c']), ['a', 'b', 'c'])
+
+ def test_w_duplicates(self):
+ self.assertEqual(self._callFUT([['a'], ['b', 'a']]), ['b', 'a'])
+
+ def test_suffix_across_multiple_duplicates(self):
+ O1 = ['x', 'y', 'z']
+ O2 = ['q', 'z']
+ O3 = [1, 3, 5]
+ O4 = ['z']
+ self.assertEqual(self._callFUT([O1, O2, O3, O4]),
+ ['x', 'y', 'q', 1, 3, 5, 'z'])
+
+
+class Test__flatten(unittest.TestCase):
+
+ def _callFUT(self, ob):
+ from zope.interface.ro import _legacy_flatten
+ return _legacy_flatten(ob)
+
+ def test_w_empty_bases(self):
+ class Foo(object):
+ pass
+ foo = Foo()
+ foo.__bases__ = ()
+ self.assertEqual(self._callFUT(foo), [foo])
+
+ def test_w_single_base(self):
+ class Foo(object):
+ pass
+ self.assertEqual(self._callFUT(Foo), [Foo, object])
+
+ def test_w_bases(self):
+ class Foo(object):
+ pass
+ class Bar(Foo):
+ pass
+ self.assertEqual(self._callFUT(Bar), [Bar, Foo, object])
+
+ def test_w_diamond(self):
+ class Foo(object):
+ pass
+ class Bar(Foo):
+ pass
+ class Baz(Foo):
+ pass
+ class Qux(Bar, Baz):
+ pass
+ self.assertEqual(self._callFUT(Qux),
+ [Qux, Bar, Foo, object, Baz, Foo, object])
+
+
+class Test_ro(unittest.TestCase):
+ maxDiff = None
+ def _callFUT(self, ob, **kwargs):
+ from zope.interface.ro import _legacy_ro
+ return _legacy_ro(ob, **kwargs)
+
+ def test_w_empty_bases(self):
+ class Foo(object):
+ pass
+ foo = Foo()
+ foo.__bases__ = ()
+ self.assertEqual(self._callFUT(foo), [foo])
+
+ def test_w_single_base(self):
+ class Foo(object):
+ pass
+ self.assertEqual(self._callFUT(Foo), [Foo, object])
+
+ def test_w_bases(self):
+ class Foo(object):
+ pass
+ class Bar(Foo):
+ pass
+ self.assertEqual(self._callFUT(Bar), [Bar, Foo, object])
+
+ def test_w_diamond(self):
+ class Foo(object):
+ pass
+ class Bar(Foo):
+ pass
+ class Baz(Foo):
+ pass
+ class Qux(Bar, Baz):
+ pass
+ self.assertEqual(self._callFUT(Qux),
+ [Qux, Bar, Baz, Foo, object])
+
+ def _make_IOErr(self):
+ # This can't be done in the standard C3 ordering.
+ class Foo(object):
+ def __init__(self, name, *bases):
+ self.__name__ = name
+ self.__bases__ = bases
+ def __repr__(self): # pragma: no cover
+ return self.__name__
+
+ # Mimic what classImplements(IOError, IIOError)
+ # does.
+ IEx = Foo('IEx')
+ IStdErr = Foo('IStdErr', IEx)
+ IEnvErr = Foo('IEnvErr', IStdErr)
+ IIOErr = Foo('IIOErr', IEnvErr)
+ IOSErr = Foo('IOSErr', IEnvErr)
+
+ IOErr = Foo('IOErr', IEnvErr, IIOErr, IOSErr)
+ return IOErr, [IOErr, IIOErr, IOSErr, IEnvErr, IStdErr, IEx]
+
+ def test_non_orderable(self):
+ IOErr, bases = self._make_IOErr()
+
+ self.assertEqual(self._callFUT(IOErr), bases)
+
+ def test_mixed_inheritance_and_implementation(self):
+ # https://github.com/zopefoundation/zope.interface/issues/8
+ # This test should fail, but doesn't, as described in that issue.
+ # pylint:disable=inherit-non-class
+ from zope.interface import implementer
+ from zope.interface import Interface
+ from zope.interface import providedBy
+ from zope.interface import implementedBy
+
+ class IFoo(Interface):
+ pass
+
+ @implementer(IFoo)
+ class ImplementsFoo(object):
+ pass
+
+ class ExtendsFoo(ImplementsFoo):
+ pass
+
+ class ImplementsNothing(object):
+ pass
+
+ class ExtendsFooImplementsNothing(ExtendsFoo, ImplementsNothing):
+ pass
+
+ self.assertEqual(
+ self._callFUT(providedBy(ExtendsFooImplementsNothing())),
+ [implementedBy(ExtendsFooImplementsNothing),
+ implementedBy(ExtendsFoo),
+ implementedBy(ImplementsFoo),
+ IFoo,
+ Interface,
+ implementedBy(ImplementsNothing),
+ implementedBy(object)])
+
+
+class C3Setting(object):
+
+ def __init__(self, setting, value):
+ self._setting = setting
+ self._value = value
+
+ def __enter__(self):
+ from zope.interface import ro
+ setattr(ro.C3, self._setting.__name__, self._value)
+
+ def __exit__(self, t, v, tb):
+ from zope.interface import ro
+ setattr(ro.C3, self._setting.__name__, self._setting)
+
+class TestC3(unittest.TestCase):
+ def _makeOne(self, C, strict=False, base_mros=None):
+ from zope.interface.ro import C3
+ return C3.resolver(C, strict, base_mros)
+
+ def test_base_mros_given(self):
+ c3 = self._makeOne(type(self), base_mros={unittest.TestCase: unittest.TestCase.__mro__})
+ memo = c3.memo
+ self.assertIn(unittest.TestCase, memo)
+ # We used the StaticMRO class
+ self.assertIsNone(memo[unittest.TestCase].had_inconsistency)
+
+ def test_one_base_optimization(self):
+ c3 = self._makeOne(type(self))
+ # Even though we didn't call .mro() yet, the MRO has been
+ # computed.
+ self.assertIsNotNone(c3._C3__mro) # pylint:disable=no-member
+ c3._merge = None
+ self.assertEqual(c3.mro(), list(type(self).__mro__))
+
+
+class Test_ROComparison(unittest.TestCase):
+
+ class MockC3(object):
+ direct_inconsistency = False
+ bases_had_inconsistency = False
+
+ def _makeOne(self, c3=None, c3_ro=(), legacy_ro=()):
+ from zope.interface.ro import _ROComparison
+ return _ROComparison(c3 or self.MockC3(), c3_ro, legacy_ro)
+
+ def test_inconsistent_label(self):
+ comp = self._makeOne()
+ self.assertEqual('no', comp._inconsistent_label)
+
+ comp.c3.direct_inconsistency = True
+ self.assertEqual("direct", comp._inconsistent_label)
+
+ comp.c3.bases_had_inconsistency = True
+ self.assertEqual("direct+bases", comp._inconsistent_label)
+
+ comp.c3.direct_inconsistency = False
+ self.assertEqual('bases', comp._inconsistent_label)
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/test_sorting.py b/contrib/python/zope.interface/py2/zope/interface/tests/test_sorting.py
new file mode 100644
index 0000000000..e4dd887d40
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/test_sorting.py
@@ -0,0 +1,64 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Test interface sorting
+"""
+
+import unittest
+
+from zope.interface import Interface
+
+class I1(Interface): pass
+class I2(I1): pass
+class I3(I1): pass
+class I4(Interface): pass
+class I5(I4): pass
+class I6(I2): pass
+
+
+class Test(unittest.TestCase):
+
+ def test(self):
+ l = [I1, I3, I5, I6, I4, I2]
+ l.sort()
+ self.assertEqual(l, [I1, I2, I3, I4, I5, I6])
+
+ def test_w_None(self):
+ l = [I1, None, I3, I5, I6, I4, I2]
+ l.sort()
+ self.assertEqual(l, [I1, I2, I3, I4, I5, I6, None])
+
+ def test_w_equal_names(self):
+ # interfaces with equal names but different modules should sort by
+ # module name
+ from .m1 import I1 as m1_I1
+ l = [I1, m1_I1]
+ l.sort()
+ self.assertEqual(l, [m1_I1, I1])
+
+ def test_I1_I2(self):
+ self.assertLess(I1.__name__, I2.__name__)
+ self.assertEqual(I1.__module__, I2.__module__)
+ self.assertEqual(I1.__module__, __name__)
+ self.assertLess(I1, I2)
+
+ def _makeI1(self):
+ class I1(Interface):
+ pass
+ return I1
+
+ def test_nested(self):
+ nested_I1 = self._makeI1()
+ self.assertEqual(I1, nested_I1)
+ self.assertEqual(nested_I1, I1)
+ self.assertEqual(hash(I1), hash(nested_I1))
diff --git a/contrib/python/zope.interface/py2/zope/interface/tests/test_verify.py b/contrib/python/zope.interface/py2/zope/interface/tests/test_verify.py
new file mode 100644
index 0000000000..bb7bb4a95e
--- /dev/null
+++ b/contrib/python/zope.interface/py2/zope/interface/tests/test_verify.py
@@ -0,0 +1,656 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" zope.interface.verify unit tests
+"""
+import unittest
+
+# pylint:disable=inherit-non-class,no-method-argument,no-self-argument
+
+class Test_verifyClass(unittest.TestCase):
+
+ verifier = None
+
+ def setUp(self):
+ self.verifier = self._get_FUT()
+
+ @classmethod
+ def _get_FUT(cls):
+ from zope.interface.verify import verifyClass
+ return verifyClass
+
+ _adjust_object_before_verify = lambda self, x: x
+
+ def _callFUT(self, iface, klass, **kwargs):
+ return self.verifier(iface,
+ self._adjust_object_before_verify(klass),
+ **kwargs)
+
+ def test_class_doesnt_implement(self):
+ from zope.interface import Interface
+ from zope.interface.exceptions import DoesNotImplement
+
+ class ICurrent(Interface):
+ pass
+
+ class Current(object):
+ pass
+
+ self.assertRaises(DoesNotImplement, self._callFUT, ICurrent, Current)
+
+ def test_class_doesnt_implement_but_classImplements_later(self):
+ from zope.interface import Interface
+ from zope.interface import classImplements
+
+ class ICurrent(Interface):
+ pass
+
+ class Current(object):
+ pass
+
+ classImplements(Current, ICurrent)
+
+ self._callFUT(ICurrent, Current)
+
+ def test_class_doesnt_have_required_method_simple(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface.exceptions import BrokenImplementation
+
+ class ICurrent(Interface):
+ def method():
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+ pass
+
+ self.assertRaises(BrokenImplementation,
+ self._callFUT, ICurrent, Current)
+
+ def test_class_has_required_method_simple(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class ICurrent(Interface):
+ def method():
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self):
+ raise NotImplementedError()
+
+ self._callFUT(ICurrent, Current)
+
+ def test_class_doesnt_have_required_method_derived(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface.exceptions import BrokenImplementation
+
+ class IBase(Interface):
+ def method():
+ """docstring"""
+
+ class IDerived(IBase):
+ pass
+
+ @implementer(IDerived)
+ class Current(object):
+ pass
+
+ self.assertRaises(BrokenImplementation,
+ self._callFUT, IDerived, Current)
+
+ def test_class_has_required_method_derived(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class IBase(Interface):
+ def method():
+ """docstring"""
+
+ class IDerived(IBase):
+ pass
+
+ @implementer(IDerived)
+ class Current(object):
+
+ def method(self):
+ raise NotImplementedError()
+
+ self._callFUT(IDerived, Current)
+
+ def test_method_takes_wrong_arg_names_but_OK(self):
+ # We no longer require names to match.
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class ICurrent(Interface):
+
+ def method(a):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self, b):
+ raise NotImplementedError()
+
+ self._callFUT(ICurrent, Current)
+
+ def test_method_takes_not_enough_args(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface.exceptions import BrokenMethodImplementation
+
+ class ICurrent(Interface):
+
+ def method(a):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self):
+ raise NotImplementedError()
+
+ self.assertRaises(BrokenMethodImplementation,
+ self._callFUT, ICurrent, Current)
+
+ def test_method_doesnt_take_required_starargs(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface.exceptions import BrokenMethodImplementation
+
+ class ICurrent(Interface):
+
+ def method(*args):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self):
+ raise NotImplementedError()
+
+ self.assertRaises(BrokenMethodImplementation,
+ self._callFUT, ICurrent, Current)
+
+ def test_method_doesnt_take_required_only_kwargs(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface.exceptions import BrokenMethodImplementation
+
+ class ICurrent(Interface):
+
+ def method(**kw):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self):
+ raise NotImplementedError()
+
+ self.assertRaises(BrokenMethodImplementation,
+ self._callFUT, ICurrent, Current)
+
+ def test_method_takes_extra_arg(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface.exceptions import BrokenMethodImplementation
+
+ class ICurrent(Interface):
+
+ def method(a):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self, a, b):
+ raise NotImplementedError()
+
+ self.assertRaises(BrokenMethodImplementation,
+ self._callFUT, ICurrent, Current)
+
+ def test_method_takes_extra_arg_with_default(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class ICurrent(Interface):
+
+ def method(a):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self, a, b=None):
+ raise NotImplementedError()
+
+ self._callFUT(ICurrent, Current)
+
+ def test_method_takes_only_positional_args(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class ICurrent(Interface):
+
+ def method(a):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self, *args):
+ raise NotImplementedError()
+
+ self._callFUT(ICurrent, Current)
+
+ def test_method_takes_only_kwargs(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface.exceptions import BrokenMethodImplementation
+
+ class ICurrent(Interface):
+
+ def method(a):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self, **kw):
+ raise NotImplementedError()
+
+ self.assertRaises(BrokenMethodImplementation,
+ self._callFUT, ICurrent, Current)
+
+ def test_method_takes_extra_starargs(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class ICurrent(Interface):
+
+ def method(a):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self, a, *args):
+ raise NotImplementedError()
+
+ self._callFUT(ICurrent, Current)
+
+ def test_method_takes_extra_starargs_and_kwargs(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class ICurrent(Interface):
+
+ def method(a):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self, a, *args, **kw):
+ raise NotImplementedError()
+
+ self._callFUT(ICurrent, Current)
+
+ def test_method_doesnt_take_required_positional_and_starargs(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface.exceptions import BrokenMethodImplementation
+
+ class ICurrent(Interface):
+
+ def method(a, *args):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self, a):
+ raise NotImplementedError()
+
+ self.assertRaises(BrokenMethodImplementation,
+ self._callFUT, ICurrent, Current)
+
+ def test_method_takes_required_positional_and_starargs(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class ICurrent(Interface):
+
+ def method(a, *args):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self, a, *args):
+ raise NotImplementedError()
+
+ self._callFUT(ICurrent, Current)
+
+ def test_method_takes_only_starargs(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class ICurrent(Interface):
+
+ def method(a, *args):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self, *args):
+ raise NotImplementedError()
+
+ self._callFUT(ICurrent, Current)
+
+ def test_method_takes_required_kwargs(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class ICurrent(Interface):
+
+ def method(**kwargs):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self, **kw):
+ raise NotImplementedError()
+
+ self._callFUT(ICurrent, Current)
+
+ def test_method_takes_positional_plus_required_starargs(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface.exceptions import BrokenMethodImplementation
+
+ class ICurrent(Interface):
+
+ def method(*args):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self, a, *args):
+ raise NotImplementedError()
+
+ self.assertRaises(BrokenMethodImplementation,
+ self._callFUT, ICurrent, Current)
+
+
+ def test_method_doesnt_take_required_kwargs(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface.exceptions import BrokenMethodImplementation
+
+ class ICurrent(Interface):
+
+ def method(**kwargs):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ def method(self, a):
+ raise NotImplementedError()
+
+ self.assertRaises(BrokenMethodImplementation,
+ self._callFUT, ICurrent, Current)
+
+
+ def test_class_has_method_for_iface_attr(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class ICurrent(Interface):
+ attr = Attribute("The foo Attribute")
+
+ @implementer(ICurrent)
+ class Current:
+
+ def attr(self):
+ raise NotImplementedError()
+
+ self._callFUT(ICurrent, Current)
+
+ def test_class_has_nonmethod_for_method(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface.exceptions import BrokenMethodImplementation
+
+ class ICurrent(Interface):
+ def method():
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current:
+ method = 1
+
+ self.assertRaises(BrokenMethodImplementation,
+ self._callFUT, ICurrent, Current)
+
+ def test_class_has_attribute_for_attribute(self):
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class ICurrent(Interface):
+ attr = Attribute("The foo Attribute")
+
+ @implementer(ICurrent)
+ class Current:
+
+ attr = 1
+
+ self._callFUT(ICurrent, Current)
+
+ def test_class_misses_attribute_for_attribute(self):
+ # This check *passes* for verifyClass
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class ICurrent(Interface):
+ attr = Attribute("The foo Attribute")
+
+ @implementer(ICurrent)
+ class Current:
+ pass
+
+ self._callFUT(ICurrent, Current)
+
+ def test_w_callable_non_func_method(self):
+ from zope.interface.interface import Method
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ class QuasiMethod(Method):
+ def __call__(self, *args, **kw):
+ raise NotImplementedError()
+
+ class QuasiCallable(object):
+ def __call__(self, *args, **kw):
+ raise NotImplementedError()
+
+ class ICurrent(Interface):
+ attr = QuasiMethod('This is callable')
+
+ @implementer(ICurrent)
+ class Current:
+ attr = QuasiCallable()
+
+ self._callFUT(ICurrent, Current)
+
+
+ def test_w_decorated_method(self):
+ from zope.interface import Interface
+ from zope.interface import implementer
+
+ def decorator(func):
+ # this is, in fact, zope.proxy.non_overridable
+ return property(lambda self: func.__get__(self))
+
+ class ICurrent(Interface):
+
+ def method(a):
+ """docstring"""
+
+ @implementer(ICurrent)
+ class Current(object):
+
+ @decorator
+ def method(self, a):
+ raise NotImplementedError()
+
+ self._callFUT(ICurrent, Current)
+
+ def test_dict_IFullMapping(self):
+ # A dict should be an IFullMapping, but this exposes two
+ # issues. First, on CPython, methods of builtin types are
+ # "method_descriptor" objects, and are harder to introspect.
+ # Second, on PyPy, the signatures can be just plain wrong,
+ # specifying as required arguments that are actually optional.
+ # See https://github.com/zopefoundation/zope.interface/issues/118
+ from zope.interface.common.mapping import IFullMapping
+ self._callFUT(IFullMapping, dict, tentative=True)
+
+ def test_list_ISequence(self):
+ # As for test_dict_IFullMapping
+ from zope.interface.common.sequence import ISequence
+ self._callFUT(ISequence, list, tentative=True)
+
+ def test_tuple_IReadSequence(self):
+ # As for test_dict_IFullMapping
+ from zope.interface.common.sequence import IReadSequence
+ self._callFUT(IReadSequence, tuple, tentative=True)
+
+
+ def test_multiple_invalid(self):
+ from zope.interface.exceptions import MultipleInvalid
+ from zope.interface.exceptions import DoesNotImplement
+ from zope.interface.exceptions import BrokenImplementation
+ from zope.interface import Interface
+ from zope.interface import classImplements
+
+ class ISeveralMethods(Interface):
+ def meth1(arg1):
+ "Method 1"
+ def meth2(arg1):
+ "Method 2"
+
+ class SeveralMethods(object):
+ pass
+
+ with self.assertRaises(MultipleInvalid) as exc:
+ self._callFUT(ISeveralMethods, SeveralMethods)
+
+ ex = exc.exception
+ self.assertEqual(3, len(ex.exceptions))
+ self.assertIsInstance(ex.exceptions[0], DoesNotImplement)
+ self.assertIsInstance(ex.exceptions[1], BrokenImplementation)
+ self.assertIsInstance(ex.exceptions[2], BrokenImplementation)
+
+ # If everything else is correct, only the single error is raised without
+ # the wrapper.
+ classImplements(SeveralMethods, ISeveralMethods)
+ SeveralMethods.meth1 = lambda self, arg1: "Hi"
+
+ with self.assertRaises(BrokenImplementation):
+ self._callFUT(ISeveralMethods, SeveralMethods)
+
+class Test_verifyObject(Test_verifyClass):
+
+ @classmethod
+ def _get_FUT(cls):
+ from zope.interface.verify import verifyObject
+ return verifyObject
+
+ def _adjust_object_before_verify(self, target):
+ if isinstance(target, (type, type(OldSkool))):
+ target = target()
+ return target
+
+ def test_class_misses_attribute_for_attribute(self):
+ # This check *fails* for verifyObject
+ from zope.interface import Attribute
+ from zope.interface import Interface
+ from zope.interface import implementer
+ from zope.interface.exceptions import BrokenImplementation
+
+ class ICurrent(Interface):
+ attr = Attribute("The foo Attribute")
+
+ @implementer(ICurrent)
+ class Current:
+ pass
+
+ self.assertRaises(BrokenImplementation,
+ self._callFUT, ICurrent, Current)
+
+ def test_module_hit(self):
+ from .idummy import IDummyModule
+ from . import dummy
+
+ self._callFUT(IDummyModule, dummy)
+
+ def test_module_miss(self):
+ from zope.interface import Interface
+ from . import dummy
+ from zope.interface.exceptions import DoesNotImplement
+
+ # same name, different object
+ class IDummyModule(Interface):
+ pass
+
+ self.assertRaises(DoesNotImplement,
+ self._callFUT, IDummyModule, dummy)
+
+ def test_staticmethod_hit_on_class(self):
+ from zope.interface import Interface
+ from zope.interface import provider
+ from zope.interface.verify import verifyObject
+
+ class IFoo(Interface):
+
+ def bar(a, b):
+ "The bar method"
+
+ @provider(IFoo)
+ class Foo(object):
+
+ @staticmethod
+ def bar(a, b):
+ raise AssertionError("We're never actually called")
+
+ # Don't use self._callFUT, we don't want to instantiate the
+ # class.
+ verifyObject(IFoo, Foo)
+
+class OldSkool:
+ pass