blob: 3a2bdf59526d4fd2904b4cb9276e1e0a8c543157 [file] [log] [blame]
Guido van Rossum3bead091992-01-27 17:00:37 +00001# Python test set -- part 5, built-in exceptions
2
Tim Peters80dc76e2006-06-07 06:57:51 +00003import os
4import sys
Georg Brandlcdcede62006-05-30 08:47:19 +00005import unittest
Tim Peters80dc76e2006-06-07 06:57:51 +00006import pickle, cPickle
Brett Cannon672237d2008-09-09 00:49:16 +00007import warnings
Tim Peters80dc76e2006-06-07 06:57:51 +00008
Brett Cannon672237d2008-09-09 00:49:16 +00009from test.test_support import TESTFN, unlink, run_unittest, captured_output
Senthil Kumarance8e33a2010-01-08 19:04:16 +000010from test.test_pep352 import ignore_message_warning
Guido van Rossum83b120d2001-08-23 03:23:03 +000011
Guido van Rossum3bead091992-01-27 17:00:37 +000012# XXX This is not really enough, each *operation* should be tested!
13
Georg Brandlcdcede62006-05-30 08:47:19 +000014class ExceptionTests(unittest.TestCase):
Barry Warsawb9c1d3d2001-08-13 23:07:00 +000015
Georg Brandlcdcede62006-05-30 08:47:19 +000016 def testReload(self):
17 # Reloading the built-in exceptions module failed prior to Py2.2, while it
18 # should act the same as reloading built-in sys.
19 try:
20 import exceptions
21 reload(exceptions)
22 except ImportError, e:
23 self.fail("reloading exceptions: %s" % e)
Jeremy Hylton56c807d2000-06-20 18:52:57 +000024
Georg Brandlcdcede62006-05-30 08:47:19 +000025 def raise_catch(self, exc, excname):
26 try:
27 raise exc, "spam"
28 except exc, err:
29 buf1 = str(err)
30 try:
31 raise exc("spam")
32 except exc, err:
33 buf2 = str(err)
34 self.assertEquals(buf1, buf2)
35 self.assertEquals(exc.__name__, excname)
Guido van Rossum3bead091992-01-27 17:00:37 +000036
Georg Brandlcdcede62006-05-30 08:47:19 +000037 def testRaising(self):
Tim Petersdd55b0a2006-05-30 23:28:02 +000038 self.raise_catch(AttributeError, "AttributeError")
Georg Brandlcdcede62006-05-30 08:47:19 +000039 self.assertRaises(AttributeError, getattr, sys, "undefined_attribute")
Guido van Rossum3bead091992-01-27 17:00:37 +000040
Georg Brandlcdcede62006-05-30 08:47:19 +000041 self.raise_catch(EOFError, "EOFError")
42 fp = open(TESTFN, 'w')
43 fp.close()
44 fp = open(TESTFN, 'r')
45 savestdin = sys.stdin
46 try:
47 try:
48 sys.stdin = fp
49 x = raw_input()
50 except EOFError:
51 pass
52 finally:
53 sys.stdin = savestdin
54 fp.close()
55 unlink(TESTFN)
Guido van Rossum3bead091992-01-27 17:00:37 +000056
Georg Brandlcdcede62006-05-30 08:47:19 +000057 self.raise_catch(IOError, "IOError")
58 self.assertRaises(IOError, open, 'this file does not exist', 'r')
Guido van Rossum3bead091992-01-27 17:00:37 +000059
Georg Brandlcdcede62006-05-30 08:47:19 +000060 self.raise_catch(ImportError, "ImportError")
61 self.assertRaises(ImportError, __import__, "undefined_module")
Guido van Rossum3bead091992-01-27 17:00:37 +000062
Georg Brandlcdcede62006-05-30 08:47:19 +000063 self.raise_catch(IndexError, "IndexError")
64 x = []
65 self.assertRaises(IndexError, x.__getitem__, 10)
Guido van Rossum3bead091992-01-27 17:00:37 +000066
Georg Brandlcdcede62006-05-30 08:47:19 +000067 self.raise_catch(KeyError, "KeyError")
68 x = {}
69 self.assertRaises(KeyError, x.__getitem__, 'key')
Guido van Rossum3bead091992-01-27 17:00:37 +000070
Georg Brandlcdcede62006-05-30 08:47:19 +000071 self.raise_catch(KeyboardInterrupt, "KeyboardInterrupt")
Guido van Rossum3bead091992-01-27 17:00:37 +000072
Georg Brandlcdcede62006-05-30 08:47:19 +000073 self.raise_catch(MemoryError, "MemoryError")
Guido van Rossum3bead091992-01-27 17:00:37 +000074
Georg Brandlcdcede62006-05-30 08:47:19 +000075 self.raise_catch(NameError, "NameError")
76 try: x = undefined_variable
77 except NameError: pass
Guido van Rossum3bead091992-01-27 17:00:37 +000078
Georg Brandlcdcede62006-05-30 08:47:19 +000079 self.raise_catch(OverflowError, "OverflowError")
80 x = 1
81 for dummy in range(128):
82 x += x # this simply shouldn't blow up
Guido van Rossum3bead091992-01-27 17:00:37 +000083
Georg Brandlcdcede62006-05-30 08:47:19 +000084 self.raise_catch(RuntimeError, "RuntimeError")
Guido van Rossum3bead091992-01-27 17:00:37 +000085
Georg Brandlcdcede62006-05-30 08:47:19 +000086 self.raise_catch(SyntaxError, "SyntaxError")
87 try: exec '/\n'
88 except SyntaxError: pass
Guido van Rossum3bead091992-01-27 17:00:37 +000089
Georg Brandlcdcede62006-05-30 08:47:19 +000090 self.raise_catch(IndentationError, "IndentationError")
Fred Drake72e48bd2000-09-08 16:32:34 +000091
Georg Brandlcdcede62006-05-30 08:47:19 +000092 self.raise_catch(TabError, "TabError")
93 # can only be tested under -tt, and is the only test for -tt
94 #try: compile("try:\n\t1/0\n \t1/0\nfinally:\n pass\n", '<string>', 'exec')
95 #except TabError: pass
96 #else: self.fail("TabError not raised")
Fred Drake72e48bd2000-09-08 16:32:34 +000097
Georg Brandlcdcede62006-05-30 08:47:19 +000098 self.raise_catch(SystemError, "SystemError")
Fred Drake72e48bd2000-09-08 16:32:34 +000099
Georg Brandlcdcede62006-05-30 08:47:19 +0000100 self.raise_catch(SystemExit, "SystemExit")
101 self.assertRaises(SystemExit, sys.exit, 0)
Fred Drake85f36392000-07-11 17:53:00 +0000102
Georg Brandlcdcede62006-05-30 08:47:19 +0000103 self.raise_catch(TypeError, "TypeError")
104 try: [] + ()
105 except TypeError: pass
Fred Drake85f36392000-07-11 17:53:00 +0000106
Georg Brandlcdcede62006-05-30 08:47:19 +0000107 self.raise_catch(ValueError, "ValueError")
108 self.assertRaises(ValueError, chr, 10000)
Guido van Rossum3bead091992-01-27 17:00:37 +0000109
Georg Brandlcdcede62006-05-30 08:47:19 +0000110 self.raise_catch(ZeroDivisionError, "ZeroDivisionError")
Senthil Kumarance8e33a2010-01-08 19:04:16 +0000111 try: x = 1/0
Georg Brandlcdcede62006-05-30 08:47:19 +0000112 except ZeroDivisionError: pass
Guido van Rossum3bead091992-01-27 17:00:37 +0000113
Georg Brandlcdcede62006-05-30 08:47:19 +0000114 self.raise_catch(Exception, "Exception")
Senthil Kumarance8e33a2010-01-08 19:04:16 +0000115 try: x = 1/0
Georg Brandlcdcede62006-05-30 08:47:19 +0000116 except Exception, e: pass
Guido van Rossum3bead091992-01-27 17:00:37 +0000117
Georg Brandlcdcede62006-05-30 08:47:19 +0000118 def testSyntaxErrorMessage(self):
Neal Norwitze152aab2006-06-02 04:45:53 +0000119 # make sure the right exception message is raised for each of
120 # these code fragments
Guido van Rossum3bead091992-01-27 17:00:37 +0000121
Georg Brandlcdcede62006-05-30 08:47:19 +0000122 def ckmsg(src, msg):
123 try:
124 compile(src, '<fragment>', 'exec')
125 except SyntaxError, e:
126 if e.msg != msg:
127 self.fail("expected %s, got %s" % (msg, e.msg))
128 else:
129 self.fail("failed to get expected SyntaxError")
Guido van Rossum3bead091992-01-27 17:00:37 +0000130
Georg Brandlcdcede62006-05-30 08:47:19 +0000131 s = '''while 1:
132 try:
133 pass
134 finally:
135 continue'''
Barry Warsaw992cb8a2000-05-25 23:16:54 +0000136
Georg Brandlcdcede62006-05-30 08:47:19 +0000137 if not sys.platform.startswith('java'):
138 ckmsg(s, "'continue' not supported inside 'finally' clause")
Jeremy Hyltonede049b2001-09-26 20:01:13 +0000139
Georg Brandlcdcede62006-05-30 08:47:19 +0000140 s = '''if 1:
141 try:
142 continue
143 except:
144 pass'''
Jeremy Hyltonede049b2001-09-26 20:01:13 +0000145
Georg Brandlcdcede62006-05-30 08:47:19 +0000146 ckmsg(s, "'continue' not properly in loop")
147 ckmsg("continue\n", "'continue' not properly in loop")
Jeremy Hyltonede049b2001-09-26 20:01:13 +0000148
Georg Brandlcdcede62006-05-30 08:47:19 +0000149 def testSettingException(self):
Neal Norwitze152aab2006-06-02 04:45:53 +0000150 # test that setting an exception at the C level works even if the
151 # exception object can't be constructed.
Finn Bockaa3dc452001-12-08 10:15:48 +0000152
Georg Brandlcdcede62006-05-30 08:47:19 +0000153 class BadException:
154 def __init__(self_):
155 raise RuntimeError, "can't instantiate BadException"
Jeremy Hyltonede049b2001-09-26 20:01:13 +0000156
Georg Brandlcdcede62006-05-30 08:47:19 +0000157 def test_capi1():
158 import _testcapi
159 try:
160 _testcapi.raise_exception(BadException, 1)
161 except TypeError, err:
162 exc, err, tb = sys.exc_info()
163 co = tb.tb_frame.f_code
164 self.assertEquals(co.co_name, "test_capi1")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000165 self.assertTrue(co.co_filename.endswith('test_exceptions'+os.extsep+'py'))
Georg Brandlcdcede62006-05-30 08:47:19 +0000166 else:
167 self.fail("Expected exception")
Richard Jones7b9558d2006-05-27 12:29:24 +0000168
Georg Brandlcdcede62006-05-30 08:47:19 +0000169 def test_capi2():
170 import _testcapi
171 try:
172 _testcapi.raise_exception(BadException, 0)
173 except RuntimeError, err:
174 exc, err, tb = sys.exc_info()
175 co = tb.tb_frame.f_code
176 self.assertEquals(co.co_name, "__init__")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000177 self.assertTrue(co.co_filename.endswith('test_exceptions'+os.extsep+'py'))
Georg Brandlcdcede62006-05-30 08:47:19 +0000178 co2 = tb.tb_frame.f_back.f_code
179 self.assertEquals(co2.co_name, "test_capi2")
180 else:
181 self.fail("Expected exception")
Richard Jones7b9558d2006-05-27 12:29:24 +0000182
Georg Brandlcdcede62006-05-30 08:47:19 +0000183 if not sys.platform.startswith('java'):
184 test_capi1()
185 test_capi2()
Georg Brandl05f97bf2006-05-30 07:13:29 +0000186
Thomas Hellerdf08f0b2006-10-27 18:31:36 +0000187 def test_WindowsError(self):
188 try:
189 WindowsError
190 except NameError:
191 pass
192 else:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000193 self.assertEqual(str(WindowsError(1001)),
Thomas Hellerdf08f0b2006-10-27 18:31:36 +0000194 "1001")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000195 self.assertEqual(str(WindowsError(1001, "message")),
Thomas Hellerdf08f0b2006-10-27 18:31:36 +0000196 "[Error 1001] message")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000197 self.assertEqual(WindowsError(1001, "message").errno, 22)
198 self.assertEqual(WindowsError(1001, "message").winerror, 1001)
Thomas Hellerdf08f0b2006-10-27 18:31:36 +0000199
Georg Brandlcdcede62006-05-30 08:47:19 +0000200 def testAttributes(self):
Neal Norwitze152aab2006-06-02 04:45:53 +0000201 # test that exception attributes are happy
Tim Petersdd55b0a2006-05-30 23:28:02 +0000202
Georg Brandlcdcede62006-05-30 08:47:19 +0000203 exceptionList = [
Georg Brandle08940e2006-06-01 13:00:49 +0000204 (BaseException, (), {'message' : '', 'args' : ()}),
205 (BaseException, (1, ), {'message' : 1, 'args' : (1,)}),
206 (BaseException, ('foo',),
207 {'message' : 'foo', 'args' : ('foo',)}),
208 (BaseException, ('foo', 1),
209 {'message' : '', 'args' : ('foo', 1)}),
210 (SystemExit, ('foo',),
211 {'message' : 'foo', 'args' : ('foo',), 'code' : 'foo'}),
212 (IOError, ('foo',),
Georg Brandl3267d282006-09-30 09:03:42 +0000213 {'message' : 'foo', 'args' : ('foo',), 'filename' : None,
214 'errno' : None, 'strerror' : None}),
Georg Brandle08940e2006-06-01 13:00:49 +0000215 (IOError, ('foo', 'bar'),
Georg Brandl3267d282006-09-30 09:03:42 +0000216 {'message' : '', 'args' : ('foo', 'bar'), 'filename' : None,
217 'errno' : 'foo', 'strerror' : 'bar'}),
Georg Brandle08940e2006-06-01 13:00:49 +0000218 (IOError, ('foo', 'bar', 'baz'),
Georg Brandl3267d282006-09-30 09:03:42 +0000219 {'message' : '', 'args' : ('foo', 'bar'), 'filename' : 'baz',
220 'errno' : 'foo', 'strerror' : 'bar'}),
221 (IOError, ('foo', 'bar', 'baz', 'quux'),
222 {'message' : '', 'args' : ('foo', 'bar', 'baz', 'quux')}),
Georg Brandle08940e2006-06-01 13:00:49 +0000223 (EnvironmentError, ('errnoStr', 'strErrorStr', 'filenameStr'),
224 {'message' : '', 'args' : ('errnoStr', 'strErrorStr'),
225 'strerror' : 'strErrorStr', 'errno' : 'errnoStr',
226 'filename' : 'filenameStr'}),
227 (EnvironmentError, (1, 'strErrorStr', 'filenameStr'),
228 {'message' : '', 'args' : (1, 'strErrorStr'), 'errno' : 1,
229 'strerror' : 'strErrorStr', 'filename' : 'filenameStr'}),
Brett Cannonf8267df2007-02-28 18:15:00 +0000230 (SyntaxError, (), {'message' : '', 'msg' : None, 'text' : None,
231 'filename' : None, 'lineno' : None, 'offset' : None,
232 'print_file_and_line' : None}),
Georg Brandle08940e2006-06-01 13:00:49 +0000233 (SyntaxError, ('msgStr',),
234 {'message' : 'msgStr', 'args' : ('msgStr',), 'text' : None,
235 'print_file_and_line' : None, 'msg' : 'msgStr',
236 'filename' : None, 'lineno' : None, 'offset' : None}),
237 (SyntaxError, ('msgStr', ('filenameStr', 'linenoStr', 'offsetStr',
238 'textStr')),
239 {'message' : '', 'offset' : 'offsetStr', 'text' : 'textStr',
240 'args' : ('msgStr', ('filenameStr', 'linenoStr',
241 'offsetStr', 'textStr')),
242 'print_file_and_line' : None, 'msg' : 'msgStr',
243 'filename' : 'filenameStr', 'lineno' : 'linenoStr'}),
244 (SyntaxError, ('msgStr', 'filenameStr', 'linenoStr', 'offsetStr',
245 'textStr', 'print_file_and_lineStr'),
246 {'message' : '', 'text' : None,
247 'args' : ('msgStr', 'filenameStr', 'linenoStr', 'offsetStr',
248 'textStr', 'print_file_and_lineStr'),
249 'print_file_and_line' : None, 'msg' : 'msgStr',
250 'filename' : None, 'lineno' : None, 'offset' : None}),
251 (UnicodeError, (), {'message' : '', 'args' : (),}),
Georg Brandl38f62372006-09-06 06:50:05 +0000252 (UnicodeEncodeError, ('ascii', u'a', 0, 1, 'ordinal not in range'),
253 {'message' : '', 'args' : ('ascii', u'a', 0, 1,
254 'ordinal not in range'),
255 'encoding' : 'ascii', 'object' : u'a',
256 'start' : 0, 'reason' : 'ordinal not in range'}),
257 (UnicodeDecodeError, ('ascii', '\xff', 0, 1, 'ordinal not in range'),
Georg Brandle08940e2006-06-01 13:00:49 +0000258 {'message' : '', 'args' : ('ascii', '\xff', 0, 1,
Georg Brandl38f62372006-09-06 06:50:05 +0000259 'ordinal not in range'),
Georg Brandle08940e2006-06-01 13:00:49 +0000260 'encoding' : 'ascii', 'object' : '\xff',
Georg Brandl38f62372006-09-06 06:50:05 +0000261 'start' : 0, 'reason' : 'ordinal not in range'}),
Georg Brandle08940e2006-06-01 13:00:49 +0000262 (UnicodeTranslateError, (u"\u3042", 0, 1, "ouch"),
263 {'message' : '', 'args' : (u'\u3042', 0, 1, 'ouch'),
264 'object' : u'\u3042', 'reason' : 'ouch',
265 'start' : 0, 'end' : 1}),
266 ]
Georg Brandlcdcede62006-05-30 08:47:19 +0000267 try:
268 exceptionList.append(
Georg Brandle08940e2006-06-01 13:00:49 +0000269 (WindowsError, (1, 'strErrorStr', 'filenameStr'),
270 {'message' : '', 'args' : (1, 'strErrorStr'),
271 'strerror' : 'strErrorStr', 'winerror' : 1,
272 'errno' : 22, 'filename' : 'filenameStr'})
273 )
Tim Peters80dc76e2006-06-07 06:57:51 +0000274 except NameError:
275 pass
Georg Brandlcdcede62006-05-30 08:47:19 +0000276
Senthil Kumarance8e33a2010-01-08 19:04:16 +0000277 with warnings.catch_warnings():
278 ignore_message_warning()
279 for exc, args, expected in exceptionList:
280 try:
281 raise exc(*args)
282 except BaseException, e:
283 if type(e) is not exc:
284 raise
285 # Verify module name
286 self.assertEquals(type(e).__module__, 'exceptions')
287 # Verify no ref leaks in Exc_str()
288 s = str(e)
289 for checkArgName in expected:
290 self.assertEquals(repr(getattr(e, checkArgName)),
291 repr(expected[checkArgName]),
292 'exception "%s", attribute "%s"' %
293 (repr(e), checkArgName))
Tim Petersdd55b0a2006-05-30 23:28:02 +0000294
Senthil Kumarance8e33a2010-01-08 19:04:16 +0000295 # test for pickling support
296 for p in pickle, cPickle:
297 for protocol in range(p.HIGHEST_PROTOCOL + 1):
298 new = p.loads(p.dumps(e, protocol))
299 for checkArgName in expected:
300 got = repr(getattr(new, checkArgName))
301 want = repr(expected[checkArgName])
302 self.assertEquals(got, want,
303 'pickled "%r", attribute "%s"' %
304 (e, checkArgName))
Georg Brandlcdcede62006-05-30 08:47:19 +0000305
Georg Brandl0674d3f2009-09-16 20:30:09 +0000306
307 def testDeprecatedMessageAttribute(self):
308 # Accessing BaseException.message and relying on its value set by
309 # BaseException.__init__ triggers a deprecation warning.
310 exc = BaseException("foo")
311 with warnings.catch_warnings(record=True) as w:
Brett Cannon6fdd3dc2010-01-10 02:56:19 +0000312 warnings.simplefilter('default')
Georg Brandl0674d3f2009-09-16 20:30:09 +0000313 self.assertEquals(exc.message, "foo")
314 self.assertEquals(len(w), 1)
315 self.assertEquals(w[0].category, DeprecationWarning)
316 self.assertEquals(
317 str(w[0].message),
318 "BaseException.message has been deprecated as of Python 2.6")
319
320
321 def testRegularMessageAttribute(self):
322 # Accessing BaseException.message after explicitly setting a value
323 # for it does not trigger a deprecation warning.
324 exc = BaseException("foo")
325 exc.message = "bar"
326 with warnings.catch_warnings(record=True) as w:
327 self.assertEquals(exc.message, "bar")
328 self.assertEquals(len(w), 0)
329 # Deleting the message is supported, too.
330 del exc.message
331 with self.assertRaises(AttributeError):
332 exc.message
333
334 def testPickleMessageAttribute(self):
335 # Pickling with message attribute must work, as well.
336 e = Exception("foo")
337 f = Exception("foo")
338 f.message = "bar"
339 for p in pickle, cPickle:
340 ep = p.loads(p.dumps(e))
Senthil Kumarance8e33a2010-01-08 19:04:16 +0000341 with warnings.catch_warnings():
342 ignore_message_warning()
343 self.assertEqual(ep.message, "foo")
Georg Brandl0674d3f2009-09-16 20:30:09 +0000344 fp = p.loads(p.dumps(f))
345 self.assertEqual(fp.message, "bar")
346
Brett Cannone05e6b02007-01-29 04:41:44 +0000347 def testSlicing(self):
348 # Test that you can slice an exception directly instead of requiring
349 # going through the 'args' attribute.
350 args = (1, 2, 3)
351 exc = BaseException(*args)
Senthil Kumarance8e33a2010-01-08 19:04:16 +0000352 self.assertEqual(exc[:], args)
Brett Cannone05e6b02007-01-29 04:41:44 +0000353
Georg Brandlcdcede62006-05-30 08:47:19 +0000354 def testKeywordArgs(self):
Neal Norwitze152aab2006-06-02 04:45:53 +0000355 # test that builtin exception don't take keyword args,
356 # but user-defined subclasses can if they want
Georg Brandlcdcede62006-05-30 08:47:19 +0000357 self.assertRaises(TypeError, BaseException, a=1)
Georg Brandle08940e2006-06-01 13:00:49 +0000358
Georg Brandlcdcede62006-05-30 08:47:19 +0000359 class DerivedException(BaseException):
360 def __init__(self, fancy_arg):
361 BaseException.__init__(self)
362 self.fancy_arg = fancy_arg
363
364 x = DerivedException(fancy_arg=42)
365 self.assertEquals(x.fancy_arg, 42)
366
Armin Rigo53c1692f2006-06-21 21:58:50 +0000367 def testInfiniteRecursion(self):
368 def f():
369 return f()
370 self.assertRaises(RuntimeError, f)
371
372 def g():
373 try:
374 return g()
375 except ValueError:
376 return -1
Antoine Pitrou0668c622008-08-26 22:42:08 +0000377
378 # The test prints an unraisable recursion error when
379 # doing "except ValueError", this is because subclass
380 # checking has recursion checking too.
381 with captured_output("stderr"):
382 try:
383 g()
384 except RuntimeError:
385 pass
386 except:
387 self.fail("Should have raised KeyError")
388 else:
389 self.fail("Should have raised KeyError")
Armin Rigo53c1692f2006-06-21 21:58:50 +0000390
Brett Cannonca2ca792006-09-09 07:11:46 +0000391 def testUnicodeStrUsage(self):
392 # Make sure both instances and classes have a str and unicode
393 # representation.
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000394 self.assertTrue(str(Exception))
395 self.assertTrue(unicode(Exception))
396 self.assertTrue(str(Exception('a')))
397 self.assertTrue(unicode(Exception(u'a')))
398 self.assertTrue(unicode(Exception(u'\xe1')))
Brett Cannonca2ca792006-09-09 07:11:46 +0000399
Amaury Forgeot d'Arc246daed2008-07-31 00:42:16 +0000400 def test_badisinstance(self):
401 # Bug #2542: if issubclass(e, MyException) raises an exception,
402 # it should be ignored
403 class Meta(type):
404 def __subclasscheck__(cls, subclass):
405 raise ValueError()
406
407 class MyException(Exception):
408 __metaclass__ = Meta
409 pass
410
411 with captured_output("stderr") as stderr:
412 try:
413 raise KeyError()
414 except MyException, e:
415 self.fail("exception should not be a MyException")
416 except KeyError:
417 pass
418 except:
Antoine Pitrou0668c622008-08-26 22:42:08 +0000419 self.fail("Should have raised KeyError")
Amaury Forgeot d'Arc246daed2008-07-31 00:42:16 +0000420 else:
Antoine Pitrou0668c622008-08-26 22:42:08 +0000421 self.fail("Should have raised KeyError")
422
423 with captured_output("stderr") as stderr:
424 def g():
425 try:
426 return g()
427 except RuntimeError:
428 return sys.exc_info()
429 e, v, tb = g()
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000430 self.assertTrue(e is RuntimeError, e)
431 self.assertTrue("maximum recursion depth exceeded" in str(v), v)
Antoine Pitrou0668c622008-08-26 22:42:08 +0000432
Brett Cannonca2ca792006-09-09 07:11:46 +0000433
Ezio Melottif84caf42009-12-24 22:25:17 +0000434
435# Helper class used by TestSameStrAndUnicodeMsg
436class ExcWithOverriddenStr(Exception):
437 """Subclass of Exception that accepts a keyword 'msg' arg that is
438 returned by __str__. 'msg' won't be included in self.args"""
439 def __init__(self, *args, **kwargs):
440 self.msg = kwargs.pop('msg') # msg should always be present
441 super(ExcWithOverriddenStr, self).__init__(*args, **kwargs)
442 def __str__(self):
443 return self.msg
444
445
446class TestSameStrAndUnicodeMsg(unittest.TestCase):
447 """unicode(err) should return the same message of str(err). See #6108"""
448
449 def check_same_msg(self, exc, msg):
450 """Helper function that checks if str(exc) == unicode(exc) == msg"""
451 self.assertEqual(str(exc), msg)
452 self.assertEqual(str(exc), unicode(exc))
453
454 def test_builtin_exceptions(self):
455 """Check same msg for built-in exceptions"""
456 # These exceptions implement a __str__ method that uses the args
457 # to create a better error message. unicode(e) should return the same
458 # message.
459 exceptions = [
460 SyntaxError('invalid syntax', ('<string>', 1, 3, '2+*3')),
461 IOError(2, 'No such file or directory'),
462 KeyError('both should have the same quotes'),
463 UnicodeDecodeError('ascii', '\xc3\xa0', 0, 1,
464 'ordinal not in range(128)'),
465 UnicodeEncodeError('ascii', u'\u1234', 0, 1,
466 'ordinal not in range(128)')
467 ]
468 for exception in exceptions:
469 self.assertEqual(str(exception), unicode(exception))
470
471 def test_0_args(self):
472 """Check same msg for Exception with 0 args"""
473 # str() and unicode() on an Exception with no args should return an
474 # empty string
475 self.check_same_msg(Exception(), '')
476
477 def test_0_args_with_overridden___str__(self):
478 """Check same msg for exceptions with 0 args and overridden __str__"""
479 # str() and unicode() on an exception with overridden __str__ that
480 # returns an ascii-only string should return the same string
481 for msg in ('foo', u'foo'):
482 self.check_same_msg(ExcWithOverriddenStr(msg=msg), msg)
483
484 # if __str__ returns a non-ascii unicode string str() should fail
485 # but unicode() should return the unicode string
486 e = ExcWithOverriddenStr(msg=u'f\xf6\xf6') # no args
487 self.assertRaises(UnicodeEncodeError, str, e)
488 self.assertEqual(unicode(e), u'f\xf6\xf6')
489
490 def test_1_arg(self):
491 """Check same msg for Exceptions with 1 arg"""
492 for arg in ('foo', u'foo'):
493 self.check_same_msg(Exception(arg), arg)
494
495 # if __str__ is not overridden and self.args[0] is a non-ascii unicode
496 # string, str() should try to return str(self.args[0]) and fail.
497 # unicode() should return unicode(self.args[0]) and succeed.
498 e = Exception(u'f\xf6\xf6')
499 self.assertRaises(UnicodeEncodeError, str, e)
500 self.assertEqual(unicode(e), u'f\xf6\xf6')
501
502 def test_1_arg_with_overridden___str__(self):
503 """Check same msg for exceptions with overridden __str__ and 1 arg"""
504 # when __str__ is overridden and __unicode__ is not implemented
505 # unicode(e) returns the same as unicode(e.__str__()).
506 for msg in ('foo', u'foo'):
507 self.check_same_msg(ExcWithOverriddenStr('arg', msg=msg), msg)
508
509 # if __str__ returns a non-ascii unicode string, str() should fail
510 # but unicode() should succeed.
511 e = ExcWithOverriddenStr('arg', msg=u'f\xf6\xf6') # 1 arg
512 self.assertRaises(UnicodeEncodeError, str, e)
513 self.assertEqual(unicode(e), u'f\xf6\xf6')
514
515 def test_many_args(self):
516 """Check same msg for Exceptions with many args"""
517 argslist = [
518 (3, 'foo'),
519 (1, u'foo', 'bar'),
520 (4, u'f\xf6\xf6', u'bar', 'baz')
521 ]
522 # both str() and unicode() should return a repr() of the args
523 for args in argslist:
524 self.check_same_msg(Exception(*args), repr(args))
525
526 def test_many_args_with_overridden___str__(self):
527 """Check same msg for exceptions with overridden __str__ and many args"""
528 # if __str__ returns an ascii string / ascii unicode string
529 # both str() and unicode() should succeed
530 for msg in ('foo', u'foo'):
531 e = ExcWithOverriddenStr('arg1', u'arg2', u'f\xf6\xf6', msg=msg)
532 self.check_same_msg(e, msg)
533
534 # if __str__ returns a non-ascii unicode string, str() should fail
535 # but unicode() should succeed
536 e = ExcWithOverriddenStr('arg1', u'f\xf6\xf6', u'arg3', # 3 args
537 msg=u'f\xf6\xf6')
538 self.assertRaises(UnicodeEncodeError, str, e)
539 self.assertEqual(unicode(e), u'f\xf6\xf6')
540
Georg Brandl740cdc32009-12-28 08:34:58 +0000541 def test_exception_with_doc(self):
542 import _testcapi
543 doc2 = "This is a test docstring."
544 doc4 = "This is another test docstring."
545
546 self.assertRaises(SystemError, _testcapi.make_exception_with_doc,
547 "error1")
548
549 # test basic usage of PyErr_NewException
550 error1 = _testcapi.make_exception_with_doc("_testcapi.error1")
551 self.assertIs(type(error1), type)
552 self.assertTrue(issubclass(error1, Exception))
553 self.assertIsNone(error1.__doc__)
554
555 # test with given docstring
556 error2 = _testcapi.make_exception_with_doc("_testcapi.error2", doc2)
557 self.assertEqual(error2.__doc__, doc2)
558
559 # test with explicit base (without docstring)
560 error3 = _testcapi.make_exception_with_doc("_testcapi.error3",
561 base=error2)
562 self.assertTrue(issubclass(error3, error2))
563
564 # test with explicit base tuple
565 class C(object):
566 pass
567 error4 = _testcapi.make_exception_with_doc("_testcapi.error4", doc4,
568 (error3, C))
569 self.assertTrue(issubclass(error4, error3))
570 self.assertTrue(issubclass(error4, C))
571 self.assertEqual(error4.__doc__, doc4)
572
573 # test with explicit dictionary
574 error5 = _testcapi.make_exception_with_doc("_testcapi.error5", "",
575 error4, {'a': 1})
576 self.assertTrue(issubclass(error5, error4))
577 self.assertEqual(error5.a, 1)
578 self.assertEqual(error5.__doc__, "")
579
Ezio Melottif84caf42009-12-24 22:25:17 +0000580
Georg Brandlcdcede62006-05-30 08:47:19 +0000581def test_main():
Ezio Melottif84caf42009-12-24 22:25:17 +0000582 run_unittest(ExceptionTests, TestSameStrAndUnicodeMsg)
Georg Brandlcdcede62006-05-30 08:47:19 +0000583
584if __name__ == '__main__':
585 test_main()