diff options
| author | Jason Madden <jamadden@gmail.com> | 2020-04-06 07:57:12 -0500 |
|---|---|---|
| committer | Jason Madden <jamadden@gmail.com> | 2020-04-07 07:32:06 -0500 |
| commit | 46781f87ccbc02ae3d884e2dbe57b799c3804077 (patch) | |
| tree | e6b9a6fc7f6904dc560767507d3c4be9811777c6 /src/zope/interface/tests | |
| parent | a404e5fed4766625b564de558942dd4efd979e89 (diff) | |
| download | zope-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.py | 135 |
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): |
