1 # Python test set -- part 5, built-in exceptions
8 from test
.test_support
import (TESTFN
, unlink
, run_unittest
, captured_output
,
9 check_warnings
, cpython_only
)
10 from test
.test_pep352
import ignore_deprecation_warnings
12 # XXX This is not really enough, each *operation* should be tested!
14 class ExceptionTests(unittest
.TestCase
):
17 # Reloading the built-in exceptions module failed prior to Py2.2, while it
18 # should act the same as reloading built-in sys.
20 from imp
import reload
23 except ImportError, e
:
24 self
.fail("reloading exceptions: %s" % e
)
26 def raise_catch(self
, exc
, excname
):
35 self
.assertEquals(buf1
, buf2
)
36 self
.assertEquals(exc
.__name
__, excname
)
38 def testRaising(self
):
39 self
.raise_catch(AttributeError, "AttributeError")
40 self
.assertRaises(AttributeError, getattr, sys
, "undefined_attribute")
42 self
.raise_catch(EOFError, "EOFError")
43 fp
= open(TESTFN
, 'w')
45 fp
= open(TESTFN
, 'r')
58 self
.raise_catch(IOError, "IOError")
59 self
.assertRaises(IOError, open, 'this file does not exist', 'r')
61 self
.raise_catch(ImportError, "ImportError")
62 self
.assertRaises(ImportError, __import__, "undefined_module")
64 self
.raise_catch(IndexError, "IndexError")
66 self
.assertRaises(IndexError, x
.__getitem
__, 10)
68 self
.raise_catch(KeyError, "KeyError")
70 self
.assertRaises(KeyError, x
.__getitem
__, 'key')
72 self
.raise_catch(KeyboardInterrupt, "KeyboardInterrupt")
74 self
.raise_catch(MemoryError, "MemoryError")
76 self
.raise_catch(NameError, "NameError")
77 try: x
= undefined_variable
78 except NameError: pass
80 self
.raise_catch(OverflowError, "OverflowError")
82 for dummy
in range(128):
83 x
+= x
# this simply shouldn't blow up
85 self
.raise_catch(RuntimeError, "RuntimeError")
87 self
.raise_catch(SyntaxError, "SyntaxError")
89 except SyntaxError: pass
91 self
.raise_catch(IndentationError, "IndentationError")
93 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")
99 self
.raise_catch(SystemError, "SystemError")
101 self
.raise_catch(SystemExit, "SystemExit")
102 self
.assertRaises(SystemExit, sys
.exit
, 0)
104 self
.raise_catch(TypeError, "TypeError")
106 except TypeError: pass
108 self
.raise_catch(ValueError, "ValueError")
109 self
.assertRaises(ValueError, chr, 10000)
111 self
.raise_catch(ZeroDivisionError, "ZeroDivisionError")
113 except ZeroDivisionError: pass
115 self
.raise_catch(Exception, "Exception")
117 except Exception, e
: pass
119 def testSyntaxErrorMessage(self
):
120 # make sure the right exception message is raised for each of
121 # these code fragments
125 compile(src
, '<fragment>', 'exec')
126 except SyntaxError, e
:
128 self
.fail("expected %s, got %s" % (msg
, e
.msg
))
130 self
.fail("failed to get expected SyntaxError")
138 if not sys
.platform
.startswith('java'):
139 ckmsg(s
, "'continue' not supported inside 'finally' clause")
147 ckmsg(s
, "'continue' not properly in loop")
148 ckmsg("continue\n", "'continue' not properly in loop")
151 def testSettingException(self
):
152 # test that setting an exception at the C level works even if the
153 # exception object can't be constructed.
157 raise RuntimeError, "can't instantiate BadException"
162 _testcapi
.raise_exception(BadException
, 1)
163 except TypeError, err
:
164 exc
, err
, tb
= sys
.exc_info()
165 co
= tb
.tb_frame
.f_code
166 self
.assertEquals(co
.co_name
, "test_capi1")
167 self
.assertTrue(co
.co_filename
.endswith('test_exceptions'+os
.extsep
+'py'))
169 self
.fail("Expected exception")
174 _testcapi
.raise_exception(BadException
, 0)
175 except RuntimeError, err
:
176 exc
, err
, tb
= sys
.exc_info()
177 co
= tb
.tb_frame
.f_code
178 self
.assertEquals(co
.co_name
, "__init__")
179 self
.assertTrue(co
.co_filename
.endswith('test_exceptions'+os
.extsep
+'py'))
180 co2
= tb
.tb_frame
.f_back
.f_code
181 self
.assertEquals(co2
.co_name
, "test_capi2")
183 self
.fail("Expected exception")
185 if not sys
.platform
.startswith('java'):
189 def test_WindowsError(self
):
195 self
.assertEqual(str(WindowsError(1001)),
197 self
.assertEqual(str(WindowsError(1001, "message")),
198 "[Error 1001] message")
199 self
.assertEqual(WindowsError(1001, "message").errno
, 22)
200 self
.assertEqual(WindowsError(1001, "message").winerror
, 1001)
202 @ignore_deprecation_warnings
203 def testAttributes(self
):
204 # test that exception attributes are happy
207 (BaseException
, (), {'message' : '', 'args' : ()}),
208 (BaseException
, (1, ), {'message' : 1, 'args' : (1,)}),
209 (BaseException
, ('foo',),
210 {'message' : 'foo', 'args' : ('foo',)}),
211 (BaseException
, ('foo', 1),
212 {'message' : '', 'args' : ('foo', 1)}),
213 (SystemExit, ('foo',),
214 {'message' : 'foo', 'args' : ('foo',), 'code' : 'foo'}),
216 {'message' : 'foo', 'args' : ('foo',), 'filename' : None,
217 'errno' : None, 'strerror' : None}),
218 (IOError, ('foo', 'bar'),
219 {'message' : '', 'args' : ('foo', 'bar'), 'filename' : None,
220 'errno' : 'foo', 'strerror' : 'bar'}),
221 (IOError, ('foo', 'bar', 'baz'),
222 {'message' : '', 'args' : ('foo', 'bar'), 'filename' : 'baz',
223 'errno' : 'foo', 'strerror' : 'bar'}),
224 (IOError, ('foo', 'bar', 'baz', 'quux'),
225 {'message' : '', 'args' : ('foo', 'bar', 'baz', 'quux')}),
226 (EnvironmentError, ('errnoStr', 'strErrorStr', 'filenameStr'),
227 {'message' : '', 'args' : ('errnoStr', 'strErrorStr'),
228 'strerror' : 'strErrorStr', 'errno' : 'errnoStr',
229 'filename' : 'filenameStr'}),
230 (EnvironmentError, (1, 'strErrorStr', 'filenameStr'),
231 {'message' : '', 'args' : (1, 'strErrorStr'), 'errno' : 1,
232 'strerror' : 'strErrorStr', 'filename' : 'filenameStr'}),
233 (SyntaxError, (), {'message' : '', 'msg' : None, 'text' : None,
234 'filename' : None, 'lineno' : None, 'offset' : None,
235 'print_file_and_line' : None}),
236 (SyntaxError, ('msgStr',),
237 {'message' : 'msgStr', 'args' : ('msgStr',), 'text' : None,
238 'print_file_and_line' : None, 'msg' : 'msgStr',
239 'filename' : None, 'lineno' : None, 'offset' : None}),
240 (SyntaxError, ('msgStr', ('filenameStr', 'linenoStr', 'offsetStr',
242 {'message' : '', 'offset' : 'offsetStr', 'text' : 'textStr',
243 'args' : ('msgStr', ('filenameStr', 'linenoStr',
244 'offsetStr', 'textStr')),
245 'print_file_and_line' : None, 'msg' : 'msgStr',
246 'filename' : 'filenameStr', 'lineno' : 'linenoStr'}),
247 (SyntaxError, ('msgStr', 'filenameStr', 'linenoStr', 'offsetStr',
248 'textStr', 'print_file_and_lineStr'),
249 {'message' : '', 'text' : None,
250 'args' : ('msgStr', 'filenameStr', 'linenoStr', 'offsetStr',
251 'textStr', 'print_file_and_lineStr'),
252 'print_file_and_line' : None, 'msg' : 'msgStr',
253 'filename' : None, 'lineno' : None, 'offset' : None}),
254 (UnicodeError, (), {'message' : '', 'args' : (),}),
255 (UnicodeEncodeError, ('ascii', u
'a', 0, 1, 'ordinal not in range'),
256 {'message' : '', 'args' : ('ascii', u
'a', 0, 1,
257 'ordinal not in range'),
258 'encoding' : 'ascii', 'object' : u
'a',
259 'start' : 0, 'reason' : 'ordinal not in range'}),
260 (UnicodeDecodeError, ('ascii', '\xff', 0, 1, 'ordinal not in range'),
261 {'message' : '', 'args' : ('ascii', '\xff', 0, 1,
262 'ordinal not in range'),
263 'encoding' : 'ascii', 'object' : '\xff',
264 'start' : 0, 'reason' : 'ordinal not in range'}),
265 (UnicodeTranslateError, (u
"\u3042", 0, 1, "ouch"),
266 {'message' : '', 'args' : (u
'\u3042', 0, 1, 'ouch'),
267 'object' : u
'\u3042', 'reason' : 'ouch',
268 'start' : 0, 'end' : 1}),
271 exceptionList
.append(
272 (WindowsError, (1, 'strErrorStr', 'filenameStr'),
273 {'message' : '', 'args' : (1, 'strErrorStr'),
274 'strerror' : 'strErrorStr', 'winerror' : 1,
275 'errno' : 22, 'filename' : 'filenameStr'})
280 for exc
, args
, expected
in exceptionList
:
283 except BaseException
, e
:
284 if type(e
) is not exc
:
287 self
.assertEquals(type(e
).__module
__, 'exceptions')
288 # Verify no ref leaks in Exc_str()
290 for checkArgName
in expected
:
291 self
.assertEquals(repr(getattr(e
, checkArgName
)),
292 repr(expected
[checkArgName
]),
293 'exception "%s", attribute "%s"' %
294 (repr(e
), checkArgName
))
296 # test for pickling support
297 for p
in pickle
, cPickle
:
298 for protocol
in range(p
.HIGHEST_PROTOCOL
+ 1):
299 new
= p
.loads(p
.dumps(e
, protocol
))
300 for checkArgName
in expected
:
301 got
= repr(getattr(new
, checkArgName
))
302 want
= repr(expected
[checkArgName
])
303 self
.assertEquals(got
, want
,
304 'pickled "%r", attribute "%s"' %
308 def testDeprecatedMessageAttribute(self
):
309 # Accessing BaseException.message and relying on its value set by
310 # BaseException.__init__ triggers a deprecation warning.
311 exc
= BaseException("foo")
312 with
check_warnings(("BaseException.message has been deprecated "
313 "as of Python 2.6", DeprecationWarning)) as w
:
314 self
.assertEqual(exc
.message
, "foo")
315 self
.assertEqual(len(w
.warnings
), 1)
317 def testRegularMessageAttribute(self
):
318 # Accessing BaseException.message after explicitly setting a value
319 # for it does not trigger a deprecation warning.
320 exc
= BaseException("foo")
322 with
check_warnings(quiet
=True) as w
:
323 self
.assertEqual(exc
.message
, "bar")
324 self
.assertEqual(len(w
.warnings
), 0)
325 # Deleting the message is supported, too.
327 with self
.assertRaises(AttributeError):
330 @ignore_deprecation_warnings
331 def testPickleMessageAttribute(self
):
332 # Pickling with message attribute must work, as well.
336 for p
in pickle
, cPickle
:
337 ep
= p
.loads(p
.dumps(e
))
338 self
.assertEqual(ep
.message
, "foo")
339 fp
= p
.loads(p
.dumps(f
))
340 self
.assertEqual(fp
.message
, "bar")
342 @ignore_deprecation_warnings
343 def testSlicing(self
):
344 # Test that you can slice an exception directly instead of requiring
345 # going through the 'args' attribute.
347 exc
= BaseException(*args
)
348 self
.assertEqual(exc
[:], args
)
349 self
.assertEqual(exc
.args
[:], args
)
351 def testKeywordArgs(self
):
352 # test that builtin exception don't take keyword args,
353 # but user-defined subclasses can if they want
354 self
.assertRaises(TypeError, BaseException
, a
=1)
356 class DerivedException(BaseException
):
357 def __init__(self
, fancy_arg
):
358 BaseException
.__init
__(self
)
359 self
.fancy_arg
= fancy_arg
361 x
= DerivedException(fancy_arg
=42)
362 self
.assertEquals(x
.fancy_arg
, 42)
364 def testInfiniteRecursion(self
):
367 self
.assertRaises(RuntimeError, f
)
375 # The test prints an unraisable recursion error when
376 # doing "except ValueError", this is because subclass
377 # checking has recursion checking too.
378 with
captured_output("stderr"):
384 self
.fail("Should have raised KeyError")
386 self
.fail("Should have raised KeyError")
388 def testUnicodeStrUsage(self
):
389 # Make sure both instances and classes have a str and unicode
391 self
.assertTrue(str(Exception))
392 self
.assertTrue(unicode(Exception))
393 self
.assertTrue(str(Exception('a')))
394 self
.assertTrue(unicode(Exception(u
'a')))
395 self
.assertTrue(unicode(Exception(u
'\xe1')))
397 def testUnicodeChangeAttributes(self
):
398 # See issue 7309. This was a crasher.
400 u
= UnicodeEncodeError('baz', u
'xxxxx', 1, 5, 'foo')
401 self
.assertEqual(str(u
), "'baz' codec can't encode characters in position 1-4: foo")
403 self
.assertEqual(str(u
), "'baz' codec can't encode character u'\\x78' in position 1: foo")
405 u
.reason
= 0x345345345345345345
406 self
.assertEqual(str(u
), "'baz' codec can't encode characters in position 1-4: 965230951443685724997")
408 self
.assertEqual(str(u
), "'4000' codec can't encode characters in position 1-4: 965230951443685724997")
410 self
.assertEqual(str(u
), "'4000' codec can't encode characters in position 1000-4: 965230951443685724997")
412 u
= UnicodeDecodeError('baz', 'xxxxx', 1, 5, 'foo')
413 self
.assertEqual(str(u
), "'baz' codec can't decode bytes in position 1-4: foo")
415 self
.assertEqual(str(u
), "'baz' codec can't decode byte 0x78 in position 1: foo")
417 u
.reason
= 0x345345345345345345
418 self
.assertEqual(str(u
), "'baz' codec can't decode bytes in position 1-4: 965230951443685724997")
420 self
.assertEqual(str(u
), "'4000' codec can't decode bytes in position 1-4: 965230951443685724997")
422 self
.assertEqual(str(u
), "'4000' codec can't decode bytes in position 1000-4: 965230951443685724997")
424 u
= UnicodeTranslateError(u
'xxxx', 1, 5, 'foo')
425 self
.assertEqual(str(u
), "can't translate characters in position 1-4: foo")
427 self
.assertEqual(str(u
), "can't translate character u'\\x78' in position 1: foo")
429 u
.reason
= 0x345345345345345345
430 self
.assertEqual(str(u
), "can't translate characters in position 1-4: 965230951443685724997")
432 self
.assertEqual(str(u
), "can't translate characters in position 1000-4: 965230951443685724997")
434 def test_badisinstance(self
):
435 # Bug #2542: if issubclass(e, MyException) raises an exception,
436 # it should be ignored
438 def __subclasscheck__(cls
, subclass
):
441 class MyException(Exception):
445 with
captured_output("stderr") as stderr
:
448 except MyException
, e
:
449 self
.fail("exception should not be a MyException")
453 self
.fail("Should have raised KeyError")
455 self
.fail("Should have raised KeyError")
457 with
captured_output("stderr") as stderr
:
462 return sys
.exc_info()
464 self
.assertTrue(e
is RuntimeError, e
)
465 self
.assertIn("maximum recursion depth exceeded", str(v
))
469 # Helper class used by TestSameStrAndUnicodeMsg
470 class ExcWithOverriddenStr(Exception):
471 """Subclass of Exception that accepts a keyword 'msg' arg that is
472 returned by __str__. 'msg' won't be included in self.args"""
473 def __init__(self
, *args
, **kwargs
):
474 self
.msg
= kwargs
.pop('msg') # msg should always be present
475 super(ExcWithOverriddenStr
, self
).__init
__(*args
, **kwargs
)
480 class TestSameStrAndUnicodeMsg(unittest
.TestCase
):
481 """unicode(err) should return the same message of str(err). See #6108"""
483 def check_same_msg(self
, exc
, msg
):
484 """Helper function that checks if str(exc) == unicode(exc) == msg"""
485 self
.assertEqual(str(exc
), msg
)
486 self
.assertEqual(str(exc
), unicode(exc
))
488 def test_builtin_exceptions(self
):
489 """Check same msg for built-in exceptions"""
490 # These exceptions implement a __str__ method that uses the args
491 # to create a better error message. unicode(e) should return the same
494 SyntaxError('invalid syntax', ('<string>', 1, 3, '2+*3')),
495 IOError(2, 'No such file or directory'),
496 KeyError('both should have the same quotes'),
497 UnicodeDecodeError('ascii', '\xc3\xa0', 0, 1,
498 'ordinal not in range(128)'),
499 UnicodeEncodeError('ascii', u
'\u1234', 0, 1,
500 'ordinal not in range(128)')
502 for exception
in exceptions
:
503 self
.assertEqual(str(exception
), unicode(exception
))
505 def test_0_args(self
):
506 """Check same msg for Exception with 0 args"""
507 # str() and unicode() on an Exception with no args should return an
509 self
.check_same_msg(Exception(), '')
511 def test_0_args_with_overridden___str__(self
):
512 """Check same msg for exceptions with 0 args and overridden __str__"""
513 # str() and unicode() on an exception with overridden __str__ that
514 # returns an ascii-only string should return the same string
515 for msg
in ('foo', u
'foo'):
516 self
.check_same_msg(ExcWithOverriddenStr(msg
=msg
), msg
)
518 # if __str__ returns a non-ascii unicode string str() should fail
519 # but unicode() should return the unicode string
520 e
= ExcWithOverriddenStr(msg
=u
'f\xf6\xf6') # no args
521 self
.assertRaises(UnicodeEncodeError, str, e
)
522 self
.assertEqual(unicode(e
), u
'f\xf6\xf6')
524 def test_1_arg(self
):
525 """Check same msg for Exceptions with 1 arg"""
526 for arg
in ('foo', u
'foo'):
527 self
.check_same_msg(Exception(arg
), arg
)
529 # if __str__ is not overridden and self.args[0] is a non-ascii unicode
530 # string, str() should try to return str(self.args[0]) and fail.
531 # unicode() should return unicode(self.args[0]) and succeed.
532 e
= Exception(u
'f\xf6\xf6')
533 self
.assertRaises(UnicodeEncodeError, str, e
)
534 self
.assertEqual(unicode(e
), u
'f\xf6\xf6')
536 def test_1_arg_with_overridden___str__(self
):
537 """Check same msg for exceptions with overridden __str__ and 1 arg"""
538 # when __str__ is overridden and __unicode__ is not implemented
539 # unicode(e) returns the same as unicode(e.__str__()).
540 for msg
in ('foo', u
'foo'):
541 self
.check_same_msg(ExcWithOverriddenStr('arg', msg
=msg
), msg
)
543 # if __str__ returns a non-ascii unicode string, str() should fail
544 # but unicode() should succeed.
545 e
= ExcWithOverriddenStr('arg', msg
=u
'f\xf6\xf6') # 1 arg
546 self
.assertRaises(UnicodeEncodeError, str, e
)
547 self
.assertEqual(unicode(e
), u
'f\xf6\xf6')
549 def test_many_args(self
):
550 """Check same msg for Exceptions with many args"""
554 (4, u
'f\xf6\xf6', u
'bar', 'baz')
556 # both str() and unicode() should return a repr() of the args
557 for args
in argslist
:
558 self
.check_same_msg(Exception(*args
), repr(args
))
560 def test_many_args_with_overridden___str__(self
):
561 """Check same msg for exceptions with overridden __str__ and many args"""
562 # if __str__ returns an ascii string / ascii unicode string
563 # both str() and unicode() should succeed
564 for msg
in ('foo', u
'foo'):
565 e
= ExcWithOverriddenStr('arg1', u
'arg2', u
'f\xf6\xf6', msg
=msg
)
566 self
.check_same_msg(e
, msg
)
568 # if __str__ returns a non-ascii unicode string, str() should fail
569 # but unicode() should succeed
570 e
= ExcWithOverriddenStr('arg1', u
'f\xf6\xf6', u
'arg3', # 3 args
572 self
.assertRaises(UnicodeEncodeError, str, e
)
573 self
.assertEqual(unicode(e
), u
'f\xf6\xf6')
576 def test_exception_with_doc(self
):
578 doc2
= "This is a test docstring."
579 doc4
= "This is another test docstring."
581 self
.assertRaises(SystemError, _testcapi
.make_exception_with_doc
,
584 # test basic usage of PyErr_NewException
585 error1
= _testcapi
.make_exception_with_doc("_testcapi.error1")
586 self
.assertIs(type(error1
), type)
587 self
.assertTrue(issubclass(error1
, Exception))
588 self
.assertIsNone(error1
.__doc__
)
590 # test with given docstring
591 error2
= _testcapi
.make_exception_with_doc("_testcapi.error2", doc2
)
592 self
.assertEqual(error2
.__doc__
, doc2
)
594 # test with explicit base (without docstring)
595 error3
= _testcapi
.make_exception_with_doc("_testcapi.error3",
597 self
.assertTrue(issubclass(error3
, error2
))
599 # test with explicit base tuple
602 error4
= _testcapi
.make_exception_with_doc("_testcapi.error4", doc4
,
604 self
.assertTrue(issubclass(error4
, error3
))
605 self
.assertTrue(issubclass(error4
, C
))
606 self
.assertEqual(error4
.__doc__
, doc4
)
608 # test with explicit dictionary
609 error5
= _testcapi
.make_exception_with_doc("_testcapi.error5", "",
611 self
.assertTrue(issubclass(error5
, error4
))
612 self
.assertEqual(error5
.a
, 1)
613 self
.assertEqual(error5
.__doc__
, "")
617 run_unittest(ExceptionTests
, TestSameStrAndUnicodeMsg
)
619 if __name__
== '__main__':