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