summaryrefslogtreecommitdiff
path: root/src/zope/interface/tests
diff options
context:
space:
mode:
authorJason Madden <jamadden@gmail.com>2020-04-06 07:57:12 -0500
committerJason Madden <jamadden@gmail.com>2020-04-07 07:32:06 -0500
commit46781f87ccbc02ae3d884e2dbe57b799c3804077 (patch)
treee6b9a6fc7f6904dc560767507d3c4be9811777c6 /src/zope/interface/tests
parenta404e5fed4766625b564de558942dd4efd979e89 (diff)
downloadzope-interface-46781f87ccbc02ae3d884e2dbe57b799c3804077.tar.gz
Make @implementer and classImplements not re-declare redundant interfaces.
classImplementsOnly and @implementer_only can still be used to do that.
Diffstat (limited to 'src/zope/interface/tests')
-rw-r--r--src/zope/interface/tests/test_declarations.py135
1 files changed, 83 insertions, 52 deletions
diff --git a/src/zope/interface/tests/test_declarations.py b/src/zope/interface/tests/test_declarations.py
index 83815d7..33d065d 100644
--- a/src/zope/interface/tests/test_declarations.py
+++ b/src/zope/interface/tests/test_declarations.py
@@ -825,25 +825,73 @@ class Test_classImplementsOnly(unittest.TestCase):
class Test_classImplements(unittest.TestCase):
- def _callFUT(self, *args, **kw):
+ def _callFUT(self, cls, iface):
from zope.interface.declarations import classImplements
- return classImplements(*args, **kw)
+ result = classImplements(cls, iface) # pylint:disable=assignment-from-no-return
+ self.assertIsNone(result)
+ return cls
- def test_no_existing(self):
+ def __check_implementer(self, Foo):
from zope.interface.declarations import ClassProvides
from zope.interface.interface import InterfaceClass
- class Foo(object):
- pass
IFoo = InterfaceClass('IFoo')
- self._callFUT(Foo, IFoo)
- spec = Foo.__implemented__ # pylint:disable=no-member
+
+ returned = self._callFUT(Foo, IFoo)
+
+ self.assertIs(returned, Foo)
+ spec = Foo.__implemented__
+
self.assertEqual(spec.__name__,
'zope.interface.tests.test_declarations.Foo')
self.assertIs(spec.inherit, Foo)
- self.assertIs(Foo.__implemented__, spec) # pylint:disable=no-member
- 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
+ self.assertIs(Foo.__implemented__, spec)
+ 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)
+
+ 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 _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
@@ -857,9 +905,10 @@ class Test_classImplements(unittest.TestCase):
impl.inherit = Foo
self._callFUT(Foo, IBar)
# Same spec, now different values
- self.assertTrue(Foo.__implemented__ is impl)
+ self.assertIs(Foo.__implemented__, impl)
self.assertEqual(impl.inherit, Foo)
- self.assertEqual(impl.declared, (IFoo, IBar,))
+ self.assertEqual(impl.declared,
+ self._order_for_two(IFoo, IBar))
def test_w_existing_Implements_w_bases(self):
from zope.interface.declarations import Implements
@@ -886,8 +935,22 @@ class Test_classImplements(unittest.TestCase):
# 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, (IExtendsRoot, ISecondRoot,))
- self.assertEqual(impl_extends_root.__bases__, (IExtendsRoot, ISecondRoot, impl_root))
+ 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):
@@ -909,7 +972,7 @@ class Test__implements_advice(unittest.TestCase):
self.assertEqual(list(Foo.__implemented__), [IFoo]) # pylint:disable=no-member
-class Test_implementer(unittest.TestCase):
+class Test_implementer(Test_classImplements):
def _getTargetClass(self):
from zope.interface.declarations import implementer
@@ -918,42 +981,9 @@ class Test_implementer(unittest.TestCase):
def _makeOne(self, *args, **kw):
return self._getTargetClass()(*args, **kw)
- def test_oldstyle_class(self):
- # TODO Py3 story
- from zope.interface.declarations import ClassProvides
- from zope.interface.interface import InterfaceClass
- IFoo = InterfaceClass('IFoo')
- class Foo:
- pass
- decorator = self._makeOne(IFoo)
- returned = decorator(Foo)
- self.assertTrue(returned is Foo)
- spec = Foo.__implemented__ # pylint:disable=no-member
- self.assertEqual(spec.__name__,
- 'zope.interface.tests.test_declarations.Foo')
- self.assertIs(spec.inherit, Foo)
- self.assertIs(Foo.__implemented__, spec) # pylint:disable=no-member
- 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_newstyle_class(self):
- from zope.interface.declarations import ClassProvides
- from zope.interface.interface import InterfaceClass
- IFoo = InterfaceClass('IFoo')
- class Foo(object):
- pass
- decorator = self._makeOne(IFoo)
- returned = decorator(Foo)
- self.assertTrue(returned is Foo)
- spec = Foo.__implemented__ # pylint:disable=no-member
- self.assertEqual(spec.__name__,
- 'zope.interface.tests.test_declarations.Foo')
- self.assertIs(spec.inherit, Foo)
- self.assertIs(Foo.__implemented__, spec) # pylint:disable=no-member
- 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 _callFUT(self, cls, *ifaces):
+ decorator = self._makeOne(*ifaces)
+ return decorator(cls)
def test_nonclass_cannot_assign_attr(self):
from zope.interface.interface import InterfaceClass
@@ -976,6 +1006,7 @@ class Test_implementer(unittest.TestCase):
self.assertIs(foo.__implemented__, spec) # pylint:disable=no-member
+
class Test_implementer_only(unittest.TestCase):
def _getTargetClass(self):