5 from test
.test_support
import run_unittest
, check_warnings
8 from platform
import system
as platform_system
10 DEPRECATION_WARNINGS
= ["BaseException.message has been deprecated"]
13 DEPRECATION_WARNINGS
.extend(
14 ["exceptions must derive from BaseException",
15 "catching classes that don't inherit from BaseException is not allowed",
16 "__get(item|slice)__ not supported for exception classes"])
18 _deprecations
= [(msg
, DeprecationWarning) for msg
in DEPRECATION_WARNINGS
]
20 # Silence Py3k and other deprecation warnings
21 def ignore_deprecation_warnings(func
):
22 """Ignore the known DeprecationWarnings."""
23 def wrapper(*args
, **kw
):
24 with
check_warnings(*_deprecations
, quiet
=True):
25 return func(*args
, **kw
)
28 class ExceptionClassTests(unittest
.TestCase
):
30 """Tests for anything relating to exception objects themselves (e.g.,
31 inheritance hierarchy)"""
33 def test_builtins_new_style(self
):
34 self
.assertTrue(issubclass(Exception, object))
36 @ignore_deprecation_warnings
37 def verify_instance_interface(self
, ins
):
38 for attr
in ("args", "message", "__str__", "__repr__", "__getitem__"):
39 self
.assertTrue(hasattr(ins
, attr
),
40 "%s missing %s attribute" %
41 (ins
.__class
__.__name
__, attr
))
43 def test_inheritance(self
):
44 # Make sure the inheritance hierarchy matches the documentation
45 exc_set
= set(x
for x
in dir(exceptions
) if not x
.startswith('_'))
46 inheritance_tree
= open(os
.path
.join(os
.path
.split(__file__
)[0],
47 'exception_hierarchy.txt'))
49 superclass_name
= inheritance_tree
.readline().rstrip()
51 last_exc
= getattr(__builtin__
, superclass_name
)
52 except AttributeError:
53 self
.fail("base class %s not a built-in" % superclass_name
)
54 self
.assertIn(superclass_name
, exc_set
)
55 exc_set
.discard(superclass_name
)
56 superclasses
= [] # Loop will insert base exception
58 for exc_line
in inheritance_tree
:
59 exc_line
= exc_line
.rstrip()
60 depth
= exc_line
.rindex('-')
61 exc_name
= exc_line
[depth
+2:] # Slice past space
63 paren_index
= exc_name
.index('(')
64 platform_name
= exc_name
[paren_index
+1:-1]
65 exc_name
= exc_name
[:paren_index
-1] # Slice off space
66 if platform_system() != platform_name
:
67 exc_set
.discard(exc_name
)
70 left_bracket
= exc_name
.index('[')
71 exc_name
= exc_name
[:left_bracket
-1] # cover space
73 exc
= getattr(__builtin__
, exc_name
)
74 except AttributeError:
75 self
.fail("%s not a built-in exception" % exc_name
)
76 if last_depth
< depth
:
77 superclasses
.append((last_depth
, last_exc
))
78 elif last_depth
> depth
:
79 while superclasses
[-1][0] >= depth
:
81 self
.assertTrue(issubclass(exc
, superclasses
[-1][1]),
82 "%s is not a subclass of %s" % (exc
.__name
__,
83 superclasses
[-1][1].__name
__))
84 try: # Some exceptions require arguments; just skip them
85 self
.verify_instance_interface(exc())
88 self
.assertIn(exc_name
, exc_set
)
89 exc_set
.discard(exc_name
)
93 inheritance_tree
.close()
94 self
.assertEqual(len(exc_set
), 0, "%s not accounted for" % exc_set
)
96 interface_tests
= ("length", "args", "message", "str", "unicode", "repr",
99 def interface_test_driver(self
, results
):
100 for test_name
, (given
, expected
) in zip(self
.interface_tests
, results
):
101 self
.assertEqual(given
, expected
, "%s: %s != %s" % (test_name
,
104 @ignore_deprecation_warnings
105 def test_interface_single_arg(self
):
106 # Make sure interface works properly when given a single argument
109 results
= ([len(exc
.args
), 1], [exc
.args
[0], arg
], [exc
.message
, arg
],
110 [str(exc
), str(arg
)], [unicode(exc
), unicode(arg
)],
111 [repr(exc
), exc
.__class
__.__name
__ + repr(exc
.args
)],
113 self
.interface_test_driver(results
)
115 @ignore_deprecation_warnings
116 def test_interface_multi_arg(self
):
117 # Make sure interface correct when multiple arguments given
119 args
= tuple(range(arg_count
))
120 exc
= Exception(*args
)
121 results
= ([len(exc
.args
), arg_count
], [exc
.args
, args
],
122 [exc
.message
, ''], [str(exc
), str(args
)],
123 [unicode(exc
), unicode(args
)],
124 [repr(exc
), exc
.__class
__.__name
__ + repr(exc
.args
)],
126 self
.interface_test_driver(results
)
128 @ignore_deprecation_warnings
129 def test_interface_no_arg(self
):
130 # Make sure that with no args that interface is correct
132 results
= ([len(exc
.args
), 0], [exc
.args
, tuple()],
134 [str(exc
), ''], [unicode(exc
), u
''],
135 [repr(exc
), exc
.__class
__.__name
__ + '()'], [True, True])
136 self
.interface_test_driver(results
)
139 def test_message_deprecation(self
):
140 # As of Python 2.6, BaseException.message is deprecated.
141 with
check_warnings(("", DeprecationWarning)):
142 BaseException().message
145 class UsageTests(unittest
.TestCase
):
147 """Test usage of exceptions"""
149 def raise_fails(self
, object_
):
150 """Make sure that raising 'object_' triggers a TypeError."""
154 return # What is expected.
155 self
.fail("TypeError expected for raising %s" % type(object_
))
157 def catch_fails(self
, object_
):
158 """Catching 'object_' should raise a TypeError."""
166 except StandardError:
167 self
.fail("TypeError expected when catching %s" % type(object_
))
176 except StandardError:
177 self
.fail("TypeError expected when catching %s as specified in a "
178 "tuple" % type(object_
))
180 @ignore_deprecation_warnings
181 def test_raise_classic(self
):
182 # Raising a classic class is okay (for now).
190 self
.fail("unable to raise classic class")
196 self
.fail("unable to raise classic class instance")
198 def test_raise_new_style_non_exception(self
):
199 # You cannot raise a new-style class that does not inherit from
200 # BaseException; the ability was not possible until BaseException's
201 # introduction so no need to support new-style objects that do not
203 class NewStyleClass(object):
205 self
.raise_fails(NewStyleClass
)
206 self
.raise_fails(NewStyleClass())
208 def test_raise_string(self
):
209 # Raising a string raises TypeError.
210 self
.raise_fails("spam")
212 def test_catch_string(self
):
213 # Catching a string should trigger a DeprecationWarning.
214 with warnings
.catch_warnings():
215 warnings
.resetwarnings()
216 warnings
.filterwarnings("error")
218 with self
.assertRaises(DeprecationWarning):
224 # Make sure that even if the string exception is listed in a tuple
225 # that a warning is raised.
226 with self
.assertRaises(DeprecationWarning):
229 except (AssertionError, str_exc
):
234 run_unittest(ExceptionClassTests
, UsageTests
)
238 if __name__
== '__main__':