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