blob: 7b63718e564ea6ea309528c3f520002b1bc8dfde [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 Kumaran3ddc4352010-01-08 18:41:40 +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:
Senthil Kumaran3ddc4352010-01-08 18:41:40 +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")
Senthil Kumaran3ddc4352010-01-08 18:41:40 +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")
Senthil Kumaran3ddc4352010-01-08 18:41:40 +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
Senthil Kumaran3ddc4352010-01-08 18:41:40 +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
Senthil Kumaran3ddc4352010-01-08 18:41:40 +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
Senthil Kumaran3ddc4352010-01-08 18:41:40 +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
Senthil Kumaran3ddc4352010-01-08 18:41:40 +0000333 @ignore_deprecation_warnings
Georg Brandl0674d3f2009-09-16 20:30:09 +0000334 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 Kumaran3ddc4352010-01-08 18:41:40 +0000341 self.assertEqual(ep.message, "foo")
Georg Brandl0674d3f2009-09-16 20:30:09 +0000342 fp = p.loads(p.dumps(f))
343 self.assertEqual(fp.message, "bar")
344
Brett Cannone05e6b02007-01-29 04:41:44 +0000345 def testSlicing(self):
346 # Test that you can slice an exception directly instead of requiring
347 # going through the 'args' attribute.
348 args = (1, 2, 3)
349 exc = BaseException(*args)
Senthil Kumaran3ddc4352010-01-08 18:41:40 +0000350 self.assertEqual(exc.args[:], args)
351 with warnings.catch_warnings():
352 # Silence Py3k warning
353 warnings.filterwarnings("ignore", "__getslice__ not supported for "
354 "exception classes", DeprecationWarning)
355 self.assertEqual(exc[:], args)
Brett Cannone05e6b02007-01-29 04:41:44 +0000356
Georg Brandlcdcede62006-05-30 08:47:19 +0000357 def testKeywordArgs(self):
Neal Norwitze152aab2006-06-02 04:45:53 +0000358 # test that builtin exception don't take keyword args,
359 # but user-defined subclasses can if they want
Georg Brandlcdcede62006-05-30 08:47:19 +0000360 self.assertRaises(TypeError, BaseException, a=1)
Georg Brandle08940e2006-06-01 13:00:49 +0000361
Georg Brandlcdcede62006-05-30 08:47:19 +0000362 class DerivedException(BaseException):
363 def __init__(self, fancy_arg):
364 BaseException.__init__(self)
365 self.fancy_arg = fancy_arg
366
367 x = DerivedException(fancy_arg=42)
368 self.assertEquals(x.fancy_arg, 42)
369
Armin Rigo53c1692f2006-06-21 21:58:50 +0000370 def testInfiniteRecursion(self):
371 def f():
372 return f()
373 self.assertRaises(RuntimeError, f)
374
375 def g():
376 try:
377 return g()
378 except ValueError:
379 return -1
Antoine Pitrou0668c622008-08-26 22:42:08 +0000380
381 # The test prints an unraisable recursion error when
382 # doing "except ValueError", this is because subclass
383 # checking has recursion checking too.
384 with captured_output("stderr"):
385 try:
386 g()
387 except RuntimeError:
388 pass
389 except:
390 self.fail("Should have raised KeyError")
391 else:
392 self.fail("Should have raised KeyError")
Armin Rigo53c1692f2006-06-21 21:58:50 +0000393
Brett Cannonca2ca792006-09-09 07:11:46 +0000394 def testUnicodeStrUsage(self):
395 # Make sure both instances and classes have a str and unicode
396 # representation.
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000397 self.assertTrue(str(Exception))
398 self.assertTrue(unicode(Exception))
399 self.assertTrue(str(Exception('a')))
400 self.assertTrue(unicode(Exception(u'a')))
401 self.assertTrue(unicode(Exception(u'\xe1')))
Brett Cannonca2ca792006-09-09 07:11:46 +0000402
Amaury Forgeot d'Arc246daed2008-07-31 00:42:16 +0000403 def test_badisinstance(self):
404 # Bug #2542: if issubclass(e, MyException) raises an exception,
405 # it should be ignored
406 class Meta(type):
407 def __subclasscheck__(cls, subclass):
408 raise ValueError()
409
410 class MyException(Exception):
411 __metaclass__ = Meta
412 pass
413
414 with captured_output("stderr") as stderr:
415 try:
416 raise KeyError()
417 except MyException, e:
418 self.fail("exception should not be a MyException")
419 except KeyError:
420 pass
421 except:
Antoine Pitrou0668c622008-08-26 22:42:08 +0000422 self.fail("Should have raised KeyError")
Amaury Forgeot d'Arc246daed2008-07-31 00:42:16 +0000423 else:
Antoine Pitrou0668c622008-08-26 22:42:08 +0000424 self.fail("Should have raised KeyError")
425
426 with captured_output("stderr") as stderr:
427 def g():
428 try:
429 return g()
430 except RuntimeError:
431 return sys.exc_info()
432 e, v, tb = g()
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000433 self.assertTrue(e is RuntimeError, e)
434 self.assertTrue("maximum recursion depth exceeded" in str(v), v)
Antoine Pitrou0668c622008-08-26 22:42:08 +0000435
Brett Cannonca2ca792006-09-09 07:11:46 +0000436
Ezio Melottif84caf42009-12-24 22:25:17 +0000437
438# Helper class used by TestSameStrAndUnicodeMsg
439class ExcWithOverriddenStr(Exception):
440 """Subclass of Exception that accepts a keyword 'msg' arg that is
441 returned by __str__. 'msg' won't be included in self.args"""
442 def __init__(self, *args, **kwargs):
443 self.msg = kwargs.pop('msg') # msg should always be present
444 super(ExcWithOverriddenStr, self).__init__(*args, **kwargs)
445 def __str__(self):
446 return self.msg
447
448
449class TestSameStrAndUnicodeMsg(unittest.TestCase):
450 """unicode(err) should return the same message of str(err). See #6108"""
451
452 def check_same_msg(self, exc, msg):
453 """Helper function that checks if str(exc) == unicode(exc) == msg"""
454 self.assertEqual(str(exc), msg)
455 self.assertEqual(str(exc), unicode(exc))
456
457 def test_builtin_exceptions(self):
458 """Check same msg for built-in exceptions"""
459 # These exceptions implement a __str__ method that uses the args
460 # to create a better error message. unicode(e) should return the same
461 # message.
462 exceptions = [
463 SyntaxError('invalid syntax', ('<string>', 1, 3, '2+*3')),
464 IOError(2, 'No such file or directory'),
465 KeyError('both should have the same quotes'),
466 UnicodeDecodeError('ascii', '\xc3\xa0', 0, 1,
467 'ordinal not in range(128)'),
468 UnicodeEncodeError('ascii', u'\u1234', 0, 1,
469 'ordinal not in range(128)')
470 ]
471 for exception in exceptions:
472 self.assertEqual(str(exception), unicode(exception))
473
474 def test_0_args(self):
475 """Check same msg for Exception with 0 args"""
476 # str() and unicode() on an Exception with no args should return an
477 # empty string
478 self.check_same_msg(Exception(), '')
479
480 def test_0_args_with_overridden___str__(self):
481 """Check same msg for exceptions with 0 args and overridden __str__"""
482 # str() and unicode() on an exception with overridden __str__ that
483 # returns an ascii-only string should return the same string
484 for msg in ('foo', u'foo'):
485 self.check_same_msg(ExcWithOverriddenStr(msg=msg), msg)
486
487 # if __str__ returns a non-ascii unicode string str() should fail
488 # but unicode() should return the unicode string
489 e = ExcWithOverriddenStr(msg=u'f\xf6\xf6') # no args
490 self.assertRaises(UnicodeEncodeError, str, e)
491 self.assertEqual(unicode(e), u'f\xf6\xf6')
492
493 def test_1_arg(self):
494 """Check same msg for Exceptions with 1 arg"""
495 for arg in ('foo', u'foo'):
496 self.check_same_msg(Exception(arg), arg)
497
498 # if __str__ is not overridden and self.args[0] is a non-ascii unicode
499 # string, str() should try to return str(self.args[0]) and fail.
500 # unicode() should return unicode(self.args[0]) and succeed.
501 e = Exception(u'f\xf6\xf6')
502 self.assertRaises(UnicodeEncodeError, str, e)
503 self.assertEqual(unicode(e), u'f\xf6\xf6')
504
505 def test_1_arg_with_overridden___str__(self):
506 """Check same msg for exceptions with overridden __str__ and 1 arg"""
507 # when __str__ is overridden and __unicode__ is not implemented
508 # unicode(e) returns the same as unicode(e.__str__()).
509 for msg in ('foo', u'foo'):
510 self.check_same_msg(ExcWithOverriddenStr('arg', msg=msg), msg)
511
512 # if __str__ returns a non-ascii unicode string, str() should fail
513 # but unicode() should succeed.
514 e = ExcWithOverriddenStr('arg', msg=u'f\xf6\xf6') # 1 arg
515 self.assertRaises(UnicodeEncodeError, str, e)
516 self.assertEqual(unicode(e), u'f\xf6\xf6')
517
518 def test_many_args(self):
519 """Check same msg for Exceptions with many args"""
520 argslist = [
521 (3, 'foo'),
522 (1, u'foo', 'bar'),
523 (4, u'f\xf6\xf6', u'bar', 'baz')
524 ]
525 # both str() and unicode() should return a repr() of the args
526 for args in argslist:
527 self.check_same_msg(Exception(*args), repr(args))
528
529 def test_many_args_with_overridden___str__(self):
530 """Check same msg for exceptions with overridden __str__ and many args"""
531 # if __str__ returns an ascii string / ascii unicode string
532 # both str() and unicode() should succeed
533 for msg in ('foo', u'foo'):
534 e = ExcWithOverriddenStr('arg1', u'arg2', u'f\xf6\xf6', msg=msg)
535 self.check_same_msg(e, msg)
536
537 # if __str__ returns a non-ascii unicode string, str() should fail
538 # but unicode() should succeed
539 e = ExcWithOverriddenStr('arg1', u'f\xf6\xf6', u'arg3', # 3 args
540 msg=u'f\xf6\xf6')
541 self.assertRaises(UnicodeEncodeError, str, e)
542 self.assertEqual(unicode(e), u'f\xf6\xf6')
543
Georg Brandl740cdc32009-12-28 08:34:58 +0000544 def test_exception_with_doc(self):
545 import _testcapi
546 doc2 = "This is a test docstring."
547 doc4 = "This is another test docstring."
548
549 self.assertRaises(SystemError, _testcapi.make_exception_with_doc,
550 "error1")
551
552 # test basic usage of PyErr_NewException
553 error1 = _testcapi.make_exception_with_doc("_testcapi.error1")
554 self.assertIs(type(error1), type)
555 self.assertTrue(issubclass(error1, Exception))
556 self.assertIsNone(error1.__doc__)
557
558 # test with given docstring
559 error2 = _testcapi.make_exception_with_doc("_testcapi.error2", doc2)
560 self.assertEqual(error2.__doc__, doc2)
561
562 # test with explicit base (without docstring)
563 error3 = _testcapi.make_exception_with_doc("_testcapi.error3",
564 base=error2)
565 self.assertTrue(issubclass(error3, error2))
566
567 # test with explicit base tuple
568 class C(object):
569 pass
570 error4 = _testcapi.make_exception_with_doc("_testcapi.error4", doc4,
571 (error3, C))
572 self.assertTrue(issubclass(error4, error3))
573 self.assertTrue(issubclass(error4, C))
574 self.assertEqual(error4.__doc__, doc4)
575
576 # test with explicit dictionary
577 error5 = _testcapi.make_exception_with_doc("_testcapi.error5", "",
578 error4, {'a': 1})
579 self.assertTrue(issubclass(error5, error4))
580 self.assertEqual(error5.a, 1)
581 self.assertEqual(error5.__doc__, "")
582
Ezio Melottif84caf42009-12-24 22:25:17 +0000583
Georg Brandlcdcede62006-05-30 08:47:19 +0000584def test_main():
Ezio Melottif84caf42009-12-24 22:25:17 +0000585 run_unittest(ExceptionTests, TestSameStrAndUnicodeMsg)
Georg Brandlcdcede62006-05-30 08:47:19 +0000586
587if __name__ == '__main__':
588 test_main()