test_advice.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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. """Tests for advice
  15. This module was adapted from 'protocols.tests.advice', part of the Python
  16. Enterprise Application Kit (PEAK). Please notify the PEAK authors
  17. (pje@telecommunity.com and tsarna@sarna.org) if bugs are found or
  18. Zope-specific changes are required, so that the PEAK version of this module
  19. can be kept in sync.
  20. PEAK is a Python application framework that interoperates with (but does
  21. not require) Zope 3 and Twisted. It provides tools for manipulating UML
  22. models, object-relational persistence, aspect-oriented programming, and more.
  23. Visit the PEAK home page at http://peak.telecommunity.com for more information.
  24. """
  25. import sys
  26. import unittest
  27. class FrameInfoTest(unittest.TestCase):
  28. def test_w_module(self):
  29. from . import advisory_testing
  30. (kind, module,
  31. f_locals, f_globals) = advisory_testing.moduleLevelFrameInfo
  32. self.assertEqual(kind, "module")
  33. for d in module.__dict__, f_locals, f_globals:
  34. self.assertIs(d, advisory_testing.my_globals)
  35. def test_w_class(self):
  36. from . import advisory_testing
  37. (kind,
  38. module,
  39. f_locals,
  40. f_globals) = advisory_testing.NewStyleClass.classLevelFrameInfo
  41. self.assertEqual(kind, "class")
  42. for d in module.__dict__, f_globals:
  43. self.assertIs(d, advisory_testing.my_globals)
  44. def test_inside_function_call(self):
  45. from zope.interface.advice import getFrameInfo
  46. kind, module, f_locals, f_globals = getFrameInfo(sys._getframe())
  47. self.assertEqual(kind, "function call")
  48. frame = sys._getframe()
  49. self.assertEqual(f_locals, frame.f_locals)
  50. self.assertEqual(f_locals, locals())
  51. for d in module.__dict__, f_globals:
  52. self.assertIs(d, globals())
  53. def test_inside_exec(self):
  54. from zope.interface.advice import getFrameInfo
  55. _globals = {'getFrameInfo': getFrameInfo}
  56. _locals = {}
  57. exec(_FUNKY_EXEC, _globals, _locals)
  58. self.assertEqual(_locals['kind'], "exec")
  59. self.assertIs(_locals['f_locals'], _locals)
  60. self.assertIsNone(_locals['module'])
  61. self.assertIs(_locals['f_globals'], _globals)
  62. _FUNKY_EXEC = """\
  63. import sys
  64. kind, module, f_locals, f_globals = getFrameInfo(sys._getframe())
  65. """
  66. class Test_isClassAdvisor(unittest.TestCase):
  67. def _callFUT(self, *args, **kw):
  68. from zope.interface.advice import isClassAdvisor
  69. return isClassAdvisor(*args, **kw)
  70. def test_w_non_function(self):
  71. self.assertEqual(self._callFUT(self), False)
  72. def test_w_normal_function(self):
  73. def foo():
  74. raise NotImplementedError()
  75. self.assertEqual(self._callFUT(foo), False)
  76. def test_w_advisor_function(self):
  77. def bar():
  78. raise NotImplementedError()
  79. bar.previousMetaclass = object()
  80. self.assertEqual(self._callFUT(bar), True)
  81. class Test_determineMetaclass(unittest.TestCase):
  82. def _callFUT(self, *args, **kw):
  83. from zope.interface.advice import determineMetaclass
  84. return determineMetaclass(*args, **kw)
  85. def test_empty_w_explicit_metatype(self):
  86. class Meta(type):
  87. pass
  88. self.assertEqual(self._callFUT((), Meta), Meta)
  89. def test_single(self):
  90. class Meta(type):
  91. pass
  92. self.assertEqual(self._callFUT((Meta,)), type)
  93. def test_meta_of_class(self):
  94. class Metameta(type):
  95. pass
  96. class Meta(type, metaclass=Metameta):
  97. pass
  98. self.assertEqual(self._callFUT((Meta, type)), Metameta)
  99. def test_multiple_in_hierarchy_py3k(self):
  100. class Meta_A(type):
  101. pass
  102. class Meta_B(Meta_A):
  103. pass
  104. class A(type, metaclass=Meta_A):
  105. pass
  106. class B(type, metaclass=Meta_B):
  107. pass
  108. self.assertEqual(self._callFUT((A, B)), Meta_B)
  109. def test_multiple_not_in_hierarchy_py3k(self):
  110. class Meta_A(type):
  111. pass
  112. class Meta_B(type):
  113. pass
  114. class A(type, metaclass=Meta_A):
  115. pass
  116. class B(type, metaclass=Meta_B):
  117. pass
  118. self.assertRaises(TypeError, self._callFUT, (A, B))
  119. class Test_minimalBases(unittest.TestCase):
  120. def _callFUT(self, klasses):
  121. from zope.interface.advice import minimalBases
  122. return minimalBases(klasses)
  123. def test_empty(self):
  124. self.assertEqual(self._callFUT([]), [])
  125. def test_w_newstyle_meta(self):
  126. self.assertEqual(self._callFUT([type]), [type])
  127. def test_w_newstyle_class(self):
  128. class C:
  129. pass
  130. self.assertEqual(self._callFUT([C]), [C])
  131. def test_simple_hierarchy_skips_implied(self):
  132. class A:
  133. pass
  134. class B(A):
  135. pass
  136. class C(B):
  137. pass
  138. class D:
  139. pass
  140. self.assertEqual(self._callFUT([A, B, C]), [C])
  141. self.assertEqual(self._callFUT([A, C]), [C])
  142. self.assertEqual(self._callFUT([B, C]), [C])
  143. self.assertEqual(self._callFUT([A, B]), [B])
  144. self.assertEqual(self._callFUT([D, B, D]), [B, D])
  145. def test_repeats_kicked_to_end_of_queue(self):
  146. class A:
  147. pass
  148. class B:
  149. pass
  150. self.assertEqual(self._callFUT([A, B, A]), [B, A])