test_odd_declarations.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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 . import odd
  20. from zope.interface import Interface
  21. from zope.interface import implementer
  22. from zope.interface import directlyProvides
  23. from zope.interface import providedBy
  24. from zope.interface import directlyProvidedBy
  25. from zope.interface import classImplements
  26. from zope.interface import classImplementsOnly
  27. from zope.interface import implementedBy
  28. from zope.interface._compat import _skip_under_py3k
  29. class I1(Interface): pass
  30. class I2(Interface): pass
  31. class I3(Interface): pass
  32. class I31(I3): pass
  33. class I4(Interface): pass
  34. class I5(Interface): pass
  35. class Odd(object):
  36. pass
  37. Odd = odd.MetaClass('Odd', Odd.__bases__, {})
  38. class B(Odd): __implemented__ = I2
  39. # TODO: We are going to need more magic to make classProvides work with odd
  40. # classes. This will work in the next iteration. For now, we'll use
  41. # a different mechanism.
  42. # from zope.interface import classProvides
  43. class A(Odd):
  44. pass
  45. classImplements(A, I1)
  46. class C(A, B):
  47. pass
  48. classImplements(C, I31)
  49. class Test(unittest.TestCase):
  50. def test_ObjectSpecification(self):
  51. c = C()
  52. directlyProvides(c, I4)
  53. self.assertEqual([i.getName() for i in providedBy(c)],
  54. ['I4', 'I31', 'I1', 'I2']
  55. )
  56. self.assertEqual([i.getName() for i in providedBy(c).flattened()],
  57. ['I4', 'I31', 'I3', 'I1', 'I2', 'Interface']
  58. )
  59. self.assertTrue(I1 in providedBy(c))
  60. self.assertFalse(I3 in providedBy(c))
  61. self.assertTrue(providedBy(c).extends(I3))
  62. self.assertTrue(providedBy(c).extends(I31))
  63. self.assertFalse(providedBy(c).extends(I5))
  64. class COnly(A, B):
  65. pass
  66. classImplementsOnly(COnly, I31)
  67. class D(COnly):
  68. pass
  69. classImplements(D, I5)
  70. classImplements(D, I5)
  71. c = D()
  72. directlyProvides(c, I4)
  73. self.assertEqual([i.getName() for i in providedBy(c)],
  74. ['I4', 'I5', 'I31'])
  75. self.assertEqual([i.getName() for i in providedBy(c).flattened()],
  76. ['I4', 'I5', 'I31', 'I3', 'Interface'])
  77. self.assertFalse(I1 in providedBy(c))
  78. self.assertFalse(I3 in providedBy(c))
  79. self.assertTrue(providedBy(c).extends(I3))
  80. self.assertFalse(providedBy(c).extends(I1))
  81. self.assertTrue(providedBy(c).extends(I31))
  82. self.assertTrue(providedBy(c).extends(I5))
  83. class COnly(A, B): __implemented__ = I31
  84. class D(COnly):
  85. pass
  86. classImplements(D, I5)
  87. classImplements(D, I5)
  88. c = D()
  89. directlyProvides(c, I4)
  90. self.assertEqual([i.getName() for i in providedBy(c)],
  91. ['I4', 'I5', 'I31'])
  92. self.assertEqual([i.getName() for i in providedBy(c).flattened()],
  93. ['I4', 'I5', 'I31', 'I3', 'Interface'])
  94. self.assertFalse(I1 in providedBy(c))
  95. self.assertFalse(I3 in providedBy(c))
  96. self.assertTrue(providedBy(c).extends(I3))
  97. self.assertFalse(providedBy(c).extends(I1))
  98. self.assertTrue(providedBy(c).extends(I31))
  99. self.assertTrue(providedBy(c).extends(I5))
  100. def test_classImplements(self):
  101. @implementer(I3)
  102. class A(Odd):
  103. pass
  104. @implementer(I4)
  105. class B(Odd):
  106. pass
  107. class C(A, B):
  108. pass
  109. classImplements(C, I1, I2)
  110. self.assertEqual([i.getName() for i in implementedBy(C)],
  111. ['I1', 'I2', 'I3', 'I4'])
  112. classImplements(C, I5)
  113. self.assertEqual([i.getName() for i in implementedBy(C)],
  114. ['I1', 'I2', 'I5', 'I3', 'I4'])
  115. def test_classImplementsOnly(self):
  116. @implementer(I3)
  117. class A(Odd):
  118. pass
  119. @implementer(I4)
  120. class B(Odd):
  121. pass
  122. class C(A, B):
  123. pass
  124. classImplementsOnly(C, I1, I2)
  125. self.assertEqual([i.__name__ for i in implementedBy(C)],
  126. ['I1', 'I2'])
  127. def test_directlyProvides(self):
  128. class IA1(Interface): pass
  129. class IA2(Interface): pass
  130. class IB(Interface): pass
  131. class IC(Interface): pass
  132. class A(Odd):
  133. pass
  134. classImplements(A, IA1, IA2)
  135. class B(Odd):
  136. pass
  137. classImplements(B, IB)
  138. class C(A, B):
  139. pass
  140. classImplements(C, IC)
  141. ob = C()
  142. directlyProvides(ob, I1, I2)
  143. self.assertTrue(I1 in providedBy(ob))
  144. self.assertTrue(I2 in providedBy(ob))
  145. self.assertTrue(IA1 in providedBy(ob))
  146. self.assertTrue(IA2 in providedBy(ob))
  147. self.assertTrue(IB in providedBy(ob))
  148. self.assertTrue(IC in providedBy(ob))
  149. directlyProvides(ob, directlyProvidedBy(ob)-I2)
  150. self.assertTrue(I1 in providedBy(ob))
  151. self.assertFalse(I2 in providedBy(ob))
  152. self.assertFalse(I2 in providedBy(ob))
  153. directlyProvides(ob, directlyProvidedBy(ob), I2)
  154. self.assertTrue(I2 in providedBy(ob))
  155. @_skip_under_py3k
  156. def test_directlyProvides_fails_for_odd_class(self):
  157. self.assertRaises(TypeError, directlyProvides, C, I5)
  158. # see above
  159. #def TODO_test_classProvides_fails_for_odd_class(self):
  160. # try:
  161. # class A(Odd):
  162. # classProvides(I1)
  163. # except TypeError:
  164. # pass # Success
  165. # self.assert_(False,
  166. # "Shouldn't be able to use directlyProvides on odd class."
  167. # )
  168. def test_implementedBy(self):
  169. class I2(I1): pass
  170. class C1(Odd):
  171. pass
  172. classImplements(C1, I2)
  173. class C2(C1):
  174. pass
  175. classImplements(C2, I3)
  176. self.assertEqual([i.getName() for i in implementedBy(C2)],
  177. ['I3', 'I2'])
  178. def test_odd_metaclass_that_doesnt_subclass_type(self):
  179. # This was originally a doctest in odd.py.
  180. # It verifies that the metaclass the rest of these tests use
  181. # works as expected.
  182. # This is used for testing support for ExtensionClass in new interfaces.
  183. class A(object):
  184. a = 1
  185. A = odd.MetaClass('A', A.__bases__, A.__dict__)
  186. class B(object):
  187. b = 1
  188. B = odd.MetaClass('B', B.__bases__, B.__dict__)
  189. class C(A, B):
  190. pass
  191. self.assertEqual(C.__bases__, (A, B))
  192. a = A()
  193. aa = A()
  194. self.assertEqual(a.a, 1)
  195. self.assertEqual(aa.a, 1)
  196. aa.a = 2
  197. self.assertEqual(a.a, 1)
  198. self.assertEqual(aa.a, 2)
  199. c = C()
  200. self.assertEqual(c.a, 1)
  201. self.assertEqual(c.b, 1)
  202. c.b = 2
  203. self.assertEqual(c.b, 2)
  204. C.c = 1
  205. self.assertEqual(c.c, 1)
  206. c.c
  207. try:
  208. from types import ClassType
  209. except ImportError:
  210. pass
  211. else:
  212. # This test only makes sense under Python 2.x
  213. assert not isinstance(C, (type, ClassType))
  214. self.assertIs(C.__class__.__class__, C.__class__)