test_odd_declarations.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. ##############################################################################
  2. #
  3. # Copyright (c) 2003 Zope Foundation and Contributors.
  4. # All Rights Reserved.
  5. #
  6. # This software is subject to the provisions of the Zope Public License,
  7. # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
  8. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
  9. # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  10. # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
  11. # FOR A PARTICULAR PURPOSE.
  12. #
  13. ##############################################################################
  14. """Test interface declarations against ExtensionClass-like classes.
  15. These tests are to make sure we do something sane in the presence of
  16. classic ExtensionClass classes and instances.
  17. """
  18. import unittest
  19. from zope.interface import Interface
  20. from zope.interface import classImplements
  21. from zope.interface import classImplementsOnly
  22. from zope.interface import directlyProvidedBy
  23. from zope.interface import directlyProvides
  24. from zope.interface import implementedBy
  25. from zope.interface import implementer
  26. from zope.interface import providedBy
  27. from . import odd
  28. class I1(Interface):
  29. pass
  30. class I2(Interface):
  31. pass
  32. class I3(Interface):
  33. pass
  34. class I31(I3):
  35. pass
  36. class I4(Interface):
  37. pass
  38. class I5(Interface):
  39. pass
  40. class Odd:
  41. pass
  42. Odd = odd.MetaClass('Odd', Odd.__bases__, {})
  43. class B(Odd):
  44. __implemented__ = I2
  45. # TODO: We are going to need more magic to make classProvides work with odd
  46. # classes. This will work in the next iteration. For now, we'll use
  47. # a different mechanism.
  48. # from zope.interface import classProvides
  49. class A(Odd):
  50. pass
  51. classImplements(A, I1)
  52. class C(A, B):
  53. pass
  54. classImplements(C, I31)
  55. class Test(unittest.TestCase):
  56. def test_ObjectSpecification(self):
  57. c = C()
  58. directlyProvides(c, I4)
  59. self.assertEqual([i.getName() for i in providedBy(c)],
  60. ['I4', 'I31', 'I1', 'I2']
  61. )
  62. self.assertEqual([i.getName() for i in providedBy(c).flattened()],
  63. ['I4', 'I31', 'I3', 'I1', 'I2', 'Interface']
  64. )
  65. self.assertIn(I1, providedBy(c))
  66. self.assertNotIn(I3, providedBy(c))
  67. self.assertTrue(providedBy(c).extends(I3))
  68. self.assertTrue(providedBy(c).extends(I31))
  69. self.assertFalse(providedBy(c).extends(I5))
  70. class COnly(A, B):
  71. pass
  72. classImplementsOnly(COnly, I31)
  73. class D(COnly):
  74. pass
  75. classImplements(D, I5)
  76. classImplements(D, I5)
  77. c = D()
  78. directlyProvides(c, I4)
  79. self.assertEqual([i.getName() for i in providedBy(c)],
  80. ['I4', 'I5', 'I31'])
  81. self.assertEqual([i.getName() for i in providedBy(c).flattened()],
  82. ['I4', 'I5', 'I31', 'I3', 'Interface'])
  83. self.assertNotIn(I1, providedBy(c))
  84. self.assertNotIn(I3, providedBy(c))
  85. self.assertTrue(providedBy(c).extends(I3))
  86. self.assertFalse(providedBy(c).extends(I1))
  87. self.assertTrue(providedBy(c).extends(I31))
  88. self.assertTrue(providedBy(c).extends(I5))
  89. class COnly(A, B):
  90. __implemented__ = I31
  91. class D(COnly):
  92. pass
  93. classImplements(D, I5)
  94. classImplements(D, I5)
  95. c = D()
  96. directlyProvides(c, I4)
  97. self.assertEqual([i.getName() for i in providedBy(c)],
  98. ['I4', 'I5', 'I31'])
  99. self.assertEqual([i.getName() for i in providedBy(c).flattened()],
  100. ['I4', 'I5', 'I31', 'I3', 'Interface'])
  101. self.assertNotIn(I1, providedBy(c))
  102. self.assertNotIn(I3, providedBy(c))
  103. self.assertTrue(providedBy(c).extends(I3))
  104. self.assertFalse(providedBy(c).extends(I1))
  105. self.assertTrue(providedBy(c).extends(I31))
  106. self.assertTrue(providedBy(c).extends(I5))
  107. def test_classImplements(self):
  108. @implementer(I3)
  109. class A(Odd):
  110. pass
  111. @implementer(I4)
  112. class B(Odd):
  113. pass
  114. class C(A, B):
  115. pass
  116. classImplements(C, I1, I2)
  117. self.assertEqual([i.getName() for i in implementedBy(C)],
  118. ['I1', 'I2', 'I3', 'I4'])
  119. classImplements(C, I5)
  120. self.assertEqual([i.getName() for i in implementedBy(C)],
  121. ['I1', 'I2', 'I5', 'I3', 'I4'])
  122. def test_classImplementsOnly(self):
  123. @implementer(I3)
  124. class A(Odd):
  125. pass
  126. @implementer(I4)
  127. class B(Odd):
  128. pass
  129. class C(A, B):
  130. pass
  131. classImplementsOnly(C, I1, I2)
  132. self.assertEqual([i.__name__ for i in implementedBy(C)],
  133. ['I1', 'I2'])
  134. def test_directlyProvides(self):
  135. class IA1(Interface):
  136. pass
  137. class IA2(Interface):
  138. pass
  139. class IB(Interface):
  140. pass
  141. class IC(Interface):
  142. pass
  143. class A(Odd):
  144. pass
  145. classImplements(A, IA1, IA2)
  146. class B(Odd):
  147. pass
  148. classImplements(B, IB)
  149. class C(A, B):
  150. pass
  151. classImplements(C, IC)
  152. ob = C()
  153. directlyProvides(ob, I1, I2)
  154. self.assertIn(I1, providedBy(ob))
  155. self.assertIn(I2, providedBy(ob))
  156. self.assertIn(IA1, providedBy(ob))
  157. self.assertIn(IA2, providedBy(ob))
  158. self.assertIn(IB, providedBy(ob))
  159. self.assertIn(IC, providedBy(ob))
  160. directlyProvides(ob, directlyProvidedBy(ob) - I2)
  161. self.assertIn(I1, providedBy(ob))
  162. self.assertNotIn(I2, providedBy(ob))
  163. self.assertNotIn(I2, providedBy(ob))
  164. directlyProvides(ob, directlyProvidedBy(ob), I2)
  165. self.assertIn(I2, providedBy(ob))
  166. # see above
  167. # def TODO_test_classProvides_fails_for_odd_class(self):
  168. # try:
  169. # class A(Odd):
  170. # classProvides(I1)
  171. # except TypeError:
  172. # pass # Success
  173. # self.assert_(
  174. # False,
  175. # "Shouldn't be able to use directlyProvides on odd class."
  176. # )
  177. def test_implementedBy(self):
  178. class I2(I1):
  179. pass
  180. class C1(Odd):
  181. pass
  182. classImplements(C1, I2)
  183. class C2(C1):
  184. pass
  185. classImplements(C2, I3)
  186. self.assertEqual([i.getName() for i in implementedBy(C2)],
  187. ['I3', 'I2'])
  188. def test_odd_metaclass_that_doesnt_subclass_type(self):
  189. # This was originally a doctest in odd.py.
  190. # It verifies that the metaclass the rest of these tests use
  191. # works as expected.
  192. # This is used for testing support for ExtensionClass in new
  193. # interfaces.
  194. class A:
  195. a = 1
  196. A = odd.MetaClass('A', A.__bases__, A.__dict__)
  197. class B:
  198. b = 1
  199. B = odd.MetaClass('B', B.__bases__, B.__dict__)
  200. class C(A, B):
  201. pass
  202. self.assertEqual(C.__bases__, (A, B))
  203. a = A()
  204. aa = A()
  205. self.assertEqual(a.a, 1)
  206. self.assertEqual(aa.a, 1)
  207. aa.a = 2
  208. self.assertEqual(a.a, 1)
  209. self.assertEqual(aa.a, 2)
  210. c = C()
  211. self.assertEqual(c.a, 1)
  212. self.assertEqual(c.b, 1)
  213. c.b = 2
  214. self.assertEqual(c.b, 2)
  215. C.c = 1
  216. self.assertEqual(c.c, 1)
  217. c.c
  218. self.assertIs(C.__class__.__class__, C.__class__)