/Lib/test/test_pep352.py

http://unladen-swallow.googlecode.com/ · Python · 249 lines · 208 code · 26 blank · 15 comment · 39 complexity · 6861ef6c4af5b8ae145410114ac5244e MD5 · raw file

  1. import unittest
  2. import __builtin__
  3. import exceptions
  4. import warnings
  5. from test.test_support import run_unittest
  6. import os
  7. from platform import system as platform_system
  8. def ignore_message_warning():
  9. """Ignore the DeprecationWarning for BaseException.message."""
  10. warnings.resetwarnings()
  11. warnings.filterwarnings("ignore", "BaseException.message",
  12. DeprecationWarning)
  13. class ExceptionClassTests(unittest.TestCase):
  14. """Tests for anything relating to exception objects themselves (e.g.,
  15. inheritance hierarchy)"""
  16. def test_builtins_new_style(self):
  17. self.failUnless(issubclass(Exception, object))
  18. def verify_instance_interface(self, ins):
  19. with warnings.catch_warnings():
  20. ignore_message_warning()
  21. for attr in ("args", "message", "__str__", "__repr__",
  22. "__getitem__"):
  23. self.failUnless(hasattr(ins, attr),
  24. "%s missing %s attribute" %
  25. (ins.__class__.__name__, attr))
  26. def test_inheritance(self):
  27. # Make sure the inheritance hierarchy matches the documentation
  28. exc_set = set(x for x in dir(exceptions) if not x.startswith('_'))
  29. inheritance_tree = open(os.path.join(os.path.split(__file__)[0],
  30. 'exception_hierarchy.txt'))
  31. try:
  32. superclass_name = inheritance_tree.readline().rstrip()
  33. try:
  34. last_exc = getattr(__builtin__, superclass_name)
  35. except AttributeError:
  36. self.fail("base class %s not a built-in" % superclass_name)
  37. self.failUnless(superclass_name in exc_set)
  38. exc_set.discard(superclass_name)
  39. superclasses = [] # Loop will insert base exception
  40. last_depth = 0
  41. for exc_line in inheritance_tree:
  42. exc_line = exc_line.rstrip()
  43. depth = exc_line.rindex('-')
  44. exc_name = exc_line[depth+2:] # Slice past space
  45. if '(' in exc_name:
  46. paren_index = exc_name.index('(')
  47. platform_name = exc_name[paren_index+1:-1]
  48. exc_name = exc_name[:paren_index-1] # Slice off space
  49. if platform_system() != platform_name:
  50. exc_set.discard(exc_name)
  51. continue
  52. if '[' in exc_name:
  53. left_bracket = exc_name.index('[')
  54. exc_name = exc_name[:left_bracket-1] # cover space
  55. try:
  56. exc = getattr(__builtin__, exc_name)
  57. except AttributeError:
  58. self.fail("%s not a built-in exception" % exc_name)
  59. if last_depth < depth:
  60. superclasses.append((last_depth, last_exc))
  61. elif last_depth > depth:
  62. while superclasses[-1][0] >= depth:
  63. superclasses.pop()
  64. self.failUnless(issubclass(exc, superclasses[-1][1]),
  65. "%s is not a subclass of %s" % (exc.__name__,
  66. superclasses[-1][1].__name__))
  67. try: # Some exceptions require arguments; just skip them
  68. self.verify_instance_interface(exc())
  69. except TypeError:
  70. pass
  71. self.failUnless(exc_name in exc_set)
  72. exc_set.discard(exc_name)
  73. last_exc = exc
  74. last_depth = depth
  75. finally:
  76. inheritance_tree.close()
  77. self.failUnlessEqual(len(exc_set), 0, "%s not accounted for" % exc_set)
  78. interface_tests = ("length", "args", "message", "str", "unicode", "repr",
  79. "indexing")
  80. def interface_test_driver(self, results):
  81. for test_name, (given, expected) in zip(self.interface_tests, results):
  82. self.failUnlessEqual(given, expected, "%s: %s != %s" % (test_name,
  83. given, expected))
  84. def test_interface_single_arg(self):
  85. # Make sure interface works properly when given a single argument
  86. arg = "spam"
  87. exc = Exception(arg)
  88. with warnings.catch_warnings():
  89. ignore_message_warning()
  90. results = ([len(exc.args), 1], [exc.args[0], arg],
  91. [exc.message, arg],
  92. [str(exc), str(arg)], [unicode(exc), unicode(arg)],
  93. [repr(exc), exc.__class__.__name__ + repr(exc.args)], [exc[0],
  94. arg])
  95. self.interface_test_driver(results)
  96. def test_interface_multi_arg(self):
  97. # Make sure interface correct when multiple arguments given
  98. arg_count = 3
  99. args = tuple(range(arg_count))
  100. exc = Exception(*args)
  101. with warnings.catch_warnings():
  102. ignore_message_warning()
  103. results = ([len(exc.args), arg_count], [exc.args, args],
  104. [exc.message, ''], [str(exc), str(args)],
  105. [unicode(exc), unicode(args)],
  106. [repr(exc), exc.__class__.__name__ + repr(exc.args)],
  107. [exc[-1], args[-1]])
  108. self.interface_test_driver(results)
  109. def test_interface_no_arg(self):
  110. # Make sure that with no args that interface is correct
  111. exc = Exception()
  112. with warnings.catch_warnings():
  113. ignore_message_warning()
  114. results = ([len(exc.args), 0], [exc.args, tuple()],
  115. [exc.message, ''],
  116. [str(exc), ''], [unicode(exc), u''],
  117. [repr(exc), exc.__class__.__name__ + '()'], [True, True])
  118. self.interface_test_driver(results)
  119. def test_message_deprecation(self):
  120. # As of Python 2.6, BaseException.message is deprecated.
  121. with warnings.catch_warnings():
  122. warnings.resetwarnings()
  123. warnings.filterwarnings('error')
  124. try:
  125. BaseException().message
  126. except DeprecationWarning:
  127. pass
  128. else:
  129. self.fail("BaseException.message not deprecated")
  130. class UsageTests(unittest.TestCase):
  131. """Test usage of exceptions"""
  132. def raise_fails(self, object_):
  133. """Make sure that raising 'object_' triggers a TypeError."""
  134. try:
  135. raise object_
  136. except TypeError:
  137. return # What is expected.
  138. self.fail("TypeError expected for raising %s" % type(object_))
  139. def catch_fails(self, object_):
  140. """Catching 'object_' should raise a TypeError."""
  141. try:
  142. try:
  143. raise StandardError
  144. except object_:
  145. pass
  146. except TypeError:
  147. pass
  148. except StandardError:
  149. self.fail("TypeError expected when catching %s" % type(object_))
  150. try:
  151. try:
  152. raise StandardError
  153. except (object_,):
  154. pass
  155. except TypeError:
  156. return
  157. except StandardError:
  158. self.fail("TypeError expected when catching %s as specified in a "
  159. "tuple" % type(object_))
  160. def test_raise_classic(self):
  161. # Raising a classic class is okay (for now).
  162. class ClassicClass:
  163. pass
  164. try:
  165. raise ClassicClass
  166. except ClassicClass:
  167. pass
  168. except:
  169. self.fail("unable to raise classic class")
  170. try:
  171. raise ClassicClass()
  172. except ClassicClass:
  173. pass
  174. except:
  175. self.fail("unable to raise class class instance")
  176. def test_raise_new_style_non_exception(self):
  177. # You cannot raise a new-style class that does not inherit from
  178. # BaseException; the ability was not possible until BaseException's
  179. # introduction so no need to support new-style objects that do not
  180. # inherit from it.
  181. class NewStyleClass(object):
  182. pass
  183. self.raise_fails(NewStyleClass)
  184. self.raise_fails(NewStyleClass())
  185. def test_raise_string(self):
  186. # Raising a string raises TypeError.
  187. self.raise_fails("spam")
  188. def test_catch_string(self):
  189. # Catching a string should trigger a DeprecationWarning.
  190. with warnings.catch_warnings():
  191. warnings.resetwarnings()
  192. warnings.filterwarnings("error")
  193. str_exc = "spam"
  194. try:
  195. try:
  196. raise StandardError
  197. except str_exc:
  198. pass
  199. except DeprecationWarning:
  200. pass
  201. except StandardError:
  202. self.fail("catching a string exception did not raise "
  203. "DeprecationWarning")
  204. # Make sure that even if the string exception is listed in a tuple
  205. # that a warning is raised.
  206. try:
  207. try:
  208. raise StandardError
  209. except (AssertionError, str_exc):
  210. pass
  211. except DeprecationWarning:
  212. pass
  213. except StandardError:
  214. self.fail("catching a string exception specified in a tuple did "
  215. "not raise DeprecationWarning")
  216. def test_main():
  217. run_unittest(ExceptionClassTests, UsageTests)
  218. if __name__ == '__main__':
  219. test_main()