|
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 |
|
9 class ExceptionClassTests(unittest.TestCase): |
|
10 |
|
11 """Tests for anything relating to exception objects themselves (e.g., |
|
12 inheritance hierarchy)""" |
|
13 |
|
14 def test_builtins_new_style(self): |
|
15 self.failUnless(issubclass(Exception, object)) |
|
16 |
|
17 def verify_instance_interface(self, ins): |
|
18 for attr in ("args", "message", "__str__", "__repr__", "__getitem__"): |
|
19 self.failUnless(hasattr(ins, attr), "%s missing %s attribute" % |
|
20 (ins.__class__.__name__, attr)) |
|
21 |
|
22 def test_inheritance(self): |
|
23 # Make sure the inheritance hierarchy matches the documentation |
|
24 exc_set = set(x for x in dir(exceptions) if not x.startswith('_')) |
|
25 inheritance_tree = open(os.path.join(os.path.split(__file__)[0], |
|
26 'exception_hierarchy.txt')) |
|
27 try: |
|
28 superclass_name = inheritance_tree.readline().rstrip() |
|
29 try: |
|
30 last_exc = getattr(__builtin__, superclass_name) |
|
31 except AttributeError: |
|
32 self.fail("base class %s not a built-in" % superclass_name) |
|
33 self.failUnless(superclass_name in exc_set) |
|
34 exc_set.discard(superclass_name) |
|
35 superclasses = [] # Loop will insert base exception |
|
36 last_depth = 0 |
|
37 for exc_line in inheritance_tree: |
|
38 exc_line = exc_line.rstrip() |
|
39 depth = exc_line.rindex('-') |
|
40 exc_name = exc_line[depth+2:] # Slice past space |
|
41 if '(' in exc_name: |
|
42 paren_index = exc_name.index('(') |
|
43 platform_name = exc_name[paren_index+1:-1] |
|
44 exc_name = exc_name[:paren_index-1] # Slice off space |
|
45 if platform_system() != platform_name: |
|
46 exc_set.discard(exc_name) |
|
47 continue |
|
48 if '[' in exc_name: |
|
49 left_bracket = exc_name.index('[') |
|
50 exc_name = exc_name[:left_bracket-1] # cover space |
|
51 try: |
|
52 exc = getattr(__builtin__, exc_name) |
|
53 except AttributeError: |
|
54 self.fail("%s not a built-in exception" % exc_name) |
|
55 if last_depth < depth: |
|
56 superclasses.append((last_depth, last_exc)) |
|
57 elif last_depth > depth: |
|
58 while superclasses[-1][0] >= depth: |
|
59 superclasses.pop() |
|
60 self.failUnless(issubclass(exc, superclasses[-1][1]), |
|
61 "%s is not a subclass of %s" % (exc.__name__, |
|
62 superclasses[-1][1].__name__)) |
|
63 try: # Some exceptions require arguments; just skip them |
|
64 self.verify_instance_interface(exc()) |
|
65 except TypeError: |
|
66 pass |
|
67 self.failUnless(exc_name in exc_set) |
|
68 exc_set.discard(exc_name) |
|
69 last_exc = exc |
|
70 last_depth = depth |
|
71 finally: |
|
72 inheritance_tree.close() |
|
73 self.failUnlessEqual(len(exc_set), 0, "%s not accounted for" % exc_set) |
|
74 |
|
75 interface_tests = ("length", "args", "message", "str", "unicode", "repr", |
|
76 "indexing") |
|
77 |
|
78 def interface_test_driver(self, results): |
|
79 for test_name, (given, expected) in zip(self.interface_tests, results): |
|
80 self.failUnlessEqual(given, expected, "%s: %s != %s" % (test_name, |
|
81 given, expected)) |
|
82 |
|
83 def test_interface_single_arg(self): |
|
84 # Make sure interface works properly when given a single argument |
|
85 arg = "spam" |
|
86 exc = Exception(arg) |
|
87 results = ([len(exc.args), 1], [exc.args[0], arg], [exc.message, arg], |
|
88 [str(exc), str(arg)], [unicode(exc), unicode(arg)], |
|
89 [repr(exc), exc.__class__.__name__ + repr(exc.args)], [exc[0], arg]) |
|
90 self.interface_test_driver(results) |
|
91 |
|
92 def test_interface_multi_arg(self): |
|
93 # Make sure interface correct when multiple arguments given |
|
94 arg_count = 3 |
|
95 args = tuple(range(arg_count)) |
|
96 exc = Exception(*args) |
|
97 results = ([len(exc.args), arg_count], [exc.args, args], |
|
98 [exc.message, ''], [str(exc), str(args)], |
|
99 [unicode(exc), unicode(args)], |
|
100 [repr(exc), exc.__class__.__name__ + repr(exc.args)], |
|
101 [exc[-1], args[-1]]) |
|
102 self.interface_test_driver(results) |
|
103 |
|
104 def test_interface_no_arg(self): |
|
105 # Make sure that with no args that interface is correct |
|
106 exc = Exception() |
|
107 results = ([len(exc.args), 0], [exc.args, tuple()], [exc.message, ''], |
|
108 [str(exc), ''], [unicode(exc), u''], |
|
109 [repr(exc), exc.__class__.__name__ + '()'], [True, True]) |
|
110 self.interface_test_driver(results) |
|
111 |
|
112 class UsageTests(unittest.TestCase): |
|
113 |
|
114 """Test usage of exceptions""" |
|
115 |
|
116 def setUp(self): |
|
117 self._filters = warnings.filters[:] |
|
118 |
|
119 def tearDown(self): |
|
120 warnings.filters = self._filters[:] |
|
121 |
|
122 def test_raise_classic(self): |
|
123 class ClassicClass: |
|
124 pass |
|
125 try: |
|
126 raise ClassicClass |
|
127 except ClassicClass: |
|
128 pass |
|
129 except: |
|
130 self.fail("unable to raise classic class") |
|
131 try: |
|
132 raise ClassicClass() |
|
133 except ClassicClass: |
|
134 pass |
|
135 except: |
|
136 self.fail("unable to raise class class instance") |
|
137 |
|
138 def test_raise_new_style_non_exception(self): |
|
139 class NewStyleClass(object): |
|
140 pass |
|
141 try: |
|
142 raise NewStyleClass |
|
143 except TypeError: |
|
144 pass |
|
145 except: |
|
146 self.fail("unable to raise new-style class") |
|
147 try: |
|
148 raise NewStyleClass() |
|
149 except TypeError: |
|
150 pass |
|
151 except: |
|
152 self.fail("unable to raise new-style class instance") |
|
153 |
|
154 def test_raise_string(self): |
|
155 warnings.resetwarnings() |
|
156 warnings.filterwarnings("error") |
|
157 try: |
|
158 raise "spam" |
|
159 except DeprecationWarning: |
|
160 pass |
|
161 except: |
|
162 self.fail("raising a string did not cause a DeprecationWarning") |
|
163 |
|
164 def test_catch_string(self): |
|
165 # Test will be pertinent when catching exceptions raises a |
|
166 # DeprecationWarning |
|
167 warnings.filterwarnings("ignore", "raising") |
|
168 str_exc = "spam" |
|
169 try: |
|
170 raise str_exc |
|
171 except str_exc: |
|
172 pass |
|
173 except: |
|
174 self.fail("catching a string exception failed") |
|
175 |
|
176 def test_main(): |
|
177 run_unittest(ExceptionClassTests, UsageTests) |
|
178 |
|
179 |
|
180 |
|
181 if __name__ == '__main__': |
|
182 test_main() |