+++ /dev/null
-import unittest\r
-import __builtin__\r
-import exceptions\r
-import warnings\r
-from test.test_support import run_unittest, check_warnings\r
-import os\r
-import sys\r
-from platform import system as platform_system\r
-\r
-DEPRECATION_WARNINGS = ["BaseException.message has been deprecated"]\r
-\r
-if sys.py3kwarning:\r
- DEPRECATION_WARNINGS.extend(\r
- ["exceptions must derive from BaseException",\r
- "catching classes that don't inherit from BaseException is not allowed",\r
- "__get(item|slice)__ not supported for exception classes"])\r
-\r
-_deprecations = [(msg, DeprecationWarning) for msg in DEPRECATION_WARNINGS]\r
-\r
-# Silence Py3k and other deprecation warnings\r
-def ignore_deprecation_warnings(func):\r
- """Ignore the known DeprecationWarnings."""\r
- def wrapper(*args, **kw):\r
- with check_warnings(*_deprecations, quiet=True):\r
- return func(*args, **kw)\r
- return wrapper\r
-\r
-class ExceptionClassTests(unittest.TestCase):\r
-\r
- """Tests for anything relating to exception objects themselves (e.g.,\r
- inheritance hierarchy)"""\r
-\r
- def test_builtins_new_style(self):\r
- self.assertTrue(issubclass(Exception, object))\r
-\r
- @ignore_deprecation_warnings\r
- def verify_instance_interface(self, ins):\r
- for attr in ("args", "message", "__str__", "__repr__", "__getitem__"):\r
- self.assertTrue(hasattr(ins, attr),\r
- "%s missing %s attribute" %\r
- (ins.__class__.__name__, attr))\r
-\r
- def test_inheritance(self):\r
- # Make sure the inheritance hierarchy matches the documentation\r
- exc_set = set(x for x in dir(exceptions) if not x.startswith('_'))\r
- inheritance_tree = open(os.path.join(os.path.split(__file__)[0],\r
- 'exception_hierarchy.txt'))\r
- try:\r
- superclass_name = inheritance_tree.readline().rstrip()\r
- try:\r
- last_exc = getattr(__builtin__, superclass_name)\r
- except AttributeError:\r
- self.fail("base class %s not a built-in" % superclass_name)\r
- self.assertIn(superclass_name, exc_set)\r
- exc_set.discard(superclass_name)\r
- superclasses = [] # Loop will insert base exception\r
- last_depth = 0\r
- for exc_line in inheritance_tree:\r
- exc_line = exc_line.rstrip()\r
- depth = exc_line.rindex('-')\r
- exc_name = exc_line[depth+2:] # Slice past space\r
- if '(' in exc_name:\r
- paren_index = exc_name.index('(')\r
- platform_name = exc_name[paren_index+1:-1]\r
- exc_name = exc_name[:paren_index-1] # Slice off space\r
- if platform_system() != platform_name:\r
- exc_set.discard(exc_name)\r
- continue\r
- if '[' in exc_name:\r
- left_bracket = exc_name.index('[')\r
- exc_name = exc_name[:left_bracket-1] # cover space\r
- try:\r
- exc = getattr(__builtin__, exc_name)\r
- except AttributeError:\r
- self.fail("%s not a built-in exception" % exc_name)\r
- if last_depth < depth:\r
- superclasses.append((last_depth, last_exc))\r
- elif last_depth > depth:\r
- while superclasses[-1][0] >= depth:\r
- superclasses.pop()\r
- self.assertTrue(issubclass(exc, superclasses[-1][1]),\r
- "%s is not a subclass of %s" % (exc.__name__,\r
- superclasses[-1][1].__name__))\r
- try: # Some exceptions require arguments; just skip them\r
- self.verify_instance_interface(exc())\r
- except TypeError:\r
- pass\r
- self.assertIn(exc_name, exc_set)\r
- exc_set.discard(exc_name)\r
- last_exc = exc\r
- last_depth = depth\r
- finally:\r
- inheritance_tree.close()\r
- self.assertEqual(len(exc_set), 0, "%s not accounted for" % exc_set)\r
-\r
- interface_tests = ("length", "args", "message", "str", "unicode", "repr",\r
- "indexing")\r
-\r
- def interface_test_driver(self, results):\r
- for test_name, (given, expected) in zip(self.interface_tests, results):\r
- self.assertEqual(given, expected, "%s: %s != %s" % (test_name,\r
- given, expected))\r
-\r
- @ignore_deprecation_warnings\r
- def test_interface_single_arg(self):\r
- # Make sure interface works properly when given a single argument\r
- arg = "spam"\r
- exc = Exception(arg)\r
- results = ([len(exc.args), 1], [exc.args[0], arg], [exc.message, arg],\r
- [str(exc), str(arg)], [unicode(exc), unicode(arg)],\r
- [repr(exc), exc.__class__.__name__ + repr(exc.args)],\r
- [exc[0], arg])\r
- self.interface_test_driver(results)\r
-\r
- @ignore_deprecation_warnings\r
- def test_interface_multi_arg(self):\r
- # Make sure interface correct when multiple arguments given\r
- arg_count = 3\r
- args = tuple(range(arg_count))\r
- exc = Exception(*args)\r
- results = ([len(exc.args), arg_count], [exc.args, args],\r
- [exc.message, ''], [str(exc), str(args)],\r
- [unicode(exc), unicode(args)],\r
- [repr(exc), exc.__class__.__name__ + repr(exc.args)],\r
- [exc[-1], args[-1]])\r
- self.interface_test_driver(results)\r
-\r
- @ignore_deprecation_warnings\r
- def test_interface_no_arg(self):\r
- # Make sure that with no args that interface is correct\r
- exc = Exception()\r
- results = ([len(exc.args), 0], [exc.args, tuple()],\r
- [exc.message, ''],\r
- [str(exc), ''], [unicode(exc), u''],\r
- [repr(exc), exc.__class__.__name__ + '()'], [True, True])\r
- self.interface_test_driver(results)\r
-\r
-\r
- def test_message_deprecation(self):\r
- # As of Python 2.6, BaseException.message is deprecated.\r
- with check_warnings(("", DeprecationWarning)):\r
- BaseException().message\r
-\r
-\r
-class UsageTests(unittest.TestCase):\r
-\r
- """Test usage of exceptions"""\r
-\r
- def raise_fails(self, object_):\r
- """Make sure that raising 'object_' triggers a TypeError."""\r
- try:\r
- raise object_\r
- except TypeError:\r
- return # What is expected.\r
- self.fail("TypeError expected for raising %s" % type(object_))\r
-\r
- def catch_fails(self, object_):\r
- """Catching 'object_' should raise a TypeError."""\r
- try:\r
- try:\r
- raise StandardError\r
- except object_:\r
- pass\r
- except TypeError:\r
- pass\r
- except StandardError:\r
- self.fail("TypeError expected when catching %s" % type(object_))\r
-\r
- try:\r
- try:\r
- raise StandardError\r
- except (object_,):\r
- pass\r
- except TypeError:\r
- return\r
- except StandardError:\r
- self.fail("TypeError expected when catching %s as specified in a "\r
- "tuple" % type(object_))\r
-\r
- @ignore_deprecation_warnings\r
- def test_raise_classic(self):\r
- # Raising a classic class is okay (for now).\r
- class ClassicClass:\r
- pass\r
- try:\r
- raise ClassicClass\r
- except ClassicClass:\r
- pass\r
- except:\r
- self.fail("unable to raise classic class")\r
- try:\r
- raise ClassicClass()\r
- except ClassicClass:\r
- pass\r
- except:\r
- self.fail("unable to raise classic class instance")\r
-\r
- def test_raise_new_style_non_exception(self):\r
- # You cannot raise a new-style class that does not inherit from\r
- # BaseException; the ability was not possible until BaseException's\r
- # introduction so no need to support new-style objects that do not\r
- # inherit from it.\r
- class NewStyleClass(object):\r
- pass\r
- self.raise_fails(NewStyleClass)\r
- self.raise_fails(NewStyleClass())\r
-\r
- def test_raise_string(self):\r
- # Raising a string raises TypeError.\r
- self.raise_fails("spam")\r
-\r
- def test_catch_string(self):\r
- # Catching a string should trigger a DeprecationWarning.\r
- with warnings.catch_warnings():\r
- warnings.resetwarnings()\r
- warnings.filterwarnings("error")\r
- str_exc = "spam"\r
- with self.assertRaises(DeprecationWarning):\r
- try:\r
- raise StandardError\r
- except str_exc:\r
- pass\r
-\r
- # Make sure that even if the string exception is listed in a tuple\r
- # that a warning is raised.\r
- with self.assertRaises(DeprecationWarning):\r
- try:\r
- raise StandardError\r
- except (AssertionError, str_exc):\r
- pass\r
-\r
-\r
-def test_main():\r
- run_unittest(ExceptionClassTests, UsageTests)\r
-\r
-\r
-\r
-if __name__ == '__main__':\r
- test_main()\r