blob: 8a0f30f50ec1577471b7f69d26bf27bd4e812756 [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
Ezio Melotti1f517e12010-02-02 17:34:37 +000010from test.test_pep352 import ignore_deprecation_warnings
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:
Ezio Melotti1f517e12010-02-02 17:34:37 +000020 from imp import reload
Georg Brandlcdcede62006-05-30 08:47:19 +000021 import exceptions
22 reload(exceptions)
23 except ImportError, e:
24 self.fail("reloading exceptions: %s" % e)
Jeremy Hylton56c807d2000-06-20 18:52:57 +000025
Georg Brandlcdcede62006-05-30 08:47:19 +000026 def raise_catch(self, exc, excname):
27 try:
28 raise exc, "spam"
29 except exc, err:
30 buf1 = str(err)
31 try:
32 raise exc("spam")
33 except exc, err:
34 buf2 = str(err)
35 self.assertEquals(buf1, buf2)
36 self.assertEquals(exc.__name__, excname)
Guido van Rossum3bead091992-01-27 17:00:37 +000037
Georg Brandlcdcede62006-05-30 08:47:19 +000038 def testRaising(self):
Tim Petersdd55b0a2006-05-30 23:28:02 +000039 self.raise_catch(AttributeError, "AttributeError")
Georg Brandlcdcede62006-05-30 08:47:19 +000040 self.assertRaises(AttributeError, getattr, sys, "undefined_attribute")
Guido van Rossum3bead091992-01-27 17:00:37 +000041
Georg Brandlcdcede62006-05-30 08:47:19 +000042 self.raise_catch(EOFError, "EOFError")
43 fp = open(TESTFN, 'w')
44 fp.close()
45 fp = open(TESTFN, 'r')
46 savestdin = sys.stdin
47 try:
48 try:
49 sys.stdin = fp
50 x = raw_input()
51 except EOFError:
52 pass
53 finally:
54 sys.stdin = savestdin
55 fp.close()
56 unlink(TESTFN)
Guido van Rossum3bead091992-01-27 17:00:37 +000057
Georg Brandlcdcede62006-05-30 08:47:19 +000058 self.raise_catch(IOError, "IOError")
59 self.assertRaises(IOError, open, 'this file does not exist', 'r')
Guido van Rossum3bead091992-01-27 17:00:37 +000060
Georg Brandlcdcede62006-05-30 08:47:19 +000061 self.raise_catch(ImportError, "ImportError")
62 self.assertRaises(ImportError, __import__, "undefined_module")
Guido van Rossum3bead091992-01-27 17:00:37 +000063
Georg Brandlcdcede62006-05-30 08:47:19 +000064 self.raise_catch(IndexError, "IndexError")
65 x = []
66 self.assertRaises(IndexError, x.__getitem__, 10)
Guido van Rossum3bead091992-01-27 17:00:37 +000067
Georg Brandlcdcede62006-05-30 08:47:19 +000068 self.raise_catch(KeyError, "KeyError")
69 x = {}
70 self.assertRaises(KeyError, x.__getitem__, 'key')
Guido van Rossum3bead091992-01-27 17:00:37 +000071
Georg Brandlcdcede62006-05-30 08:47:19 +000072 self.raise_catch(KeyboardInterrupt, "KeyboardInterrupt")
Guido van Rossum3bead091992-01-27 17:00:37 +000073
Georg Brandlcdcede62006-05-30 08:47:19 +000074 self.raise_catch(MemoryError, "MemoryError")
Guido van Rossum3bead091992-01-27 17:00:37 +000075
Georg Brandlcdcede62006-05-30 08:47:19 +000076 self.raise_catch(NameError, "NameError")
77 try: x = undefined_variable
78 except NameError: pass
Guido van Rossum3bead091992-01-27 17:00:37 +000079
Georg Brandlcdcede62006-05-30 08:47:19 +000080 self.raise_catch(OverflowError, "OverflowError")
81 x = 1
82 for dummy in range(128):
83 x += x # this simply shouldn't blow up
Guido van Rossum3bead091992-01-27 17:00:37 +000084
Georg Brandlcdcede62006-05-30 08:47:19 +000085 self.raise_catch(RuntimeError, "RuntimeError")
Guido van Rossum3bead091992-01-27 17:00:37 +000086
Georg Brandlcdcede62006-05-30 08:47:19 +000087 self.raise_catch(SyntaxError, "SyntaxError")
88 try: exec '/\n'
89 except SyntaxError: pass
Guido van Rossum3bead091992-01-27 17:00:37 +000090
Georg Brandlcdcede62006-05-30 08:47:19 +000091 self.raise_catch(IndentationError, "IndentationError")
Fred Drake72e48bd2000-09-08 16:32:34 +000092
Georg Brandlcdcede62006-05-30 08:47:19 +000093 self.raise_catch(TabError, "TabError")
94 # can only be tested under -tt, and is the only test for -tt
95 #try: compile("try:\n\t1/0\n \t1/0\nfinally:\n pass\n", '<string>', 'exec')
96 #except TabError: pass
97 #else: self.fail("TabError not raised")
Fred Drake72e48bd2000-09-08 16:32:34 +000098
Georg Brandlcdcede62006-05-30 08:47:19 +000099 self.raise_catch(SystemError, "SystemError")
Fred Drake72e48bd2000-09-08 16:32:34 +0000100
Georg Brandlcdcede62006-05-30 08:47:19 +0000101 self.raise_catch(SystemExit, "SystemExit")
102 self.assertRaises(SystemExit, sys.exit, 0)
Fred Drake85f36392000-07-11 17:53:00 +0000103
Georg Brandlcdcede62006-05-30 08:47:19 +0000104 self.raise_catch(TypeError, "TypeError")
105 try: [] + ()
106 except TypeError: pass
Fred Drake85f36392000-07-11 17:53:00 +0000107
Georg Brandlcdcede62006-05-30 08:47:19 +0000108 self.raise_catch(ValueError, "ValueError")
109 self.assertRaises(ValueError, chr, 10000)
Guido van Rossum3bead091992-01-27 17:00:37 +0000110
Georg Brandlcdcede62006-05-30 08:47:19 +0000111 self.raise_catch(ZeroDivisionError, "ZeroDivisionError")
Ezio Melotti1f517e12010-02-02 17:34:37 +0000112 try: x = 1 // 0
Georg Brandlcdcede62006-05-30 08:47:19 +0000113 except ZeroDivisionError: pass
Guido van Rossum3bead091992-01-27 17:00:37 +0000114
Georg Brandlcdcede62006-05-30 08:47:19 +0000115 self.raise_catch(Exception, "Exception")
Ezio Melotti1f517e12010-02-02 17:34:37 +0000116 try: x = 1 // 0
Georg Brandlcdcede62006-05-30 08:47:19 +0000117 except Exception, e: pass
Guido van Rossum3bead091992-01-27 17:00:37 +0000118
Georg Brandlcdcede62006-05-30 08:47:19 +0000119 def testSyntaxErrorMessage(self):
Neal Norwitze152aab2006-06-02 04:45:53 +0000120 # make sure the right exception message is raised for each of
121 # these code fragments
Guido van Rossum3bead091992-01-27 17:00:37 +0000122
Georg Brandlcdcede62006-05-30 08:47:19 +0000123 def ckmsg(src, msg):
124 try:
125 compile(src, '<fragment>', 'exec')
126 except SyntaxError, e:
127 if e.msg != msg:
128 self.fail("expected %s, got %s" % (msg, e.msg))
129 else:
130 self.fail("failed to get expected SyntaxError")
Guido van Rossum3bead091992-01-27 17:00:37 +0000131
Georg Brandlcdcede62006-05-30 08:47:19 +0000132 s = '''while 1:
133 try:
134 pass
135 finally:
136 continue'''
Barry Warsaw992cb8a2000-05-25 23:16:54 +0000137
Georg Brandlcdcede62006-05-30 08:47:19 +0000138 if not sys.platform.startswith('java'):
139 ckmsg(s, "'continue' not supported inside 'finally' clause")
Jeremy Hyltonede049b2001-09-26 20:01:13 +0000140
Georg Brandlcdcede62006-05-30 08:47:19 +0000141 s = '''if 1:
142 try:
143 continue
144 except:
145 pass'''
Jeremy Hyltonede049b2001-09-26 20:01:13 +0000146
Georg Brandlcdcede62006-05-30 08:47:19 +0000147 ckmsg(s, "'continue' not properly in loop")
148 ckmsg("continue\n", "'continue' not properly in loop")
Jeremy Hyltonede049b2001-09-26 20:01:13 +0000149
Georg Brandlcdcede62006-05-30 08:47:19 +0000150 def testSettingException(self):
Neal Norwitze152aab2006-06-02 04:45:53 +0000151 # test that setting an exception at the C level works even if the
152 # exception object can't be constructed.
Finn Bockaa3dc452001-12-08 10:15:48 +0000153
Georg Brandlcdcede62006-05-30 08:47:19 +0000154 class BadException:
155 def __init__(self_):
156 raise RuntimeError, "can't instantiate BadException"
Jeremy Hyltonede049b2001-09-26 20:01:13 +0000157
Georg Brandlcdcede62006-05-30 08:47:19 +0000158 def test_capi1():
159 import _testcapi
160 try:
161 _testcapi.raise_exception(BadException, 1)
162 except TypeError, err:
163 exc, err, tb = sys.exc_info()
164 co = tb.tb_frame.f_code
165 self.assertEquals(co.co_name, "test_capi1")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000166 self.assertTrue(co.co_filename.endswith('test_exceptions'+os.extsep+'py'))
Georg Brandlcdcede62006-05-30 08:47:19 +0000167 else:
168 self.fail("Expected exception")
Richard Jones7b9558d2006-05-27 12:29:24 +0000169
Georg Brandlcdcede62006-05-30 08:47:19 +0000170 def test_capi2():
171 import _testcapi
172 try:
173 _testcapi.raise_exception(BadException, 0)
174 except RuntimeError, err:
175 exc, err, tb = sys.exc_info()
176 co = tb.tb_frame.f_code
177 self.assertEquals(co.co_name, "__init__")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000178 self.assertTrue(co.co_filename.endswith('test_exceptions'+os.extsep+'py'))
Georg Brandlcdcede62006-05-30 08:47:19 +0000179 co2 = tb.tb_frame.f_back.f_code
180 self.assertEquals(co2.co_name, "test_capi2")
181 else:
182 self.fail("Expected exception")
Richard Jones7b9558d2006-05-27 12:29:24 +0000183
Georg Brandlcdcede62006-05-30 08:47:19 +0000184 if not sys.platform.startswith('java'):
185 test_capi1()
186 test_capi2()
Georg Brandl05f97bf2006-05-30 07:13:29 +0000187
Thomas Hellerdf08f0b2006-10-27 18:31:36 +0000188 def test_WindowsError(self):
189 try:
190 WindowsError
191 except NameError:
192 pass
193 else:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000194 self.assertEqual(str(WindowsError(1001)),
Thomas Hellerdf08f0b2006-10-27 18:31:36 +0000195 "1001")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000196 self.assertEqual(str(WindowsError(1001, "message")),
Thomas Hellerdf08f0b2006-10-27 18:31:36 +0000197 "[Error 1001] message")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000198 self.assertEqual(WindowsError(1001, "message").errno, 22)
199 self.assertEqual(WindowsError(1001, "message").winerror, 1001)
Thomas Hellerdf08f0b2006-10-27 18:31:36 +0000200
Ezio Melotti1f517e12010-02-02 17:34:37 +0000201 @ignore_deprecation_warnings
Georg Brandlcdcede62006-05-30 08:47:19 +0000202 def testAttributes(self):
Neal Norwitze152aab2006-06-02 04:45:53 +0000203 # test that exception attributes are happy
Tim Petersdd55b0a2006-05-30 23:28:02 +0000204
Georg Brandlcdcede62006-05-30 08:47:19 +0000205 exceptionList = [
Georg Brandle08940e2006-06-01 13:00:49 +0000206 (BaseException, (), {'message' : '', 'args' : ()}),
207 (BaseException, (1, ), {'message' : 1, 'args' : (1,)}),
208 (BaseException, ('foo',),
209 {'message' : 'foo', 'args' : ('foo',)}),
210 (BaseException, ('foo', 1),
211 {'message' : '', 'args' : ('foo', 1)}),
212 (SystemExit, ('foo',),
213 {'message' : 'foo', 'args' : ('foo',), 'code' : 'foo'}),
214 (IOError, ('foo',),
Georg Brandl3267d282006-09-30 09:03:42 +0000215 {'message' : 'foo', 'args' : ('foo',), 'filename' : None,
216 'errno' : None, 'strerror' : None}),
Georg Brandle08940e2006-06-01 13:00:49 +0000217 (IOError, ('foo', 'bar'),
Georg Brandl3267d282006-09-30 09:03:42 +0000218 {'message' : '', 'args' : ('foo', 'bar'), 'filename' : None,
219 'errno' : 'foo', 'strerror' : 'bar'}),
Georg Brandle08940e2006-06-01 13:00:49 +0000220 (IOError, ('foo', 'bar', 'baz'),
Georg Brandl3267d282006-09-30 09:03:42 +0000221 {'message' : '', 'args' : ('foo', 'bar'), 'filename' : 'baz',
222 'errno' : 'foo', 'strerror' : 'bar'}),
223 (IOError, ('foo', 'bar', 'baz', 'quux'),
224 {'message' : '', 'args' : ('foo', 'bar', 'baz', 'quux')}),
Georg Brandle08940e2006-06-01 13:00:49 +0000225 (EnvironmentError, ('errnoStr', 'strErrorStr', 'filenameStr'),
226 {'message' : '', 'args' : ('errnoStr', 'strErrorStr'),
227 'strerror' : 'strErrorStr', 'errno' : 'errnoStr',
228 'filename' : 'filenameStr'}),
229 (EnvironmentError, (1, 'strErrorStr', 'filenameStr'),
230 {'message' : '', 'args' : (1, 'strErrorStr'), 'errno' : 1,
231 'strerror' : 'strErrorStr', 'filename' : 'filenameStr'}),
Brett Cannonf8267df2007-02-28 18:15:00 +0000232 (SyntaxError, (), {'message' : '', 'msg' : None, 'text' : None,
233 'filename' : None, 'lineno' : None, 'offset' : None,
234 'print_file_and_line' : None}),
Georg Brandle08940e2006-06-01 13:00:49 +0000235 (SyntaxError, ('msgStr',),
236 {'message' : 'msgStr', 'args' : ('msgStr',), 'text' : None,
237 'print_file_and_line' : None, 'msg' : 'msgStr',
238 'filename' : None, 'lineno' : None, 'offset' : None}),
239 (SyntaxError, ('msgStr', ('filenameStr', 'linenoStr', 'offsetStr',
240 'textStr')),
241 {'message' : '', 'offset' : 'offsetStr', 'text' : 'textStr',
242 'args' : ('msgStr', ('filenameStr', 'linenoStr',
243 'offsetStr', 'textStr')),
244 'print_file_and_line' : None, 'msg' : 'msgStr',
245 'filename' : 'filenameStr', 'lineno' : 'linenoStr'}),
246 (SyntaxError, ('msgStr', 'filenameStr', 'linenoStr', 'offsetStr',
247 'textStr', 'print_file_and_lineStr'),
248 {'message' : '', 'text' : None,
249 'args' : ('msgStr', 'filenameStr', 'linenoStr', 'offsetStr',
250 'textStr', 'print_file_and_lineStr'),
251 'print_file_and_line' : None, 'msg' : 'msgStr',
252 'filename' : None, 'lineno' : None, 'offset' : None}),
253 (UnicodeError, (), {'message' : '', 'args' : (),}),
Georg Brandl38f62372006-09-06 06:50:05 +0000254 (UnicodeEncodeError, ('ascii', u'a', 0, 1, 'ordinal not in range'),
255 {'message' : '', 'args' : ('ascii', u'a', 0, 1,
256 'ordinal not in range'),
257 'encoding' : 'ascii', 'object' : u'a',
258 'start' : 0, 'reason' : 'ordinal not in range'}),
259 (UnicodeDecodeError, ('ascii', '\xff', 0, 1, 'ordinal not in range'),
Georg Brandle08940e2006-06-01 13:00:49 +0000260 {'message' : '', 'args' : ('ascii', '\xff', 0, 1,
Georg Brandl38f62372006-09-06 06:50:05 +0000261 'ordinal not in range'),
Georg Brandle08940e2006-06-01 13:00:49 +0000262 'encoding' : 'ascii', 'object' : '\xff',
Georg Brandl38f62372006-09-06 06:50:05 +0000263 'start' : 0, 'reason' : 'ordinal not in range'}),
Georg Brandle08940e2006-06-01 13:00:49 +0000264 (UnicodeTranslateError, (u"\u3042", 0, 1, "ouch"),
265 {'message' : '', 'args' : (u'\u3042', 0, 1, 'ouch'),
266 'object' : u'\u3042', 'reason' : 'ouch',
267 'start' : 0, 'end' : 1}),
268 ]
Georg Brandlcdcede62006-05-30 08:47:19 +0000269 try:
270 exceptionList.append(
Georg Brandle08940e2006-06-01 13:00:49 +0000271 (WindowsError, (1, 'strErrorStr', 'filenameStr'),
272 {'message' : '', 'args' : (1, 'strErrorStr'),
273 'strerror' : 'strErrorStr', 'winerror' : 1,
274 'errno' : 22, 'filename' : 'filenameStr'})
275 )
Tim Peters80dc76e2006-06-07 06:57:51 +0000276 except NameError:
277 pass
Georg Brandlcdcede62006-05-30 08:47:19 +0000278
Ezio Melotti1f517e12010-02-02 17:34:37 +0000279 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
Ezio Melotti1f517e12010-02-02 17:34:37 +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
Ezio Melotti1f517e12010-02-02 17:34:37 +0000334 @ignore_deprecation_warnings
Georg Brandl0674d3f2009-09-16 20:30:09 +0000335 def testPickleMessageAttribute(self):
336 # Pickling with message attribute must work, as well.
337 e = Exception("foo")
338 f = Exception("foo")
339 f.message = "bar"
340 for p in pickle, cPickle:
341 ep = p.loads(p.dumps(e))
Ezio Melotti1f517e12010-02-02 17:34:37 +0000342 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
Ezio Melotti1f517e12010-02-02 17:34:37 +0000346 @ignore_deprecation_warnings
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)
Ezio Melotti1f517e12010-02-02 17:34:37 +0000353 self.assertEqual(exc.args[:], args)
Brett Cannone05e6b02007-01-29 04:41:44 +0000354
Georg Brandlcdcede62006-05-30 08:47:19 +0000355 def testKeywordArgs(self):
Neal Norwitze152aab2006-06-02 04:45:53 +0000356 # test that builtin exception don't take keyword args,
357 # but user-defined subclasses can if they want
Georg Brandlcdcede62006-05-30 08:47:19 +0000358 self.assertRaises(TypeError, BaseException, a=1)
Georg Brandle08940e2006-06-01 13:00:49 +0000359
Georg Brandlcdcede62006-05-30 08:47:19 +0000360 class DerivedException(BaseException):
361 def __init__(self, fancy_arg):
362 BaseException.__init__(self)
363 self.fancy_arg = fancy_arg
364
365 x = DerivedException(fancy_arg=42)
366 self.assertEquals(x.fancy_arg, 42)
367
Armin Rigo53c1692f2006-06-21 21:58:50 +0000368 def testInfiniteRecursion(self):
369 def f():
370 return f()
371 self.assertRaises(RuntimeError, f)
372
373 def g():
374 try:
375 return g()
376 except ValueError:
377 return -1
Antoine Pitrou0668c622008-08-26 22:42:08 +0000378
379 # The test prints an unraisable recursion error when
380 # doing "except ValueError", this is because subclass
381 # checking has recursion checking too.
382 with captured_output("stderr"):
383 try:
384 g()
385 except RuntimeError:
386 pass
387 except:
388 self.fail("Should have raised KeyError")
389 else:
390 self.fail("Should have raised KeyError")
Armin Rigo53c1692f2006-06-21 21:58:50 +0000391
Brett Cannonca2ca792006-09-09 07:11:46 +0000392 def testUnicodeStrUsage(self):
393 # Make sure both instances and classes have a str and unicode
394 # representation.
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000395 self.assertTrue(str(Exception))
396 self.assertTrue(unicode(Exception))
397 self.assertTrue(str(Exception('a')))
398 self.assertTrue(unicode(Exception(u'a')))
399 self.assertTrue(unicode(Exception(u'\xe1')))
Brett Cannonca2ca792006-09-09 07:11:46 +0000400
Eric Smith2d9856d2010-02-24 14:15:36 +0000401 def testUnicodeChangeAttributes(self):
402 # See issue 7309. This was a crasher.
403
404 u = UnicodeEncodeError('baz', u'xxxxx', 1, 5, 'foo')
405 self.assertEqual(str(u), "'baz' codec can't encode characters in position 1-4: foo")
406 u.end = 2
407 self.assertEqual(str(u), "'baz' codec can't encode character u'\\x78' in position 1: foo")
408 u.end = 5
409 u.reason = 0x345345345345345345
410 self.assertEqual(str(u), "'baz' codec can't encode characters in position 1-4: 965230951443685724997")
411 u.encoding = 4000
412 self.assertEqual(str(u), "'4000' codec can't encode characters in position 1-4: 965230951443685724997")
413 u.start = 1000
414 self.assertEqual(str(u), "'4000' codec can't encode characters in position 1000-4: 965230951443685724997")
415
416 u = UnicodeDecodeError('baz', 'xxxxx', 1, 5, 'foo')
417 self.assertEqual(str(u), "'baz' codec can't decode bytes in position 1-4: foo")
418 u.end = 2
419 self.assertEqual(str(u), "'baz' codec can't decode byte 0x78 in position 1: foo")
420 u.end = 5
421 u.reason = 0x345345345345345345
422 self.assertEqual(str(u), "'baz' codec can't decode bytes in position 1-4: 965230951443685724997")
423 u.encoding = 4000
424 self.assertEqual(str(u), "'4000' codec can't decode bytes in position 1-4: 965230951443685724997")
425 u.start = 1000
426 self.assertEqual(str(u), "'4000' codec can't decode bytes in position 1000-4: 965230951443685724997")
427
428 u = UnicodeTranslateError(u'xxxx', 1, 5, 'foo')
429 self.assertEqual(str(u), "can't translate characters in position 1-4: foo")
430 u.end = 2
431 self.assertEqual(str(u), "can't translate character u'\\x78' in position 1: foo")
432 u.end = 5
433 u.reason = 0x345345345345345345
434 self.assertEqual(str(u), "can't translate characters in position 1-4: 965230951443685724997")
435 u.start = 1000
436 self.assertEqual(str(u), "can't translate characters in position 1000-4: 965230951443685724997")
437
Amaury Forgeot d'Arc246daed2008-07-31 00:42:16 +0000438 def test_badisinstance(self):
439 # Bug #2542: if issubclass(e, MyException) raises an exception,
440 # it should be ignored
441 class Meta(type):
442 def __subclasscheck__(cls, subclass):
443 raise ValueError()
444
445 class MyException(Exception):
446 __metaclass__ = Meta
447 pass
448
449 with captured_output("stderr") as stderr:
450 try:
451 raise KeyError()
452 except MyException, e:
453 self.fail("exception should not be a MyException")
454 except KeyError:
455 pass
456 except:
Antoine Pitrou0668c622008-08-26 22:42:08 +0000457 self.fail("Should have raised KeyError")
Amaury Forgeot d'Arc246daed2008-07-31 00:42:16 +0000458 else:
Antoine Pitrou0668c622008-08-26 22:42:08 +0000459 self.fail("Should have raised KeyError")
460
461 with captured_output("stderr") as stderr:
462 def g():
463 try:
464 return g()
465 except RuntimeError:
466 return sys.exc_info()
467 e, v, tb = g()
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000468 self.assertTrue(e is RuntimeError, e)
Ezio Melottiaa980582010-01-23 23:04:36 +0000469 self.assertIn("maximum recursion depth exceeded", str(v))
Antoine Pitrou0668c622008-08-26 22:42:08 +0000470
Brett Cannonca2ca792006-09-09 07:11:46 +0000471
Ezio Melottif84caf42009-12-24 22:25:17 +0000472
473# Helper class used by TestSameStrAndUnicodeMsg
474class ExcWithOverriddenStr(Exception):
475 """Subclass of Exception that accepts a keyword 'msg' arg that is
476 returned by __str__. 'msg' won't be included in self.args"""
477 def __init__(self, *args, **kwargs):
478 self.msg = kwargs.pop('msg') # msg should always be present
479 super(ExcWithOverriddenStr, self).__init__(*args, **kwargs)
480 def __str__(self):
481 return self.msg
482
483
484class TestSameStrAndUnicodeMsg(unittest.TestCase):
485 """unicode(err) should return the same message of str(err). See #6108"""
486
487 def check_same_msg(self, exc, msg):
488 """Helper function that checks if str(exc) == unicode(exc) == msg"""
489 self.assertEqual(str(exc), msg)
490 self.assertEqual(str(exc), unicode(exc))
491
492 def test_builtin_exceptions(self):
493 """Check same msg for built-in exceptions"""
494 # These exceptions implement a __str__ method that uses the args
495 # to create a better error message. unicode(e) should return the same
496 # message.
497 exceptions = [
498 SyntaxError('invalid syntax', ('<string>', 1, 3, '2+*3')),
499 IOError(2, 'No such file or directory'),
500 KeyError('both should have the same quotes'),
501 UnicodeDecodeError('ascii', '\xc3\xa0', 0, 1,
502 'ordinal not in range(128)'),
503 UnicodeEncodeError('ascii', u'\u1234', 0, 1,
504 'ordinal not in range(128)')
505 ]
506 for exception in exceptions:
507 self.assertEqual(str(exception), unicode(exception))
508
509 def test_0_args(self):
510 """Check same msg for Exception with 0 args"""
511 # str() and unicode() on an Exception with no args should return an
512 # empty string
513 self.check_same_msg(Exception(), '')
514
515 def test_0_args_with_overridden___str__(self):
516 """Check same msg for exceptions with 0 args and overridden __str__"""
517 # str() and unicode() on an exception with overridden __str__ that
518 # returns an ascii-only string should return the same string
519 for msg in ('foo', u'foo'):
520 self.check_same_msg(ExcWithOverriddenStr(msg=msg), msg)
521
522 # if __str__ returns a non-ascii unicode string str() should fail
523 # but unicode() should return the unicode string
524 e = ExcWithOverriddenStr(msg=u'f\xf6\xf6') # no args
525 self.assertRaises(UnicodeEncodeError, str, e)
526 self.assertEqual(unicode(e), u'f\xf6\xf6')
527
528 def test_1_arg(self):
529 """Check same msg for Exceptions with 1 arg"""
530 for arg in ('foo', u'foo'):
531 self.check_same_msg(Exception(arg), arg)
532
533 # if __str__ is not overridden and self.args[0] is a non-ascii unicode
534 # string, str() should try to return str(self.args[0]) and fail.
535 # unicode() should return unicode(self.args[0]) and succeed.
536 e = Exception(u'f\xf6\xf6')
537 self.assertRaises(UnicodeEncodeError, str, e)
538 self.assertEqual(unicode(e), u'f\xf6\xf6')
539
540 def test_1_arg_with_overridden___str__(self):
541 """Check same msg for exceptions with overridden __str__ and 1 arg"""
542 # when __str__ is overridden and __unicode__ is not implemented
543 # unicode(e) returns the same as unicode(e.__str__()).
544 for msg in ('foo', u'foo'):
545 self.check_same_msg(ExcWithOverriddenStr('arg', msg=msg), msg)
546
547 # if __str__ returns a non-ascii unicode string, str() should fail
548 # but unicode() should succeed.
549 e = ExcWithOverriddenStr('arg', msg=u'f\xf6\xf6') # 1 arg
550 self.assertRaises(UnicodeEncodeError, str, e)
551 self.assertEqual(unicode(e), u'f\xf6\xf6')
552
553 def test_many_args(self):
554 """Check same msg for Exceptions with many args"""
555 argslist = [
556 (3, 'foo'),
557 (1, u'foo', 'bar'),
558 (4, u'f\xf6\xf6', u'bar', 'baz')
559 ]
560 # both str() and unicode() should return a repr() of the args
561 for args in argslist:
562 self.check_same_msg(Exception(*args), repr(args))
563
564 def test_many_args_with_overridden___str__(self):
565 """Check same msg for exceptions with overridden __str__ and many args"""
566 # if __str__ returns an ascii string / ascii unicode string
567 # both str() and unicode() should succeed
568 for msg in ('foo', u'foo'):
569 e = ExcWithOverriddenStr('arg1', u'arg2', u'f\xf6\xf6', msg=msg)
570 self.check_same_msg(e, msg)
571
572 # if __str__ returns a non-ascii unicode string, str() should fail
573 # but unicode() should succeed
574 e = ExcWithOverriddenStr('arg1', u'f\xf6\xf6', u'arg3', # 3 args
575 msg=u'f\xf6\xf6')
576 self.assertRaises(UnicodeEncodeError, str, e)
577 self.assertEqual(unicode(e), u'f\xf6\xf6')
578
Georg Brandl740cdc32009-12-28 08:34:58 +0000579 def test_exception_with_doc(self):
580 import _testcapi
581 doc2 = "This is a test docstring."
582 doc4 = "This is another test docstring."
583
584 self.assertRaises(SystemError, _testcapi.make_exception_with_doc,
585 "error1")
586
587 # test basic usage of PyErr_NewException
588 error1 = _testcapi.make_exception_with_doc("_testcapi.error1")
589 self.assertIs(type(error1), type)
590 self.assertTrue(issubclass(error1, Exception))
591 self.assertIsNone(error1.__doc__)
592
593 # test with given docstring
594 error2 = _testcapi.make_exception_with_doc("_testcapi.error2", doc2)
595 self.assertEqual(error2.__doc__, doc2)
596
597 # test with explicit base (without docstring)
598 error3 = _testcapi.make_exception_with_doc("_testcapi.error3",
599 base=error2)
600 self.assertTrue(issubclass(error3, error2))
601
602 # test with explicit base tuple
603 class C(object):
604 pass
605 error4 = _testcapi.make_exception_with_doc("_testcapi.error4", doc4,
606 (error3, C))
607 self.assertTrue(issubclass(error4, error3))
608 self.assertTrue(issubclass(error4, C))
609 self.assertEqual(error4.__doc__, doc4)
610
611 # test with explicit dictionary
612 error5 = _testcapi.make_exception_with_doc("_testcapi.error5", "",
613 error4, {'a': 1})
614 self.assertTrue(issubclass(error5, error4))
615 self.assertEqual(error5.a, 1)
616 self.assertEqual(error5.__doc__, "")
617
Ezio Melottif84caf42009-12-24 22:25:17 +0000618
Georg Brandlcdcede62006-05-30 08:47:19 +0000619def test_main():
Ezio Melottif84caf42009-12-24 22:25:17 +0000620 run_unittest(ExceptionTests, TestSameStrAndUnicodeMsg)
Georg Brandlcdcede62006-05-30 08:47:19 +0000621
622if __name__ == '__main__':
623 test_main()