1# Python test set -- part 5, built-in exceptions 2 3import copy 4import os 5import sys 6import unittest 7import pickle 8import weakref 9import errno 10 11from test.support import (TESTFN, captured_stderr, check_impl_detail, 12 check_warnings, cpython_only, gc_collect, 13 no_tracing, unlink, import_module, script_helper, 14 SuppressCrashReport) 15from test import support 16 17 18class NaiveException(Exception): 19 def __init__(self, x): 20 self.x = x 21 22class SlottedNaiveException(Exception): 23 __slots__ = ('x',) 24 def __init__(self, x): 25 self.x = x 26 27class BrokenStrException(Exception): 28 def __str__(self): 29 raise Exception("str() is broken") 30 31# XXX This is not really enough, each *operation* should be tested! 32 33class ExceptionTests(unittest.TestCase): 34 35 def raise_catch(self, exc, excname): 36 try: 37 raise exc("spam") 38 except exc as err: 39 buf1 = str(err) 40 try: 41 raise exc("spam") 42 except exc as err: 43 buf2 = str(err) 44 self.assertEqual(buf1, buf2) 45 self.assertEqual(exc.__name__, excname) 46 47 def testRaising(self): 48 self.raise_catch(AttributeError, "AttributeError") 49 self.assertRaises(AttributeError, getattr, sys, "undefined_attribute") 50 51 self.raise_catch(EOFError, "EOFError") 52 fp = open(TESTFN, 'w') 53 fp.close() 54 fp = open(TESTFN, 'r') 55 savestdin = sys.stdin 56 try: 57 try: 58 import marshal 59 marshal.loads(b'') 60 except EOFError: 61 pass 62 finally: 63 sys.stdin = savestdin 64 fp.close() 65 unlink(TESTFN) 66 67 self.raise_catch(OSError, "OSError") 68 self.assertRaises(OSError, open, 'this file does not exist', 'r') 69 70 self.raise_catch(ImportError, "ImportError") 71 self.assertRaises(ImportError, __import__, "undefined_module") 72 73 self.raise_catch(IndexError, "IndexError") 74 x = [] 75 self.assertRaises(IndexError, x.__getitem__, 10) 76 77 self.raise_catch(KeyError, "KeyError") 78 x = {} 79 self.assertRaises(KeyError, x.__getitem__, 'key') 80 81 self.raise_catch(KeyboardInterrupt, "KeyboardInterrupt") 82 83 self.raise_catch(MemoryError, "MemoryError") 84 85 self.raise_catch(NameError, "NameError") 86 try: x = undefined_variable 87 except NameError: pass 88 89 self.raise_catch(OverflowError, "OverflowError") 90 x = 1 91 for dummy in range(128): 92 x += x # this simply shouldn't blow up 93 94 self.raise_catch(RuntimeError, "RuntimeError") 95 self.raise_catch(RecursionError, "RecursionError") 96 97 self.raise_catch(SyntaxError, "SyntaxError") 98 try: exec('/\n') 99 except SyntaxError: pass 100 101 self.raise_catch(IndentationError, "IndentationError") 102 103 self.raise_catch(TabError, "TabError") 104 try: compile("try:\n\t1/0\n \t1/0\nfinally:\n pass\n", 105 '<string>', 'exec') 106 except TabError: pass 107 else: self.fail("TabError not raised") 108 109 self.raise_catch(SystemError, "SystemError") 110 111 self.raise_catch(SystemExit, "SystemExit") 112 self.assertRaises(SystemExit, sys.exit, 0) 113 114 self.raise_catch(TypeError, "TypeError") 115 try: [] + () 116 except TypeError: pass 117 118 self.raise_catch(ValueError, "ValueError") 119 self.assertRaises(ValueError, chr, 17<<16) 120 121 self.raise_catch(ZeroDivisionError, "ZeroDivisionError") 122 try: x = 1/0 123 except ZeroDivisionError: pass 124 125 self.raise_catch(Exception, "Exception") 126 try: x = 1/0 127 except Exception as e: pass 128 129 self.raise_catch(StopAsyncIteration, "StopAsyncIteration") 130 131 def testSyntaxErrorMessage(self): 132 # make sure the right exception message is raised for each of 133 # these code fragments 134 135 def ckmsg(src, msg): 136 try: 137 compile(src, '<fragment>', 'exec') 138 except SyntaxError as e: 139 if e.msg != msg: 140 self.fail("expected %s, got %s" % (msg, e.msg)) 141 else: 142 self.fail("failed to get expected SyntaxError") 143 144 s = '''if 1: 145 try: 146 continue 147 except: 148 pass''' 149 150 ckmsg(s, "'continue' not properly in loop") 151 ckmsg("continue\n", "'continue' not properly in loop") 152 153 def testSyntaxErrorMissingParens(self): 154 def ckmsg(src, msg, exception=SyntaxError): 155 try: 156 compile(src, '<fragment>', 'exec') 157 except exception as e: 158 if e.msg != msg: 159 self.fail("expected %s, got %s" % (msg, e.msg)) 160 else: 161 self.fail("failed to get expected SyntaxError") 162 163 s = '''print "old style"''' 164 ckmsg(s, "Missing parentheses in call to 'print'. " 165 "Did you mean print(\"old style\")?") 166 167 s = '''print "old style",''' 168 ckmsg(s, "Missing parentheses in call to 'print'. " 169 "Did you mean print(\"old style\", end=\" \")?") 170 171 s = '''exec "old style"''' 172 ckmsg(s, "Missing parentheses in call to 'exec'") 173 174 # should not apply to subclasses, see issue #31161 175 s = '''if True:\nprint "No indent"''' 176 ckmsg(s, "expected an indented block", IndentationError) 177 178 s = '''if True:\n print()\n\texec "mixed tabs and spaces"''' 179 ckmsg(s, "inconsistent use of tabs and spaces in indentation", TabError) 180 181 def testSyntaxErrorOffset(self): 182 def check(src, lineno, offset, encoding='utf-8'): 183 with self.assertRaises(SyntaxError) as cm: 184 compile(src, '<fragment>', 'exec') 185 self.assertEqual(cm.exception.lineno, lineno) 186 self.assertEqual(cm.exception.offset, offset) 187 if cm.exception.text is not None: 188 if not isinstance(src, str): 189 src = src.decode(encoding, 'replace') 190 line = src.split('\n')[lineno-1] 191 self.assertEqual(cm.exception.text.rstrip('\n'), line) 192 193 check('def fact(x):\n\treturn x!\n', 2, 10) 194 check('1 +\n', 1, 4) 195 check('def spam():\n print(1)\n print(2)', 3, 10) 196 check('Python = "Python" +', 1, 20) 197 check('Python = "\u1e54\xfd\u0163\u0125\xf2\xf1" +', 1, 20) 198 check(b'# -*- coding: cp1251 -*-\nPython = "\xcf\xb3\xf2\xee\xed" +', 199 2, 19, encoding='cp1251') 200 check(b'Python = "\xcf\xb3\xf2\xee\xed" +', 1, 18) 201 check('x = "a', 1, 7) 202 check('lambda x: x = 2', 1, 1) 203 204 # Errors thrown by compile.c 205 check('class foo:return 1', 1, 11) 206 check('def f():\n continue', 2, 3) 207 check('def f():\n break', 2, 3) 208 check('try:\n pass\nexcept:\n pass\nexcept ValueError:\n pass', 2, 3) 209 210 # Errors thrown by tokenizer.c 211 check('(0x+1)', 1, 3) 212 check('x = 0xI', 1, 6) 213 check('0010 + 2', 1, 4) 214 check('x = 32e-+4', 1, 8) 215 check('x = 0o9', 1, 6) 216 check('\u03b1 = 0xI', 1, 6) 217 check(b'\xce\xb1 = 0xI', 1, 6) 218 check(b'# -*- coding: iso8859-7 -*-\n\xe1 = 0xI', 2, 6, 219 encoding='iso8859-7') 220 221 # Errors thrown by symtable.c 222 check('x = [(yield i) for i in range(3)]', 1, 5) 223 check('def f():\n from _ import *', 1, 1) 224 check('def f(x, x):\n pass', 1, 1) 225 check('def f(x):\n nonlocal x', 2, 3) 226 check('def f(x):\n x = 1\n global x', 3, 3) 227 check('nonlocal x', 1, 1) 228 check('def f():\n global x\n nonlocal x', 2, 3) 229 230 # Errors thrown by ast.c 231 check('for 1 in []: pass', 1, 5) 232 check('def f(*):\n pass', 1, 7) 233 check('[*x for x in xs]', 1, 2) 234 check('def f():\n x, y: int', 2, 3) 235 check('(yield i) = 2', 1, 1) 236 check('foo(x for x in range(10), 100)', 1, 5) 237 check('foo(1=2)', 1, 5) 238 239 # Errors thrown by future.c 240 check('from __future__ import doesnt_exist', 1, 1) 241 check('from __future__ import braces', 1, 1) 242 check('x=1\nfrom __future__ import division', 2, 1) 243 244 245 @cpython_only 246 def testSettingException(self): 247 # test that setting an exception at the C level works even if the 248 # exception object can't be constructed. 249 250 class BadException(Exception): 251 def __init__(self_): 252 raise RuntimeError("can't instantiate BadException") 253 254 class InvalidException: 255 pass 256 257 def test_capi1(): 258 import _testcapi 259 try: 260 _testcapi.raise_exception(BadException, 1) 261 except TypeError as err: 262 exc, err, tb = sys.exc_info() 263 co = tb.tb_frame.f_code 264 self.assertEqual(co.co_name, "test_capi1") 265 self.assertTrue(co.co_filename.endswith('test_exceptions.py')) 266 else: 267 self.fail("Expected exception") 268 269 def test_capi2(): 270 import _testcapi 271 try: 272 _testcapi.raise_exception(BadException, 0) 273 except RuntimeError as err: 274 exc, err, tb = sys.exc_info() 275 co = tb.tb_frame.f_code 276 self.assertEqual(co.co_name, "__init__") 277 self.assertTrue(co.co_filename.endswith('test_exceptions.py')) 278 co2 = tb.tb_frame.f_back.f_code 279 self.assertEqual(co2.co_name, "test_capi2") 280 else: 281 self.fail("Expected exception") 282 283 def test_capi3(): 284 import _testcapi 285 self.assertRaises(SystemError, _testcapi.raise_exception, 286 InvalidException, 1) 287 288 if not sys.platform.startswith('java'): 289 test_capi1() 290 test_capi2() 291 test_capi3() 292 293 def test_WindowsError(self): 294 try: 295 WindowsError 296 except NameError: 297 pass 298 else: 299 self.assertIs(WindowsError, OSError) 300 self.assertEqual(str(OSError(1001)), "1001") 301 self.assertEqual(str(OSError(1001, "message")), 302 "[Errno 1001] message") 303 # POSIX errno (9 aka EBADF) is untranslated 304 w = OSError(9, 'foo', 'bar') 305 self.assertEqual(w.errno, 9) 306 self.assertEqual(w.winerror, None) 307 self.assertEqual(str(w), "[Errno 9] foo: 'bar'") 308 # ERROR_PATH_NOT_FOUND (win error 3) becomes ENOENT (2) 309 w = OSError(0, 'foo', 'bar', 3) 310 self.assertEqual(w.errno, 2) 311 self.assertEqual(w.winerror, 3) 312 self.assertEqual(w.strerror, 'foo') 313 self.assertEqual(w.filename, 'bar') 314 self.assertEqual(w.filename2, None) 315 self.assertEqual(str(w), "[WinError 3] foo: 'bar'") 316 # Unknown win error becomes EINVAL (22) 317 w = OSError(0, 'foo', None, 1001) 318 self.assertEqual(w.errno, 22) 319 self.assertEqual(w.winerror, 1001) 320 self.assertEqual(w.strerror, 'foo') 321 self.assertEqual(w.filename, None) 322 self.assertEqual(w.filename2, None) 323 self.assertEqual(str(w), "[WinError 1001] foo") 324 # Non-numeric "errno" 325 w = OSError('bar', 'foo') 326 self.assertEqual(w.errno, 'bar') 327 self.assertEqual(w.winerror, None) 328 self.assertEqual(w.strerror, 'foo') 329 self.assertEqual(w.filename, None) 330 self.assertEqual(w.filename2, None) 331 332 @unittest.skipUnless(sys.platform == 'win32', 333 'test specific to Windows') 334 def test_windows_message(self): 335 """Should fill in unknown error code in Windows error message""" 336 ctypes = import_module('ctypes') 337 # this error code has no message, Python formats it as hexadecimal 338 code = 3765269347 339 with self.assertRaisesRegex(OSError, 'Windows Error 0x%x' % code): 340 ctypes.pythonapi.PyErr_SetFromWindowsErr(code) 341 342 def testAttributes(self): 343 # test that exception attributes are happy 344 345 exceptionList = [ 346 (BaseException, (), {'args' : ()}), 347 (BaseException, (1, ), {'args' : (1,)}), 348 (BaseException, ('foo',), 349 {'args' : ('foo',)}), 350 (BaseException, ('foo', 1), 351 {'args' : ('foo', 1)}), 352 (SystemExit, ('foo',), 353 {'args' : ('foo',), 'code' : 'foo'}), 354 (OSError, ('foo',), 355 {'args' : ('foo',), 'filename' : None, 'filename2' : None, 356 'errno' : None, 'strerror' : None}), 357 (OSError, ('foo', 'bar'), 358 {'args' : ('foo', 'bar'), 359 'filename' : None, 'filename2' : None, 360 'errno' : 'foo', 'strerror' : 'bar'}), 361 (OSError, ('foo', 'bar', 'baz'), 362 {'args' : ('foo', 'bar'), 363 'filename' : 'baz', 'filename2' : None, 364 'errno' : 'foo', 'strerror' : 'bar'}), 365 (OSError, ('foo', 'bar', 'baz', None, 'quux'), 366 {'args' : ('foo', 'bar'), 'filename' : 'baz', 'filename2': 'quux'}), 367 (OSError, ('errnoStr', 'strErrorStr', 'filenameStr'), 368 {'args' : ('errnoStr', 'strErrorStr'), 369 'strerror' : 'strErrorStr', 'errno' : 'errnoStr', 370 'filename' : 'filenameStr'}), 371 (OSError, (1, 'strErrorStr', 'filenameStr'), 372 {'args' : (1, 'strErrorStr'), 'errno' : 1, 373 'strerror' : 'strErrorStr', 374 'filename' : 'filenameStr', 'filename2' : None}), 375 (SyntaxError, (), {'msg' : None, 'text' : None, 376 'filename' : None, 'lineno' : None, 'offset' : None, 377 'print_file_and_line' : None}), 378 (SyntaxError, ('msgStr',), 379 {'args' : ('msgStr',), 'text' : None, 380 'print_file_and_line' : None, 'msg' : 'msgStr', 381 'filename' : None, 'lineno' : None, 'offset' : None}), 382 (SyntaxError, ('msgStr', ('filenameStr', 'linenoStr', 'offsetStr', 383 'textStr')), 384 {'offset' : 'offsetStr', 'text' : 'textStr', 385 'args' : ('msgStr', ('filenameStr', 'linenoStr', 386 'offsetStr', 'textStr')), 387 'print_file_and_line' : None, 'msg' : 'msgStr', 388 'filename' : 'filenameStr', 'lineno' : 'linenoStr'}), 389 (SyntaxError, ('msgStr', 'filenameStr', 'linenoStr', 'offsetStr', 390 'textStr', 'print_file_and_lineStr'), 391 {'text' : None, 392 'args' : ('msgStr', 'filenameStr', 'linenoStr', 'offsetStr', 393 'textStr', 'print_file_and_lineStr'), 394 'print_file_and_line' : None, 'msg' : 'msgStr', 395 'filename' : None, 'lineno' : None, 'offset' : None}), 396 (UnicodeError, (), {'args' : (),}), 397 (UnicodeEncodeError, ('ascii', 'a', 0, 1, 398 'ordinal not in range'), 399 {'args' : ('ascii', 'a', 0, 1, 400 'ordinal not in range'), 401 'encoding' : 'ascii', 'object' : 'a', 402 'start' : 0, 'reason' : 'ordinal not in range'}), 403 (UnicodeDecodeError, ('ascii', bytearray(b'\xff'), 0, 1, 404 'ordinal not in range'), 405 {'args' : ('ascii', bytearray(b'\xff'), 0, 1, 406 'ordinal not in range'), 407 'encoding' : 'ascii', 'object' : b'\xff', 408 'start' : 0, 'reason' : 'ordinal not in range'}), 409 (UnicodeDecodeError, ('ascii', b'\xff', 0, 1, 410 'ordinal not in range'), 411 {'args' : ('ascii', b'\xff', 0, 1, 412 'ordinal not in range'), 413 'encoding' : 'ascii', 'object' : b'\xff', 414 'start' : 0, 'reason' : 'ordinal not in range'}), 415 (UnicodeTranslateError, ("\u3042", 0, 1, "ouch"), 416 {'args' : ('\u3042', 0, 1, 'ouch'), 417 'object' : '\u3042', 'reason' : 'ouch', 418 'start' : 0, 'end' : 1}), 419 (NaiveException, ('foo',), 420 {'args': ('foo',), 'x': 'foo'}), 421 (SlottedNaiveException, ('foo',), 422 {'args': ('foo',), 'x': 'foo'}), 423 ] 424 try: 425 # More tests are in test_WindowsError 426 exceptionList.append( 427 (WindowsError, (1, 'strErrorStr', 'filenameStr'), 428 {'args' : (1, 'strErrorStr'), 429 'strerror' : 'strErrorStr', 'winerror' : None, 430 'errno' : 1, 431 'filename' : 'filenameStr', 'filename2' : None}) 432 ) 433 except NameError: 434 pass 435 436 for exc, args, expected in exceptionList: 437 try: 438 e = exc(*args) 439 except: 440 print("\nexc=%r, args=%r" % (exc, args), file=sys.stderr) 441 raise 442 else: 443 # Verify module name 444 if not type(e).__name__.endswith('NaiveException'): 445 self.assertEqual(type(e).__module__, 'builtins') 446 # Verify no ref leaks in Exc_str() 447 s = str(e) 448 for checkArgName in expected: 449 value = getattr(e, checkArgName) 450 self.assertEqual(repr(value), 451 repr(expected[checkArgName]), 452 '%r.%s == %r, expected %r' % ( 453 e, checkArgName, 454 value, expected[checkArgName])) 455 456 # test for pickling support 457 for p in [pickle]: 458 for protocol in range(p.HIGHEST_PROTOCOL + 1): 459 s = p.dumps(e, protocol) 460 new = p.loads(s) 461 for checkArgName in expected: 462 got = repr(getattr(new, checkArgName)) 463 want = repr(expected[checkArgName]) 464 self.assertEqual(got, want, 465 'pickled "%r", attribute "%s' % 466 (e, checkArgName)) 467 468 def testWithTraceback(self): 469 try: 470 raise IndexError(4) 471 except: 472 tb = sys.exc_info()[2] 473 474 e = BaseException().with_traceback(tb) 475 self.assertIsInstance(e, BaseException) 476 self.assertEqual(e.__traceback__, tb) 477 478 e = IndexError(5).with_traceback(tb) 479 self.assertIsInstance(e, IndexError) 480 self.assertEqual(e.__traceback__, tb) 481 482 class MyException(Exception): 483 pass 484 485 e = MyException().with_traceback(tb) 486 self.assertIsInstance(e, MyException) 487 self.assertEqual(e.__traceback__, tb) 488 489 def testInvalidTraceback(self): 490 try: 491 Exception().__traceback__ = 5 492 except TypeError as e: 493 self.assertIn("__traceback__ must be a traceback", str(e)) 494 else: 495 self.fail("No exception raised") 496 497 def testInvalidAttrs(self): 498 self.assertRaises(TypeError, setattr, Exception(), '__cause__', 1) 499 self.assertRaises(TypeError, delattr, Exception(), '__cause__') 500 self.assertRaises(TypeError, setattr, Exception(), '__context__', 1) 501 self.assertRaises(TypeError, delattr, Exception(), '__context__') 502 503 def testNoneClearsTracebackAttr(self): 504 try: 505 raise IndexError(4) 506 except: 507 tb = sys.exc_info()[2] 508 509 e = Exception() 510 e.__traceback__ = tb 511 e.__traceback__ = None 512 self.assertEqual(e.__traceback__, None) 513 514 def testChainingAttrs(self): 515 e = Exception() 516 self.assertIsNone(e.__context__) 517 self.assertIsNone(e.__cause__) 518 519 e = TypeError() 520 self.assertIsNone(e.__context__) 521 self.assertIsNone(e.__cause__) 522 523 class MyException(OSError): 524 pass 525 526 e = MyException() 527 self.assertIsNone(e.__context__) 528 self.assertIsNone(e.__cause__) 529 530 def testChainingDescriptors(self): 531 try: 532 raise Exception() 533 except Exception as exc: 534 e = exc 535 536 self.assertIsNone(e.__context__) 537 self.assertIsNone(e.__cause__) 538 self.assertFalse(e.__suppress_context__) 539 540 e.__context__ = NameError() 541 e.__cause__ = None 542 self.assertIsInstance(e.__context__, NameError) 543 self.assertIsNone(e.__cause__) 544 self.assertTrue(e.__suppress_context__) 545 e.__suppress_context__ = False 546 self.assertFalse(e.__suppress_context__) 547 548 def testKeywordArgs(self): 549 # test that builtin exception don't take keyword args, 550 # but user-defined subclasses can if they want 551 self.assertRaises(TypeError, BaseException, a=1) 552 553 class DerivedException(BaseException): 554 def __init__(self, fancy_arg): 555 BaseException.__init__(self) 556 self.fancy_arg = fancy_arg 557 558 x = DerivedException(fancy_arg=42) 559 self.assertEqual(x.fancy_arg, 42) 560 561 @no_tracing 562 def testInfiniteRecursion(self): 563 def f(): 564 return f() 565 self.assertRaises(RecursionError, f) 566 567 def g(): 568 try: 569 return g() 570 except ValueError: 571 return -1 572 self.assertRaises(RecursionError, g) 573 574 def test_str(self): 575 # Make sure both instances and classes have a str representation. 576 self.assertTrue(str(Exception)) 577 self.assertTrue(str(Exception('a'))) 578 self.assertTrue(str(Exception('a', 'b'))) 579 580 def testExceptionCleanupNames(self): 581 # Make sure the local variable bound to the exception instance by 582 # an "except" statement is only visible inside the except block. 583 try: 584 raise Exception() 585 except Exception as e: 586 self.assertTrue(e) 587 del e 588 self.assertNotIn('e', locals()) 589 590 def testExceptionCleanupState(self): 591 # Make sure exception state is cleaned up as soon as the except 592 # block is left. See #2507 593 594 class MyException(Exception): 595 def __init__(self, obj): 596 self.obj = obj 597 class MyObj: 598 pass 599 600 def inner_raising_func(): 601 # Create some references in exception value and traceback 602 local_ref = obj 603 raise MyException(obj) 604 605 # Qualified "except" with "as" 606 obj = MyObj() 607 wr = weakref.ref(obj) 608 try: 609 inner_raising_func() 610 except MyException as e: 611 pass 612 obj = None 613 obj = wr() 614 self.assertIsNone(obj) 615 616 # Qualified "except" without "as" 617 obj = MyObj() 618 wr = weakref.ref(obj) 619 try: 620 inner_raising_func() 621 except MyException: 622 pass 623 obj = None 624 obj = wr() 625 self.assertIsNone(obj) 626 627 # Bare "except" 628 obj = MyObj() 629 wr = weakref.ref(obj) 630 try: 631 inner_raising_func() 632 except: 633 pass 634 obj = None 635 obj = wr() 636 self.assertIsNone(obj) 637 638 # "except" with premature block leave 639 obj = MyObj() 640 wr = weakref.ref(obj) 641 for i in [0]: 642 try: 643 inner_raising_func() 644 except: 645 break 646 obj = None 647 obj = wr() 648 self.assertIsNone(obj) 649 650 # "except" block raising another exception 651 obj = MyObj() 652 wr = weakref.ref(obj) 653 try: 654 try: 655 inner_raising_func() 656 except: 657 raise KeyError 658 except KeyError as e: 659 # We want to test that the except block above got rid of 660 # the exception raised in inner_raising_func(), but it 661 # also ends up in the __context__ of the KeyError, so we 662 # must clear the latter manually for our test to succeed. 663 e.__context__ = None 664 obj = None 665 obj = wr() 666 # guarantee no ref cycles on CPython (don't gc_collect) 667 if check_impl_detail(cpython=False): 668 gc_collect() 669 self.assertIsNone(obj) 670 671 # Some complicated construct 672 obj = MyObj() 673 wr = weakref.ref(obj) 674 try: 675 inner_raising_func() 676 except MyException: 677 try: 678 try: 679 raise 680 finally: 681 raise 682 except MyException: 683 pass 684 obj = None 685 if check_impl_detail(cpython=False): 686 gc_collect() 687 obj = wr() 688 self.assertIsNone(obj) 689 690 # Inside an exception-silencing "with" block 691 class Context: 692 def __enter__(self): 693 return self 694 def __exit__ (self, exc_type, exc_value, exc_tb): 695 return True 696 obj = MyObj() 697 wr = weakref.ref(obj) 698 with Context(): 699 inner_raising_func() 700 obj = None 701 if check_impl_detail(cpython=False): 702 gc_collect() 703 obj = wr() 704 self.assertIsNone(obj) 705 706 def test_exception_target_in_nested_scope(self): 707 # issue 4617: This used to raise a SyntaxError 708 # "can not delete variable 'e' referenced in nested scope" 709 def print_error(): 710 e 711 try: 712 something 713 except Exception as e: 714 print_error() 715 # implicit "del e" here 716 717 def test_generator_leaking(self): 718 # Test that generator exception state doesn't leak into the calling 719 # frame 720 def yield_raise(): 721 try: 722 raise KeyError("caught") 723 except KeyError: 724 yield sys.exc_info()[0] 725 yield sys.exc_info()[0] 726 yield sys.exc_info()[0] 727 g = yield_raise() 728 self.assertEqual(next(g), KeyError) 729 self.assertEqual(sys.exc_info()[0], None) 730 self.assertEqual(next(g), KeyError) 731 self.assertEqual(sys.exc_info()[0], None) 732 self.assertEqual(next(g), None) 733 734 # Same test, but inside an exception handler 735 try: 736 raise TypeError("foo") 737 except TypeError: 738 g = yield_raise() 739 self.assertEqual(next(g), KeyError) 740 self.assertEqual(sys.exc_info()[0], TypeError) 741 self.assertEqual(next(g), KeyError) 742 self.assertEqual(sys.exc_info()[0], TypeError) 743 self.assertEqual(next(g), TypeError) 744 del g 745 self.assertEqual(sys.exc_info()[0], TypeError) 746 747 def test_generator_leaking2(self): 748 # See issue 12475. 749 def g(): 750 yield 751 try: 752 raise RuntimeError 753 except RuntimeError: 754 it = g() 755 next(it) 756 try: 757 next(it) 758 except StopIteration: 759 pass 760 self.assertEqual(sys.exc_info(), (None, None, None)) 761 762 def test_generator_leaking3(self): 763 # See issue #23353. When gen.throw() is called, the caller's 764 # exception state should be save and restored. 765 def g(): 766 try: 767 yield 768 except ZeroDivisionError: 769 yield sys.exc_info()[1] 770 it = g() 771 next(it) 772 try: 773 1/0 774 except ZeroDivisionError as e: 775 self.assertIs(sys.exc_info()[1], e) 776 gen_exc = it.throw(e) 777 self.assertIs(sys.exc_info()[1], e) 778 self.assertIs(gen_exc, e) 779 self.assertEqual(sys.exc_info(), (None, None, None)) 780 781 def test_generator_leaking4(self): 782 # See issue #23353. When an exception is raised by a generator, 783 # the caller's exception state should still be restored. 784 def g(): 785 try: 786 1/0 787 except ZeroDivisionError: 788 yield sys.exc_info()[0] 789 raise 790 it = g() 791 try: 792 raise TypeError 793 except TypeError: 794 # The caller's exception state (TypeError) is temporarily 795 # saved in the generator. 796 tp = next(it) 797 self.assertIs(tp, ZeroDivisionError) 798 try: 799 next(it) 800 # We can't check it immediately, but while next() returns 801 # with an exception, it shouldn't have restored the old 802 # exception state (TypeError). 803 except ZeroDivisionError as e: 804 self.assertIs(sys.exc_info()[1], e) 805 # We used to find TypeError here. 806 self.assertEqual(sys.exc_info(), (None, None, None)) 807 808 def test_generator_doesnt_retain_old_exc(self): 809 def g(): 810 self.assertIsInstance(sys.exc_info()[1], RuntimeError) 811 yield 812 self.assertEqual(sys.exc_info(), (None, None, None)) 813 it = g() 814 try: 815 raise RuntimeError 816 except RuntimeError: 817 next(it) 818 self.assertRaises(StopIteration, next, it) 819 820 def test_generator_finalizing_and_exc_info(self): 821 # See #7173 822 def simple_gen(): 823 yield 1 824 def run_gen(): 825 gen = simple_gen() 826 try: 827 raise RuntimeError 828 except RuntimeError: 829 return next(gen) 830 run_gen() 831 gc_collect() 832 self.assertEqual(sys.exc_info(), (None, None, None)) 833 834 def _check_generator_cleanup_exc_state(self, testfunc): 835 # Issue #12791: exception state is cleaned up as soon as a generator 836 # is closed (reference cycles are broken). 837 class MyException(Exception): 838 def __init__(self, obj): 839 self.obj = obj 840 class MyObj: 841 pass 842 843 def raising_gen(): 844 try: 845 raise MyException(obj) 846 except MyException: 847 yield 848 849 obj = MyObj() 850 wr = weakref.ref(obj) 851 g = raising_gen() 852 next(g) 853 testfunc(g) 854 g = obj = None 855 obj = wr() 856 self.assertIsNone(obj) 857 858 def test_generator_throw_cleanup_exc_state(self): 859 def do_throw(g): 860 try: 861 g.throw(RuntimeError()) 862 except RuntimeError: 863 pass 864 self._check_generator_cleanup_exc_state(do_throw) 865 866 def test_generator_close_cleanup_exc_state(self): 867 def do_close(g): 868 g.close() 869 self._check_generator_cleanup_exc_state(do_close) 870 871 def test_generator_del_cleanup_exc_state(self): 872 def do_del(g): 873 g = None 874 self._check_generator_cleanup_exc_state(do_del) 875 876 def test_generator_next_cleanup_exc_state(self): 877 def do_next(g): 878 try: 879 next(g) 880 except StopIteration: 881 pass 882 else: 883 self.fail("should have raised StopIteration") 884 self._check_generator_cleanup_exc_state(do_next) 885 886 def test_generator_send_cleanup_exc_state(self): 887 def do_send(g): 888 try: 889 g.send(None) 890 except StopIteration: 891 pass 892 else: 893 self.fail("should have raised StopIteration") 894 self._check_generator_cleanup_exc_state(do_send) 895 896 def test_3114(self): 897 # Bug #3114: in its destructor, MyObject retrieves a pointer to 898 # obsolete and/or deallocated objects. 899 class MyObject: 900 def __del__(self): 901 nonlocal e 902 e = sys.exc_info() 903 e = () 904 try: 905 raise Exception(MyObject()) 906 except: 907 pass 908 self.assertEqual(e, (None, None, None)) 909 910 def test_unicode_change_attributes(self): 911 # See issue 7309. This was a crasher. 912 913 u = UnicodeEncodeError('baz', 'xxxxx', 1, 5, 'foo') 914 self.assertEqual(str(u), "'baz' codec can't encode characters in position 1-4: foo") 915 u.end = 2 916 self.assertEqual(str(u), "'baz' codec can't encode character '\\x78' in position 1: foo") 917 u.end = 5 918 u.reason = 0x345345345345345345 919 self.assertEqual(str(u), "'baz' codec can't encode characters in position 1-4: 965230951443685724997") 920 u.encoding = 4000 921 self.assertEqual(str(u), "'4000' codec can't encode characters in position 1-4: 965230951443685724997") 922 u.start = 1000 923 self.assertEqual(str(u), "'4000' codec can't encode characters in position 1000-4: 965230951443685724997") 924 925 u = UnicodeDecodeError('baz', b'xxxxx', 1, 5, 'foo') 926 self.assertEqual(str(u), "'baz' codec can't decode bytes in position 1-4: foo") 927 u.end = 2 928 self.assertEqual(str(u), "'baz' codec can't decode byte 0x78 in position 1: foo") 929 u.end = 5 930 u.reason = 0x345345345345345345 931 self.assertEqual(str(u), "'baz' codec can't decode bytes in position 1-4: 965230951443685724997") 932 u.encoding = 4000 933 self.assertEqual(str(u), "'4000' codec can't decode bytes in position 1-4: 965230951443685724997") 934 u.start = 1000 935 self.assertEqual(str(u), "'4000' codec can't decode bytes in position 1000-4: 965230951443685724997") 936 937 u = UnicodeTranslateError('xxxx', 1, 5, 'foo') 938 self.assertEqual(str(u), "can't translate characters in position 1-4: foo") 939 u.end = 2 940 self.assertEqual(str(u), "can't translate character '\\x78' in position 1: foo") 941 u.end = 5 942 u.reason = 0x345345345345345345 943 self.assertEqual(str(u), "can't translate characters in position 1-4: 965230951443685724997") 944 u.start = 1000 945 self.assertEqual(str(u), "can't translate characters in position 1000-4: 965230951443685724997") 946 947 def test_unicode_errors_no_object(self): 948 # See issue #21134. 949 klasses = UnicodeEncodeError, UnicodeDecodeError, UnicodeTranslateError 950 for klass in klasses: 951 self.assertEqual(str(klass.__new__(klass)), "") 952 953 @no_tracing 954 def test_badisinstance(self): 955 # Bug #2542: if issubclass(e, MyException) raises an exception, 956 # it should be ignored 957 class Meta(type): 958 def __subclasscheck__(cls, subclass): 959 raise ValueError() 960 class MyException(Exception, metaclass=Meta): 961 pass 962 963 with captured_stderr() as stderr: 964 try: 965 raise KeyError() 966 except MyException as e: 967 self.fail("exception should not be a MyException") 968 except KeyError: 969 pass 970 except: 971 self.fail("Should have raised KeyError") 972 else: 973 self.fail("Should have raised KeyError") 974 975 def g(): 976 try: 977 return g() 978 except RecursionError: 979 return sys.exc_info() 980 e, v, tb = g() 981 self.assertIsInstance(v, RecursionError, type(v)) 982 self.assertIn("maximum recursion depth exceeded", str(v)) 983 984 @cpython_only 985 def test_recursion_normalizing_exception(self): 986 # Issue #22898. 987 # Test that a RecursionError is raised when tstate->recursion_depth is 988 # equal to recursion_limit in PyErr_NormalizeException() and check 989 # that a ResourceWarning is printed. 990 # Prior to #22898, the recursivity of PyErr_NormalizeException() was 991 # controlled by tstate->recursion_depth and a PyExc_RecursionErrorInst 992 # singleton was being used in that case, that held traceback data and 993 # locals indefinitely and would cause a segfault in _PyExc_Fini() upon 994 # finalization of these locals. 995 code = """if 1: 996 import sys 997 from _testcapi import get_recursion_depth 998 999 class MyException(Exception): pass 1000 1001 def setrecursionlimit(depth): 1002 while 1: 1003 try: 1004 sys.setrecursionlimit(depth) 1005 return depth 1006 except RecursionError: 1007 # sys.setrecursionlimit() raises a RecursionError if 1008 # the new recursion limit is too low (issue #25274). 1009 depth += 1 1010 1011 def recurse(cnt): 1012 cnt -= 1 1013 if cnt: 1014 recurse(cnt) 1015 else: 1016 generator.throw(MyException) 1017 1018 def gen(): 1019 f = open(%a, mode='rb', buffering=0) 1020 yield 1021 1022 generator = gen() 1023 next(generator) 1024 recursionlimit = sys.getrecursionlimit() 1025 depth = get_recursion_depth() 1026 try: 1027 # Upon the last recursive invocation of recurse(), 1028 # tstate->recursion_depth is equal to (recursion_limit - 1) 1029 # and is equal to recursion_limit when _gen_throw() calls 1030 # PyErr_NormalizeException(). 1031 recurse(setrecursionlimit(depth + 2) - depth - 1) 1032 finally: 1033 sys.setrecursionlimit(recursionlimit) 1034 print('Done.') 1035 """ % __file__ 1036 rc, out, err = script_helper.assert_python_failure("-Wd", "-c", code) 1037 # Check that the program does not fail with SIGABRT. 1038 self.assertEqual(rc, 1) 1039 self.assertIn(b'RecursionError', err) 1040 self.assertIn(b'ResourceWarning', err) 1041 self.assertIn(b'Done.', out) 1042 1043 @cpython_only 1044 def test_recursion_normalizing_infinite_exception(self): 1045 # Issue #30697. Test that a RecursionError is raised when 1046 # PyErr_NormalizeException() maximum recursion depth has been 1047 # exceeded. 1048 code = """if 1: 1049 import _testcapi 1050 try: 1051 raise _testcapi.RecursingInfinitelyError 1052 finally: 1053 print('Done.') 1054 """ 1055 rc, out, err = script_helper.assert_python_failure("-c", code) 1056 self.assertEqual(rc, 1) 1057 self.assertIn(b'RecursionError: maximum recursion depth exceeded ' 1058 b'while normalizing an exception', err) 1059 self.assertIn(b'Done.', out) 1060 1061 @cpython_only 1062 def test_recursion_normalizing_with_no_memory(self): 1063 # Issue #30697. Test that in the abort that occurs when there is no 1064 # memory left and the size of the Python frames stack is greater than 1065 # the size of the list of preallocated MemoryError instances, the 1066 # Fatal Python error message mentions MemoryError. 1067 code = """if 1: 1068 import _testcapi 1069 class C(): pass 1070 def recurse(cnt): 1071 cnt -= 1 1072 if cnt: 1073 recurse(cnt) 1074 else: 1075 _testcapi.set_nomemory(0) 1076 C() 1077 recurse(16) 1078 """ 1079 with SuppressCrashReport(): 1080 rc, out, err = script_helper.assert_python_failure("-c", code) 1081 self.assertIn(b'Fatal Python error: Cannot recover from ' 1082 b'MemoryErrors while normalizing exceptions.', err) 1083 1084 @cpython_only 1085 def test_MemoryError(self): 1086 # PyErr_NoMemory always raises the same exception instance. 1087 # Check that the traceback is not doubled. 1088 import traceback 1089 from _testcapi import raise_memoryerror 1090 def raiseMemError(): 1091 try: 1092 raise_memoryerror() 1093 except MemoryError as e: 1094 tb = e.__traceback__ 1095 else: 1096 self.fail("Should have raises a MemoryError") 1097 return traceback.format_tb(tb) 1098 1099 tb1 = raiseMemError() 1100 tb2 = raiseMemError() 1101 self.assertEqual(tb1, tb2) 1102 1103 @cpython_only 1104 def test_exception_with_doc(self): 1105 import _testcapi 1106 doc2 = "This is a test docstring." 1107 doc4 = "This is another test docstring." 1108 1109 self.assertRaises(SystemError, _testcapi.make_exception_with_doc, 1110 "error1") 1111 1112 # test basic usage of PyErr_NewException 1113 error1 = _testcapi.make_exception_with_doc("_testcapi.error1") 1114 self.assertIs(type(error1), type) 1115 self.assertTrue(issubclass(error1, Exception)) 1116 self.assertIsNone(error1.__doc__) 1117 1118 # test with given docstring 1119 error2 = _testcapi.make_exception_with_doc("_testcapi.error2", doc2) 1120 self.assertEqual(error2.__doc__, doc2) 1121 1122 # test with explicit base (without docstring) 1123 error3 = _testcapi.make_exception_with_doc("_testcapi.error3", 1124 base=error2) 1125 self.assertTrue(issubclass(error3, error2)) 1126 1127 # test with explicit base tuple 1128 class C(object): 1129 pass 1130 error4 = _testcapi.make_exception_with_doc("_testcapi.error4", doc4, 1131 (error3, C)) 1132 self.assertTrue(issubclass(error4, error3)) 1133 self.assertTrue(issubclass(error4, C)) 1134 self.assertEqual(error4.__doc__, doc4) 1135 1136 # test with explicit dictionary 1137 error5 = _testcapi.make_exception_with_doc("_testcapi.error5", "", 1138 error4, {'a': 1}) 1139 self.assertTrue(issubclass(error5, error4)) 1140 self.assertEqual(error5.a, 1) 1141 self.assertEqual(error5.__doc__, "") 1142 1143 @cpython_only 1144 def test_memory_error_cleanup(self): 1145 # Issue #5437: preallocated MemoryError instances should not keep 1146 # traceback objects alive. 1147 from _testcapi import raise_memoryerror 1148 class C: 1149 pass 1150 wr = None 1151 def inner(): 1152 nonlocal wr 1153 c = C() 1154 wr = weakref.ref(c) 1155 raise_memoryerror() 1156 # We cannot use assertRaises since it manually deletes the traceback 1157 try: 1158 inner() 1159 except MemoryError as e: 1160 self.assertNotEqual(wr(), None) 1161 else: 1162 self.fail("MemoryError not raised") 1163 self.assertEqual(wr(), None) 1164 1165 @no_tracing 1166 def test_recursion_error_cleanup(self): 1167 # Same test as above, but with "recursion exceeded" errors 1168 class C: 1169 pass 1170 wr = None 1171 def inner(): 1172 nonlocal wr 1173 c = C() 1174 wr = weakref.ref(c) 1175 inner() 1176 # We cannot use assertRaises since it manually deletes the traceback 1177 try: 1178 inner() 1179 except RecursionError as e: 1180 self.assertNotEqual(wr(), None) 1181 else: 1182 self.fail("RecursionError not raised") 1183 self.assertEqual(wr(), None) 1184 1185 def test_errno_ENOTDIR(self): 1186 # Issue #12802: "not a directory" errors are ENOTDIR even on Windows 1187 with self.assertRaises(OSError) as cm: 1188 os.listdir(__file__) 1189 self.assertEqual(cm.exception.errno, errno.ENOTDIR, cm.exception) 1190 1191 def test_unraisable(self): 1192 # Issue #22836: PyErr_WriteUnraisable() should give sensible reports 1193 class BrokenDel: 1194 def __del__(self): 1195 exc = ValueError("del is broken") 1196 # The following line is included in the traceback report: 1197 raise exc 1198 1199 obj = BrokenDel() 1200 with support.catch_unraisable_exception() as cm: 1201 del obj 1202 1203 self.assertEqual(cm.unraisable.object, BrokenDel.__del__) 1204 self.assertIsNotNone(cm.unraisable.exc_traceback) 1205 1206 def test_unhandled(self): 1207 # Check for sensible reporting of unhandled exceptions 1208 for exc_type in (ValueError, BrokenStrException): 1209 with self.subTest(exc_type): 1210 try: 1211 exc = exc_type("test message") 1212 # The following line is included in the traceback report: 1213 raise exc 1214 except exc_type: 1215 with captured_stderr() as stderr: 1216 sys.__excepthook__(*sys.exc_info()) 1217 report = stderr.getvalue() 1218 self.assertIn("test_exceptions.py", report) 1219 self.assertIn("raise exc", report) 1220 self.assertIn(exc_type.__name__, report) 1221 if exc_type is BrokenStrException: 1222 self.assertIn("<exception str() failed>", report) 1223 else: 1224 self.assertIn("test message", report) 1225 self.assertTrue(report.endswith("\n")) 1226 1227 @cpython_only 1228 def test_memory_error_in_PyErr_PrintEx(self): 1229 code = """if 1: 1230 import _testcapi 1231 class C(): pass 1232 _testcapi.set_nomemory(0, %d) 1233 C() 1234 """ 1235 1236 # Issue #30817: Abort in PyErr_PrintEx() when no memory. 1237 # Span a large range of tests as the CPython code always evolves with 1238 # changes that add or remove memory allocations. 1239 for i in range(1, 20): 1240 rc, out, err = script_helper.assert_python_failure("-c", code % i) 1241 self.assertIn(rc, (1, 120)) 1242 self.assertIn(b'MemoryError', err) 1243 1244 def test_yield_in_nested_try_excepts(self): 1245 #Issue #25612 1246 class MainError(Exception): 1247 pass 1248 1249 class SubError(Exception): 1250 pass 1251 1252 def main(): 1253 try: 1254 raise MainError() 1255 except MainError: 1256 try: 1257 yield 1258 except SubError: 1259 pass 1260 raise 1261 1262 coro = main() 1263 coro.send(None) 1264 with self.assertRaises(MainError): 1265 coro.throw(SubError()) 1266 1267 def test_generator_doesnt_retain_old_exc2(self): 1268 #Issue 28884#msg282532 1269 def g(): 1270 try: 1271 raise ValueError 1272 except ValueError: 1273 yield 1 1274 self.assertEqual(sys.exc_info(), (None, None, None)) 1275 yield 2 1276 1277 gen = g() 1278 1279 try: 1280 raise IndexError 1281 except IndexError: 1282 self.assertEqual(next(gen), 1) 1283 self.assertEqual(next(gen), 2) 1284 1285 def test_raise_in_generator(self): 1286 #Issue 25612#msg304117 1287 def g(): 1288 yield 1 1289 raise 1290 yield 2 1291 1292 with self.assertRaises(ZeroDivisionError): 1293 i = g() 1294 try: 1295 1/0 1296 except: 1297 next(i) 1298 next(i) 1299 1300 1301class ImportErrorTests(unittest.TestCase): 1302 1303 def test_attributes(self): 1304 # Setting 'name' and 'path' should not be a problem. 1305 exc = ImportError('test') 1306 self.assertIsNone(exc.name) 1307 self.assertIsNone(exc.path) 1308 1309 exc = ImportError('test', name='somemodule') 1310 self.assertEqual(exc.name, 'somemodule') 1311 self.assertIsNone(exc.path) 1312 1313 exc = ImportError('test', path='somepath') 1314 self.assertEqual(exc.path, 'somepath') 1315 self.assertIsNone(exc.name) 1316 1317 exc = ImportError('test', path='somepath', name='somename') 1318 self.assertEqual(exc.name, 'somename') 1319 self.assertEqual(exc.path, 'somepath') 1320 1321 msg = "'invalid' is an invalid keyword argument for ImportError" 1322 with self.assertRaisesRegex(TypeError, msg): 1323 ImportError('test', invalid='keyword') 1324 1325 with self.assertRaisesRegex(TypeError, msg): 1326 ImportError('test', name='name', invalid='keyword') 1327 1328 with self.assertRaisesRegex(TypeError, msg): 1329 ImportError('test', path='path', invalid='keyword') 1330 1331 with self.assertRaisesRegex(TypeError, msg): 1332 ImportError(invalid='keyword') 1333 1334 with self.assertRaisesRegex(TypeError, msg): 1335 ImportError('test', invalid='keyword', another=True) 1336 1337 def test_reset_attributes(self): 1338 exc = ImportError('test', name='name', path='path') 1339 self.assertEqual(exc.args, ('test',)) 1340 self.assertEqual(exc.msg, 'test') 1341 self.assertEqual(exc.name, 'name') 1342 self.assertEqual(exc.path, 'path') 1343 1344 # Reset not specified attributes 1345 exc.__init__() 1346 self.assertEqual(exc.args, ()) 1347 self.assertEqual(exc.msg, None) 1348 self.assertEqual(exc.name, None) 1349 self.assertEqual(exc.path, None) 1350 1351 def test_non_str_argument(self): 1352 # Issue #15778 1353 with check_warnings(('', BytesWarning), quiet=True): 1354 arg = b'abc' 1355 exc = ImportError(arg) 1356 self.assertEqual(str(arg), str(exc)) 1357 1358 def test_copy_pickle(self): 1359 for kwargs in (dict(), 1360 dict(name='somename'), 1361 dict(path='somepath'), 1362 dict(name='somename', path='somepath')): 1363 orig = ImportError('test', **kwargs) 1364 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 1365 exc = pickle.loads(pickle.dumps(orig, proto)) 1366 self.assertEqual(exc.args, ('test',)) 1367 self.assertEqual(exc.msg, 'test') 1368 self.assertEqual(exc.name, orig.name) 1369 self.assertEqual(exc.path, orig.path) 1370 for c in copy.copy, copy.deepcopy: 1371 exc = c(orig) 1372 self.assertEqual(exc.args, ('test',)) 1373 self.assertEqual(exc.msg, 'test') 1374 self.assertEqual(exc.name, orig.name) 1375 self.assertEqual(exc.path, orig.path) 1376 1377 1378if __name__ == '__main__': 1379 unittest.main() 1380