blob: a30f42bcd68bea2be447c505013d00610de10ea7 [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:
312 self.assertEquals(exc.message, "foo")
313 self.assertEquals(len(w), 1)
314 self.assertEquals(w[0].category, DeprecationWarning)
315 self.assertEquals(
316 str(w[0].message),
317 "BaseException.message has been deprecated as of Python 2.6")
318
319
320 def testRegularMessageAttribute(self):
321 # Accessing BaseException.message after explicitly setting a value
322 # for it does not trigger a deprecation warning.
323 exc = BaseException("foo")
324 exc.message = "bar"
325 with warnings.catch_warnings(record=True) as w:
326 self.assertEquals(exc.message, "bar")
327 self.assertEquals(len(w), 0)
328 # Deleting the message is supported, too.
329 del exc.message
330 with self.assertRaises(AttributeError):
331 exc.message
332
333 def testPickleMessageAttribute(self):
334 # Pickling with message attribute must work, as well.
335 e = Exception("foo")
336 f = Exception("foo")
337 f.message = "bar"
338 for p in pickle, cPickle:
339 ep = p.loads(p.dumps(e))
Senthil Kumarance8e33a2010-01-08 19:04:16 +0000340 with warnings.catch_warnings():
341 ignore_message_warning()
342 self.assertEqual(ep.message, "foo")
Georg Brandl0674d3f2009-09-16 20:30:09 +0000343 fp = p.loads(p.dumps(f))
344 self.assertEqual(fp.message, "bar")
345
Brett Cannone05e6b02007-01-29 04:41:44 +0000346 def testSlicing(self):
347 # Test that you can slice an exception directly instead of requiring
348 # going through the 'args' attribute.
349 args = (1, 2, 3)
350 exc = BaseException(*args)
Senthil Kumarance8e33a2010-01-08 19:04:16 +0000351 self.assertEqual(exc[:], args)
Brett Cannone05e6b02007-01-29 04:41:44 +0000352
Georg Brandlcdcede62006-05-30 08:47:19 +0000353 def testKeywordArgs(self):
Neal Norwitze152aab2006-06-02 04:45:53 +0000354 # test that builtin exception don't take keyword args,
355 # but user-defined subclasses can if they want
Georg Brandlcdcede62006-05-30 08:47:19 +0000356 self.assertRaises(TypeError, BaseException, a=1)
Georg Brandle08940e2006-06-01 13:00:49 +0000357
Georg Brandlcdcede62006-05-30 08:47:19 +0000358 class DerivedException(BaseException):
359 def __init__(self, fancy_arg):
360 BaseException.__init__(self)
361 self.fancy_arg = fancy_arg
362
363 x = DerivedException(fancy_arg=42)
364 self.assertEquals(x.fancy_arg, 42)
365
Armin Rigo53c1692f2006-06-21 21:58:50 +0000366 def testInfiniteRecursion(self):
367 def f():
368 return f()
369 self.assertRaises(RuntimeError, f)
370
371 def g():
372 try:
373 return g()
374 except ValueError:
375 return -1
Antoine Pitrou0668c622008-08-26 22:42:08 +0000376
377 # The test prints an unraisable recursion error when
378 # doing "except ValueError", this is because subclass
379 # checking has recursion checking too.
380 with captured_output("stderr"):
381 try:
382 g()
383 except RuntimeError:
384 pass
385 except:
386 self.fail("Should have raised KeyError")
387 else:
388 self.fail("Should have raised KeyError")
Armin Rigo53c1692f2006-06-21 21:58:50 +0000389
Brett Cannonca2ca792006-09-09 07:11:46 +0000390 def testUnicodeStrUsage(self):
391 # Make sure both instances and classes have a str and unicode
392 # representation.
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000393 self.assertTrue(str(Exception))
394 self.assertTrue(unicode(Exception))
395 self.assertTrue(str(Exception('a')))
396 self.assertTrue(unicode(Exception(u'a')))
397 self.assertTrue(unicode(Exception(u'\xe1')))
Brett Cannonca2ca792006-09-09 07:11:46 +0000398
Amaury Forgeot d'Arc246daed2008-07-31 00:42:16 +0000399 def test_badisinstance(self):
400 # Bug #2542: if issubclass(e, MyException) raises an exception,
401 # it should be ignored
402 class Meta(type):
403 def __subclasscheck__(cls, subclass):
404 raise ValueError()
405
406 class MyException(Exception):
407 __metaclass__ = Meta
408 pass
409
410 with captured_output("stderr") as stderr:
411 try:
412 raise KeyError()
413 except MyException, e:
414 self.fail("exception should not be a MyException")
415 except KeyError:
416 pass
417 except:
Antoine Pitrou0668c622008-08-26 22:42:08 +0000418 self.fail("Should have raised KeyError")
Amaury Forgeot d'Arc246daed2008-07-31 00:42:16 +0000419 else:
Antoine Pitrou0668c622008-08-26 22:42:08 +0000420 self.fail("Should have raised KeyError")
421
422 with captured_output("stderr") as stderr:
423 def g():
424 try:
425 return g()
426 except RuntimeError:
427 return sys.exc_info()
428 e, v, tb = g()
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000429 self.assertTrue(e is RuntimeError, e)
430 self.assertTrue("maximum recursion depth exceeded" in str(v), v)
Antoine Pitrou0668c622008-08-26 22:42:08 +0000431
Brett Cannonca2ca792006-09-09 07:11:46 +0000432
Ezio Melottif84caf42009-12-24 22:25:17 +0000433
434# Helper class used by TestSameStrAndUnicodeMsg
435class ExcWithOverriddenStr(Exception):
436 """Subclass of Exception that accepts a keyword 'msg' arg that is
437 returned by __str__. 'msg' won't be included in self.args"""
438 def __init__(self, *args, **kwargs):
439 self.msg = kwargs.pop('msg') # msg should always be present
440 super(ExcWithOverriddenStr, self).__init__(*args, **kwargs)
441 def __str__(self):
442 return self.msg
443
444
445class TestSameStrAndUnicodeMsg(unittest.TestCase):
446 """unicode(err) should return the same message of str(err). See #6108"""
447
448 def check_same_msg(self, exc, msg):
449 """Helper function that checks if str(exc) == unicode(exc) == msg"""
450 self.assertEqual(str(exc), msg)
451 self.assertEqual(str(exc), unicode(exc))
452
453 def test_builtin_exceptions(self):
454 """Check same msg for built-in exceptions"""
455 # These exceptions implement a __str__ method that uses the args
456 # to create a better error message. unicode(e) should return the same
457 # message.
458 exceptions = [
459 SyntaxError('invalid syntax', ('<string>', 1, 3, '2+*3')),
460 IOError(2, 'No such file or directory'),
461 KeyError('both should have the same quotes'),
462 UnicodeDecodeError('ascii', '\xc3\xa0', 0, 1,
463 'ordinal not in range(128)'),
464 UnicodeEncodeError('ascii', u'\u1234', 0, 1,
465 'ordinal not in range(128)')
466 ]
467 for exception in exceptions:
468 self.assertEqual(str(exception), unicode(exception))
469
470 def test_0_args(self):
471 """Check same msg for Exception with 0 args"""
472 # str() and unicode() on an Exception with no args should return an
473 # empty string
474 self.check_same_msg(Exception(), '')
475
476 def test_0_args_with_overridden___str__(self):
477 """Check same msg for exceptions with 0 args and overridden __str__"""
478 # str() and unicode() on an exception with overridden __str__ that
479 # returns an ascii-only string should return the same string
480 for msg in ('foo', u'foo'):
481 self.check_same_msg(ExcWithOverriddenStr(msg=msg), msg)
482
483 # if __str__ returns a non-ascii unicode string str() should fail
484 # but unicode() should return the unicode string
485 e = ExcWithOverriddenStr(msg=u'f\xf6\xf6') # no args
486 self.assertRaises(UnicodeEncodeError, str, e)
487 self.assertEqual(unicode(e), u'f\xf6\xf6')
488
489 def test_1_arg(self):
490 """Check same msg for Exceptions with 1 arg"""
491 for arg in ('foo', u'foo'):
492 self.check_same_msg(Exception(arg), arg)
493
494 # if __str__ is not overridden and self.args[0] is a non-ascii unicode
495 # string, str() should try to return str(self.args[0]) and fail.
496 # unicode() should return unicode(self.args[0]) and succeed.
497 e = Exception(u'f\xf6\xf6')
498 self.assertRaises(UnicodeEncodeError, str, e)
499 self.assertEqual(unicode(e), u'f\xf6\xf6')
500
501 def test_1_arg_with_overridden___str__(self):
502 """Check same msg for exceptions with overridden __str__ and 1 arg"""
503 # when __str__ is overridden and __unicode__ is not implemented
504 # unicode(e) returns the same as unicode(e.__str__()).
505 for msg in ('foo', u'foo'):
506 self.check_same_msg(ExcWithOverriddenStr('arg', msg=msg), msg)
507
508 # if __str__ returns a non-ascii unicode string, str() should fail
509 # but unicode() should succeed.
510 e = ExcWithOverriddenStr('arg', msg=u'f\xf6\xf6') # 1 arg
511 self.assertRaises(UnicodeEncodeError, str, e)
512 self.assertEqual(unicode(e), u'f\xf6\xf6')
513
514 def test_many_args(self):
515 """Check same msg for Exceptions with many args"""
516 argslist = [
517 (3, 'foo'),
518 (1, u'foo', 'bar'),
519 (4, u'f\xf6\xf6', u'bar', 'baz')
520 ]
521 # both str() and unicode() should return a repr() of the args
522 for args in argslist:
523 self.check_same_msg(Exception(*args), repr(args))
524
525 def test_many_args_with_overridden___str__(self):
526 """Check same msg for exceptions with overridden __str__ and many args"""
527 # if __str__ returns an ascii string / ascii unicode string
528 # both str() and unicode() should succeed
529 for msg in ('foo', u'foo'):
530 e = ExcWithOverriddenStr('arg1', u'arg2', u'f\xf6\xf6', msg=msg)
531 self.check_same_msg(e, msg)
532
533 # if __str__ returns a non-ascii unicode string, str() should fail
534 # but unicode() should succeed
535 e = ExcWithOverriddenStr('arg1', u'f\xf6\xf6', u'arg3', # 3 args
536 msg=u'f\xf6\xf6')
537 self.assertRaises(UnicodeEncodeError, str, e)
538 self.assertEqual(unicode(e), u'f\xf6\xf6')
539
Georg Brandl740cdc32009-12-28 08:34:58 +0000540 def test_exception_with_doc(self):
541 import _testcapi
542 doc2 = "This is a test docstring."
543 doc4 = "This is another test docstring."
544
545 self.assertRaises(SystemError, _testcapi.make_exception_with_doc,
546 "error1")
547
548 # test basic usage of PyErr_NewException
549 error1 = _testcapi.make_exception_with_doc("_testcapi.error1")
550 self.assertIs(type(error1), type)
551 self.assertTrue(issubclass(error1, Exception))
552 self.assertIsNone(error1.__doc__)
553
554 # test with given docstring
555 error2 = _testcapi.make_exception_with_doc("_testcapi.error2", doc2)
556 self.assertEqual(error2.__doc__, doc2)
557
558 # test with explicit base (without docstring)
559 error3 = _testcapi.make_exception_with_doc("_testcapi.error3",
560 base=error2)
561 self.assertTrue(issubclass(error3, error2))
562
563 # test with explicit base tuple
564 class C(object):
565 pass
566 error4 = _testcapi.make_exception_with_doc("_testcapi.error4", doc4,
567 (error3, C))
568 self.assertTrue(issubclass(error4, error3))
569 self.assertTrue(issubclass(error4, C))
570 self.assertEqual(error4.__doc__, doc4)
571
572 # test with explicit dictionary
573 error5 = _testcapi.make_exception_with_doc("_testcapi.error5", "",
574 error4, {'a': 1})
575 self.assertTrue(issubclass(error5, error4))
576 self.assertEqual(error5.a, 1)
577 self.assertEqual(error5.__doc__, "")
578
Ezio Melottif84caf42009-12-24 22:25:17 +0000579
Georg Brandlcdcede62006-05-30 08:47:19 +0000580def test_main():
Ezio Melottif84caf42009-12-24 22:25:17 +0000581 run_unittest(ExceptionTests, TestSameStrAndUnicodeMsg)
Georg Brandlcdcede62006-05-30 08:47:19 +0000582
583if __name__ == '__main__':
584 test_main()