1import sys 2import unittest 3import textwrap 4 5class TestInvalidExceptStar(unittest.TestCase): 6 def test_mixed_except_and_except_star_is_syntax_error(self): 7 errors = [ 8 "try: pass\nexcept ValueError: pass\nexcept* TypeError: pass\n", 9 "try: pass\nexcept* ValueError: pass\nexcept TypeError: pass\n", 10 "try: pass\nexcept ValueError as e: pass\nexcept* TypeError: pass\n", 11 "try: pass\nexcept* ValueError as e: pass\nexcept TypeError: pass\n", 12 "try: pass\nexcept ValueError: pass\nexcept* TypeError as e: pass\n", 13 "try: pass\nexcept* ValueError: pass\nexcept TypeError as e: pass\n", 14 "try: pass\nexcept ValueError: pass\nexcept*: pass\n", 15 "try: pass\nexcept* ValueError: pass\nexcept: pass\n", 16 ] 17 18 for err in errors: 19 with self.assertRaises(SyntaxError): 20 compile(err, "<string>", "exec") 21 22 def test_except_star_ExceptionGroup_is_runtime_error_single(self): 23 with self.assertRaises(TypeError): 24 try: 25 raise OSError("blah") 26 except* ExceptionGroup as e: 27 pass 28 29 def test_except_star_ExceptionGroup_is_runtime_error_tuple(self): 30 with self.assertRaises(TypeError): 31 try: 32 raise ExceptionGroup("eg", [ValueError(42)]) 33 except* (TypeError, ExceptionGroup): 34 pass 35 36 def test_except_star_invalid_exception_type(self): 37 with self.assertRaises(TypeError): 38 try: 39 raise ValueError 40 except* 42: 41 pass 42 43 with self.assertRaises(TypeError): 44 try: 45 raise ValueError 46 except* (ValueError, 42): 47 pass 48 49 50class TestBreakContinueReturnInExceptStarBlock(unittest.TestCase): 51 MSG = (r"'break', 'continue' and 'return'" 52 r" cannot appear in an except\* block") 53 54 def check_invalid(self, src): 55 with self.assertRaisesRegex(SyntaxError, self.MSG): 56 compile(textwrap.dedent(src), "<string>", "exec") 57 58 def test_break_in_except_star(self): 59 self.check_invalid( 60 """ 61 try: 62 raise ValueError 63 except* Exception as e: 64 break 65 """) 66 67 self.check_invalid( 68 """ 69 for i in range(5): 70 try: 71 pass 72 except* Exception as e: 73 if i == 2: 74 break 75 """) 76 77 self.check_invalid( 78 """ 79 for i in range(5): 80 try: 81 pass 82 except* Exception as e: 83 if i == 2: 84 break 85 finally: 86 return 0 87 """) 88 89 90 def test_continue_in_except_star_block_invalid(self): 91 self.check_invalid( 92 """ 93 for i in range(5): 94 try: 95 raise ValueError 96 except* Exception as e: 97 continue 98 """) 99 100 self.check_invalid( 101 """ 102 for i in range(5): 103 try: 104 pass 105 except* Exception as e: 106 if i == 2: 107 continue 108 """) 109 110 self.check_invalid( 111 """ 112 for i in range(5): 113 try: 114 pass 115 except* Exception as e: 116 if i == 2: 117 continue 118 finally: 119 return 0 120 """) 121 122 def test_return_in_except_star_block_invalid(self): 123 self.check_invalid( 124 """ 125 def f(): 126 try: 127 raise ValueError 128 except* Exception as e: 129 return 42 130 """) 131 132 self.check_invalid( 133 """ 134 def f(): 135 try: 136 pass 137 except* Exception as e: 138 return 42 139 finally: 140 finished = True 141 """) 142 143 def test_break_continue_in_except_star_block_valid(self): 144 try: 145 raise ValueError(42) 146 except* Exception as e: 147 count = 0 148 for i in range(5): 149 if i == 0: 150 continue 151 if i == 4: 152 break 153 count += 1 154 155 self.assertEqual(count, 3) 156 self.assertEqual(i, 4) 157 exc = e 158 self.assertIsInstance(exc, ExceptionGroup) 159 160 def test_return_in_except_star_block_valid(self): 161 try: 162 raise ValueError(42) 163 except* Exception as e: 164 def f(x): 165 return 2*x 166 r = f(3) 167 exc = e 168 self.assertEqual(r, 6) 169 self.assertIsInstance(exc, ExceptionGroup) 170 171 172class ExceptStarTest(unittest.TestCase): 173 def assertExceptionIsLike(self, exc, template): 174 if exc is None and template is None: 175 return 176 177 if template is None: 178 self.fail(f"unexpected exception: {exc}") 179 180 if exc is None: 181 self.fail(f"expected an exception like {template!r}, got None") 182 183 if not isinstance(exc, ExceptionGroup): 184 self.assertEqual(exc.__class__, template.__class__) 185 self.assertEqual(exc.args[0], template.args[0]) 186 else: 187 self.assertEqual(exc.message, template.message) 188 self.assertEqual(len(exc.exceptions), len(template.exceptions)) 189 for e, t in zip(exc.exceptions, template.exceptions): 190 self.assertExceptionIsLike(e, t) 191 192 def assertMetadataEqual(self, e1, e2): 193 if e1 is None or e2 is None: 194 self.assertTrue(e1 is None and e2 is None) 195 else: 196 self.assertEqual(e1.__context__, e2.__context__) 197 self.assertEqual(e1.__cause__, e2.__cause__) 198 self.assertEqual(e1.__traceback__, e2.__traceback__) 199 200 def assertMetadataNotEqual(self, e1, e2): 201 if e1 is None or e2 is None: 202 self.assertNotEqual(e1, e2) 203 else: 204 return not (e1.__context__ == e2.__context__ 205 and e1.__cause__ == e2.__cause__ 206 and e1.__traceback__ == e2.__traceback__) 207 208 209class TestExceptStarSplitSemantics(ExceptStarTest): 210 def doSplitTestNamed(self, exc, T, match_template, rest_template): 211 initial_sys_exception = sys.exception() 212 sys_exception = match = rest = None 213 try: 214 try: 215 raise exc 216 except* T as e: 217 sys_exception = sys.exception() 218 match = e 219 except BaseException as e: 220 rest = e 221 222 self.assertEqual(sys_exception, match) 223 self.assertExceptionIsLike(match, match_template) 224 self.assertExceptionIsLike(rest, rest_template) 225 self.assertEqual(sys.exception(), initial_sys_exception) 226 227 def doSplitTestUnnamed(self, exc, T, match_template, rest_template): 228 initial_sys_exception = sys.exception() 229 sys_exception = match = rest = None 230 try: 231 try: 232 raise exc 233 except* T: 234 sys_exception = match = sys.exception() 235 else: 236 if rest_template: 237 self.fail("Exception not raised") 238 except BaseException as e: 239 rest = e 240 self.assertExceptionIsLike(match, match_template) 241 self.assertExceptionIsLike(rest, rest_template) 242 self.assertEqual(sys.exception(), initial_sys_exception) 243 244 def doSplitTestInExceptHandler(self, exc, T, match_template, rest_template): 245 try: 246 raise ExceptionGroup('eg', [TypeError(1), ValueError(2)]) 247 except Exception: 248 self.doSplitTestNamed(exc, T, match_template, rest_template) 249 self.doSplitTestUnnamed(exc, T, match_template, rest_template) 250 251 def doSplitTestInExceptStarHandler(self, exc, T, match_template, rest_template): 252 try: 253 raise ExceptionGroup('eg', [TypeError(1), ValueError(2)]) 254 except* Exception: 255 self.doSplitTestNamed(exc, T, match_template, rest_template) 256 self.doSplitTestUnnamed(exc, T, match_template, rest_template) 257 258 def doSplitTest(self, exc, T, match_template, rest_template): 259 self.doSplitTestNamed(exc, T, match_template, rest_template) 260 self.doSplitTestUnnamed(exc, T, match_template, rest_template) 261 self.doSplitTestInExceptHandler(exc, T, match_template, rest_template) 262 self.doSplitTestInExceptStarHandler(exc, T, match_template, rest_template) 263 264 def test_no_match_single_type(self): 265 self.doSplitTest( 266 ExceptionGroup("test1", [ValueError("V"), TypeError("T")]), 267 SyntaxError, 268 None, 269 ExceptionGroup("test1", [ValueError("V"), TypeError("T")])) 270 271 def test_match_single_type(self): 272 self.doSplitTest( 273 ExceptionGroup("test2", [ValueError("V1"), ValueError("V2")]), 274 ValueError, 275 ExceptionGroup("test2", [ValueError("V1"), ValueError("V2")]), 276 None) 277 278 def test_match_single_type_partial_match(self): 279 self.doSplitTest( 280 ExceptionGroup( 281 "test3", 282 [ValueError("V1"), OSError("OS"), ValueError("V2")]), 283 ValueError, 284 ExceptionGroup("test3", [ValueError("V1"), ValueError("V2")]), 285 ExceptionGroup("test3", [OSError("OS")])) 286 287 def test_match_single_type_nested(self): 288 self.doSplitTest( 289 ExceptionGroup( 290 "g1", [ 291 ValueError("V1"), 292 OSError("OS1"), 293 ExceptionGroup( 294 "g2", [ 295 OSError("OS2"), 296 ValueError("V2"), 297 TypeError("T")])]), 298 ValueError, 299 ExceptionGroup( 300 "g1", [ 301 ValueError("V1"), 302 ExceptionGroup("g2", [ValueError("V2")])]), 303 ExceptionGroup("g1", [ 304 OSError("OS1"), 305 ExceptionGroup("g2", [ 306 OSError("OS2"), TypeError("T")])])) 307 308 def test_match_type_tuple_nested(self): 309 self.doSplitTest( 310 ExceptionGroup( 311 "h1", [ 312 ValueError("V1"), 313 OSError("OS1"), 314 ExceptionGroup( 315 "h2", [OSError("OS2"), ValueError("V2"), TypeError("T")])]), 316 (ValueError, TypeError), 317 ExceptionGroup( 318 "h1", [ 319 ValueError("V1"), 320 ExceptionGroup("h2", [ValueError("V2"), TypeError("T")])]), 321 ExceptionGroup( 322 "h1", [ 323 OSError("OS1"), 324 ExceptionGroup("h2", [OSError("OS2")])])) 325 326 def test_empty_groups_removed(self): 327 self.doSplitTest( 328 ExceptionGroup( 329 "eg", [ 330 ExceptionGroup("i1", [ValueError("V1")]), 331 ExceptionGroup("i2", [ValueError("V2"), TypeError("T1")]), 332 ExceptionGroup("i3", [TypeError("T2")])]), 333 TypeError, 334 ExceptionGroup("eg", [ 335 ExceptionGroup("i2", [TypeError("T1")]), 336 ExceptionGroup("i3", [TypeError("T2")])]), 337 ExceptionGroup("eg", [ 338 ExceptionGroup("i1", [ValueError("V1")]), 339 ExceptionGroup("i2", [ValueError("V2")])])) 340 341 def test_singleton_groups_are_kept(self): 342 self.doSplitTest( 343 ExceptionGroup("j1", [ 344 ExceptionGroup("j2", [ 345 ExceptionGroup("j3", [ValueError("V1")]), 346 ExceptionGroup("j4", [TypeError("T")])])]), 347 TypeError, 348 ExceptionGroup( 349 "j1", 350 [ExceptionGroup("j2", [ExceptionGroup("j4", [TypeError("T")])])]), 351 ExceptionGroup( 352 "j1", 353 [ExceptionGroup("j2", [ExceptionGroup("j3", [ValueError("V1")])])])) 354 355 def test_naked_exception_matched_wrapped1(self): 356 self.doSplitTest( 357 ValueError("V"), 358 ValueError, 359 ExceptionGroup("", [ValueError("V")]), 360 None) 361 362 def test_naked_exception_matched_wrapped2(self): 363 self.doSplitTest( 364 ValueError("V"), 365 Exception, 366 ExceptionGroup("", [ValueError("V")]), 367 None) 368 369 def test_exception_group_except_star_Exception_not_wrapped(self): 370 self.doSplitTest( 371 ExceptionGroup("eg", [ValueError("V")]), 372 Exception, 373 ExceptionGroup("eg", [ValueError("V")]), 374 None) 375 376 def test_plain_exception_not_matched(self): 377 self.doSplitTest( 378 ValueError("V"), 379 TypeError, 380 None, 381 ValueError("V")) 382 383 def test_match__supertype(self): 384 self.doSplitTest( 385 ExceptionGroup("st", [BlockingIOError("io"), TypeError("T")]), 386 OSError, 387 ExceptionGroup("st", [BlockingIOError("io")]), 388 ExceptionGroup("st", [TypeError("T")])) 389 390 def test_multiple_matches_named(self): 391 try: 392 raise ExceptionGroup("mmn", [OSError("os"), BlockingIOError("io")]) 393 except* BlockingIOError as e: 394 self.assertExceptionIsLike(e, 395 ExceptionGroup("mmn", [BlockingIOError("io")])) 396 except* OSError as e: 397 self.assertExceptionIsLike(e, 398 ExceptionGroup("mmn", [OSError("os")])) 399 else: 400 self.fail("Exception not raised") 401 402 def test_multiple_matches_unnamed(self): 403 try: 404 raise ExceptionGroup("mmu", [OSError("os"), BlockingIOError("io")]) 405 except* BlockingIOError: 406 e = sys.exception() 407 self.assertExceptionIsLike(e, 408 ExceptionGroup("mmu", [BlockingIOError("io")])) 409 except* OSError: 410 e = sys.exception() 411 self.assertExceptionIsLike(e, 412 ExceptionGroup("mmu", [OSError("os")])) 413 else: 414 self.fail("Exception not raised") 415 416 def test_first_match_wins_named(self): 417 try: 418 raise ExceptionGroup("fst", [BlockingIOError("io")]) 419 except* OSError as e: 420 self.assertExceptionIsLike(e, 421 ExceptionGroup("fst", [BlockingIOError("io")])) 422 except* BlockingIOError: 423 self.fail("Should have been matched as OSError") 424 else: 425 self.fail("Exception not raised") 426 427 def test_first_match_wins_unnamed(self): 428 try: 429 raise ExceptionGroup("fstu", [BlockingIOError("io")]) 430 except* OSError: 431 e = sys.exception() 432 self.assertExceptionIsLike(e, 433 ExceptionGroup("fstu", [BlockingIOError("io")])) 434 except* BlockingIOError: 435 pass 436 else: 437 self.fail("Exception not raised") 438 439 def test_nested_except_stars(self): 440 try: 441 raise ExceptionGroup("n", [BlockingIOError("io")]) 442 except* BlockingIOError: 443 try: 444 raise ExceptionGroup("n", [ValueError("io")]) 445 except* ValueError: 446 pass 447 else: 448 self.fail("Exception not raised") 449 e = sys.exception() 450 self.assertExceptionIsLike(e, 451 ExceptionGroup("n", [BlockingIOError("io")])) 452 else: 453 self.fail("Exception not raised") 454 455 def test_nested_in_loop(self): 456 for _ in range(2): 457 try: 458 raise ExceptionGroup("nl", [BlockingIOError("io")]) 459 except* BlockingIOError: 460 pass 461 else: 462 self.fail("Exception not raised") 463 464 465class TestExceptStarReraise(ExceptStarTest): 466 def test_reraise_all_named(self): 467 try: 468 try: 469 raise ExceptionGroup( 470 "eg", [TypeError(1), ValueError(2), OSError(3)]) 471 except* TypeError as e: 472 raise 473 except* ValueError as e: 474 raise 475 # OSError not handled 476 except ExceptionGroup as e: 477 exc = e 478 479 self.assertExceptionIsLike( 480 exc, 481 ExceptionGroup("eg", [TypeError(1), ValueError(2), OSError(3)])) 482 483 def test_reraise_all_unnamed(self): 484 try: 485 try: 486 raise ExceptionGroup( 487 "eg", [TypeError(1), ValueError(2), OSError(3)]) 488 except* TypeError: 489 raise 490 except* ValueError: 491 raise 492 # OSError not handled 493 except ExceptionGroup as e: 494 exc = e 495 496 self.assertExceptionIsLike( 497 exc, 498 ExceptionGroup("eg", [TypeError(1), ValueError(2), OSError(3)])) 499 500 def test_reraise_some_handle_all_named(self): 501 try: 502 try: 503 raise ExceptionGroup( 504 "eg", [TypeError(1), ValueError(2), OSError(3)]) 505 except* TypeError as e: 506 raise 507 except* ValueError as e: 508 pass 509 # OSError not handled 510 except ExceptionGroup as e: 511 exc = e 512 513 self.assertExceptionIsLike( 514 exc, ExceptionGroup("eg", [TypeError(1), OSError(3)])) 515 516 def test_reraise_partial_handle_all_unnamed(self): 517 try: 518 try: 519 raise ExceptionGroup( 520 "eg", [TypeError(1), ValueError(2)]) 521 except* TypeError: 522 raise 523 except* ValueError: 524 pass 525 except ExceptionGroup as e: 526 exc = e 527 528 self.assertExceptionIsLike( 529 exc, ExceptionGroup("eg", [TypeError(1)])) 530 531 def test_reraise_partial_handle_some_named(self): 532 try: 533 try: 534 raise ExceptionGroup( 535 "eg", [TypeError(1), ValueError(2), OSError(3)]) 536 except* TypeError as e: 537 raise 538 except* ValueError as e: 539 pass 540 # OSError not handled 541 except ExceptionGroup as e: 542 exc = e 543 544 self.assertExceptionIsLike( 545 exc, ExceptionGroup("eg", [TypeError(1), OSError(3)])) 546 547 def test_reraise_partial_handle_some_unnamed(self): 548 try: 549 try: 550 raise ExceptionGroup( 551 "eg", [TypeError(1), ValueError(2), OSError(3)]) 552 except* TypeError: 553 raise 554 except* ValueError: 555 pass 556 except ExceptionGroup as e: 557 exc = e 558 559 self.assertExceptionIsLike( 560 exc, ExceptionGroup("eg", [TypeError(1), OSError(3)])) 561 562 def test_reraise_plain_exception_named(self): 563 try: 564 try: 565 raise ValueError(42) 566 except* ValueError as e: 567 raise 568 except ExceptionGroup as e: 569 exc = e 570 571 self.assertExceptionIsLike( 572 exc, ExceptionGroup("", [ValueError(42)])) 573 574 def test_reraise_plain_exception_unnamed(self): 575 try: 576 try: 577 raise ValueError(42) 578 except* ValueError: 579 raise 580 except ExceptionGroup as e: 581 exc = e 582 583 self.assertExceptionIsLike( 584 exc, ExceptionGroup("", [ValueError(42)])) 585 586 587class TestExceptStarRaise(ExceptStarTest): 588 def test_raise_named(self): 589 orig = ExceptionGroup("eg", [ValueError(1), OSError(2)]) 590 try: 591 try: 592 raise orig 593 except* OSError as e: 594 raise TypeError(3) 595 except ExceptionGroup as e: 596 exc = e 597 598 self.assertExceptionIsLike( 599 exc, 600 ExceptionGroup( 601 "", [TypeError(3), ExceptionGroup("eg", [ValueError(1)])])) 602 603 self.assertExceptionIsLike( 604 exc.exceptions[0].__context__, 605 ExceptionGroup("eg", [OSError(2)])) 606 607 self.assertMetadataNotEqual(orig, exc) 608 self.assertMetadataEqual(orig, exc.exceptions[0].__context__) 609 610 def test_raise_unnamed(self): 611 orig = ExceptionGroup("eg", [ValueError(1), OSError(2)]) 612 try: 613 try: 614 raise orig 615 except* OSError: 616 raise TypeError(3) 617 except ExceptionGroup as e: 618 exc = e 619 620 self.assertExceptionIsLike( 621 exc, 622 ExceptionGroup( 623 "", [TypeError(3), ExceptionGroup("eg", [ValueError(1)])])) 624 625 self.assertExceptionIsLike( 626 exc.exceptions[0].__context__, 627 ExceptionGroup("eg", [OSError(2)])) 628 629 self.assertMetadataNotEqual(orig, exc) 630 self.assertMetadataEqual(orig, exc.exceptions[0].__context__) 631 632 def test_raise_handle_all_raise_one_named(self): 633 orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) 634 try: 635 try: 636 raise orig 637 except* (TypeError, ValueError) as e: 638 raise SyntaxError(3) 639 except SyntaxError as e: 640 exc = e 641 642 self.assertExceptionIsLike(exc, SyntaxError(3)) 643 644 self.assertExceptionIsLike( 645 exc.__context__, 646 ExceptionGroup("eg", [TypeError(1), ValueError(2)])) 647 648 self.assertMetadataNotEqual(orig, exc) 649 self.assertMetadataEqual(orig, exc.__context__) 650 651 def test_raise_handle_all_raise_one_unnamed(self): 652 orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) 653 try: 654 try: 655 raise orig 656 except* (TypeError, ValueError) as e: 657 raise SyntaxError(3) 658 except SyntaxError as e: 659 exc = e 660 661 self.assertExceptionIsLike(exc, SyntaxError(3)) 662 663 self.assertExceptionIsLike( 664 exc.__context__, 665 ExceptionGroup("eg", [TypeError(1), ValueError(2)])) 666 667 self.assertMetadataNotEqual(orig, exc) 668 self.assertMetadataEqual(orig, exc.__context__) 669 670 def test_raise_handle_all_raise_two_named(self): 671 orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) 672 try: 673 try: 674 raise orig 675 except* TypeError as e: 676 raise SyntaxError(3) 677 except* ValueError as e: 678 raise SyntaxError(4) 679 except ExceptionGroup as e: 680 exc = e 681 682 self.assertExceptionIsLike( 683 exc, ExceptionGroup("", [SyntaxError(3), SyntaxError(4)])) 684 685 self.assertExceptionIsLike( 686 exc.exceptions[0].__context__, 687 ExceptionGroup("eg", [TypeError(1)])) 688 689 self.assertExceptionIsLike( 690 exc.exceptions[1].__context__, 691 ExceptionGroup("eg", [ValueError(2)])) 692 693 self.assertMetadataNotEqual(orig, exc) 694 self.assertMetadataEqual(orig, exc.exceptions[0].__context__) 695 self.assertMetadataEqual(orig, exc.exceptions[1].__context__) 696 697 def test_raise_handle_all_raise_two_unnamed(self): 698 orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) 699 try: 700 try: 701 raise orig 702 except* TypeError: 703 raise SyntaxError(3) 704 except* ValueError: 705 raise SyntaxError(4) 706 except ExceptionGroup as e: 707 exc = e 708 709 self.assertExceptionIsLike( 710 exc, ExceptionGroup("", [SyntaxError(3), SyntaxError(4)])) 711 712 self.assertExceptionIsLike( 713 exc.exceptions[0].__context__, 714 ExceptionGroup("eg", [TypeError(1)])) 715 716 self.assertExceptionIsLike( 717 exc.exceptions[1].__context__, 718 ExceptionGroup("eg", [ValueError(2)])) 719 720 self.assertMetadataNotEqual(orig, exc) 721 self.assertMetadataEqual(orig, exc.exceptions[0].__context__) 722 self.assertMetadataEqual(orig, exc.exceptions[1].__context__) 723 724 725class TestExceptStarRaiseFrom(ExceptStarTest): 726 def test_raise_named(self): 727 orig = ExceptionGroup("eg", [ValueError(1), OSError(2)]) 728 try: 729 try: 730 raise orig 731 except* OSError as e: 732 raise TypeError(3) from e 733 except ExceptionGroup as e: 734 exc = e 735 736 self.assertExceptionIsLike( 737 exc, 738 ExceptionGroup( 739 "", [TypeError(3), ExceptionGroup("eg", [ValueError(1)])])) 740 741 self.assertExceptionIsLike( 742 exc.exceptions[0].__context__, 743 ExceptionGroup("eg", [OSError(2)])) 744 745 self.assertExceptionIsLike( 746 exc.exceptions[0].__cause__, 747 ExceptionGroup("eg", [OSError(2)])) 748 749 self.assertMetadataNotEqual(orig, exc) 750 self.assertMetadataEqual(orig, exc.exceptions[0].__context__) 751 self.assertMetadataEqual(orig, exc.exceptions[0].__cause__) 752 self.assertMetadataNotEqual(orig, exc.exceptions[1].__context__) 753 self.assertMetadataNotEqual(orig, exc.exceptions[1].__cause__) 754 755 def test_raise_unnamed(self): 756 orig = ExceptionGroup("eg", [ValueError(1), OSError(2)]) 757 try: 758 try: 759 raise orig 760 except* OSError: 761 e = sys.exception() 762 raise TypeError(3) from e 763 except ExceptionGroup as e: 764 exc = e 765 766 self.assertExceptionIsLike( 767 exc, 768 ExceptionGroup( 769 "", [TypeError(3), ExceptionGroup("eg", [ValueError(1)])])) 770 771 self.assertExceptionIsLike( 772 exc.exceptions[0].__context__, 773 ExceptionGroup("eg", [OSError(2)])) 774 775 self.assertExceptionIsLike( 776 exc.exceptions[0].__cause__, 777 ExceptionGroup("eg", [OSError(2)])) 778 779 self.assertMetadataNotEqual(orig, exc) 780 self.assertMetadataEqual(orig, exc.exceptions[0].__context__) 781 self.assertMetadataEqual(orig, exc.exceptions[0].__cause__) 782 self.assertMetadataNotEqual(orig, exc.exceptions[1].__context__) 783 self.assertMetadataNotEqual(orig, exc.exceptions[1].__cause__) 784 785 def test_raise_handle_all_raise_one_named(self): 786 orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) 787 try: 788 try: 789 raise orig 790 except* (TypeError, ValueError) as e: 791 raise SyntaxError(3) from e 792 except SyntaxError as e: 793 exc = e 794 795 self.assertExceptionIsLike(exc, SyntaxError(3)) 796 797 self.assertExceptionIsLike( 798 exc.__context__, 799 ExceptionGroup("eg", [TypeError(1), ValueError(2)])) 800 801 self.assertExceptionIsLike( 802 exc.__cause__, 803 ExceptionGroup("eg", [TypeError(1), ValueError(2)])) 804 805 self.assertMetadataNotEqual(orig, exc) 806 self.assertMetadataEqual(orig, exc.__context__) 807 self.assertMetadataEqual(orig, exc.__cause__) 808 809 def test_raise_handle_all_raise_one_unnamed(self): 810 orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) 811 try: 812 try: 813 raise orig 814 except* (TypeError, ValueError) as e: 815 e = sys.exception() 816 raise SyntaxError(3) from e 817 except SyntaxError as e: 818 exc = e 819 820 self.assertExceptionIsLike(exc, SyntaxError(3)) 821 822 self.assertExceptionIsLike( 823 exc.__context__, 824 ExceptionGroup("eg", [TypeError(1), ValueError(2)])) 825 826 self.assertExceptionIsLike( 827 exc.__cause__, 828 ExceptionGroup("eg", [TypeError(1), ValueError(2)])) 829 830 self.assertMetadataNotEqual(orig, exc) 831 self.assertMetadataEqual(orig, exc.__context__) 832 self.assertMetadataEqual(orig, exc.__cause__) 833 834 def test_raise_handle_all_raise_two_named(self): 835 orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) 836 try: 837 try: 838 raise orig 839 except* TypeError as e: 840 raise SyntaxError(3) from e 841 except* ValueError as e: 842 raise SyntaxError(4) from e 843 except ExceptionGroup as e: 844 exc = e 845 846 self.assertExceptionIsLike( 847 exc, ExceptionGroup("", [SyntaxError(3), SyntaxError(4)])) 848 849 self.assertExceptionIsLike( 850 exc.exceptions[0].__context__, 851 ExceptionGroup("eg", [TypeError(1)])) 852 853 self.assertExceptionIsLike( 854 exc.exceptions[0].__cause__, 855 ExceptionGroup("eg", [TypeError(1)])) 856 857 self.assertExceptionIsLike( 858 exc.exceptions[1].__context__, 859 ExceptionGroup("eg", [ValueError(2)])) 860 861 self.assertExceptionIsLike( 862 exc.exceptions[1].__cause__, 863 ExceptionGroup("eg", [ValueError(2)])) 864 865 self.assertMetadataNotEqual(orig, exc) 866 self.assertMetadataEqual(orig, exc.exceptions[0].__context__) 867 self.assertMetadataEqual(orig, exc.exceptions[0].__cause__) 868 869 def test_raise_handle_all_raise_two_unnamed(self): 870 orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)]) 871 try: 872 try: 873 raise orig 874 except* TypeError: 875 e = sys.exception() 876 raise SyntaxError(3) from e 877 except* ValueError: 878 e = sys.exception() 879 raise SyntaxError(4) from e 880 except ExceptionGroup as e: 881 exc = e 882 883 self.assertExceptionIsLike( 884 exc, ExceptionGroup("", [SyntaxError(3), SyntaxError(4)])) 885 886 self.assertExceptionIsLike( 887 exc.exceptions[0].__context__, 888 ExceptionGroup("eg", [TypeError(1)])) 889 890 self.assertExceptionIsLike( 891 exc.exceptions[0].__cause__, 892 ExceptionGroup("eg", [TypeError(1)])) 893 894 self.assertExceptionIsLike( 895 exc.exceptions[1].__context__, 896 ExceptionGroup("eg", [ValueError(2)])) 897 898 self.assertExceptionIsLike( 899 exc.exceptions[1].__cause__, 900 ExceptionGroup("eg", [ValueError(2)])) 901 902 self.assertMetadataNotEqual(orig, exc) 903 self.assertMetadataEqual(orig, exc.exceptions[0].__context__) 904 self.assertMetadataEqual(orig, exc.exceptions[0].__cause__) 905 self.assertMetadataEqual(orig, exc.exceptions[1].__context__) 906 self.assertMetadataEqual(orig, exc.exceptions[1].__cause__) 907 908 909class TestExceptStarExceptionGroupSubclass(ExceptStarTest): 910 def test_except_star_EG_subclass(self): 911 class EG(ExceptionGroup): 912 def __new__(cls, message, excs, code): 913 obj = super().__new__(cls, message, excs) 914 obj.code = code 915 return obj 916 917 def derive(self, excs): 918 return EG(self.message, excs, self.code) 919 920 try: 921 try: 922 try: 923 try: 924 raise TypeError(2) 925 except TypeError as te: 926 raise EG("nested", [te], 101) from None 927 except EG as nested: 928 try: 929 raise ValueError(1) 930 except ValueError as ve: 931 raise EG("eg", [ve, nested], 42) 932 except* ValueError as eg: 933 veg = eg 934 except EG as eg: 935 teg = eg 936 937 self.assertIsInstance(veg, EG) 938 self.assertIsInstance(teg, EG) 939 self.assertIsInstance(teg.exceptions[0], EG) 940 self.assertMetadataEqual(veg, teg) 941 self.assertEqual(veg.code, 42) 942 self.assertEqual(teg.code, 42) 943 self.assertEqual(teg.exceptions[0].code, 101) 944 945 def test_falsy_exception_group_subclass(self): 946 class FalsyEG(ExceptionGroup): 947 def __bool__(self): 948 return False 949 950 def derive(self, excs): 951 return FalsyEG(self.message, excs) 952 953 try: 954 try: 955 raise FalsyEG("eg", [TypeError(1), ValueError(2)]) 956 except *TypeError as e: 957 tes = e 958 raise 959 except *ValueError as e: 960 ves = e 961 pass 962 except Exception as e: 963 exc = e 964 965 for e in [tes, ves, exc]: 966 self.assertFalse(e) 967 self.assertIsInstance(e, FalsyEG) 968 969 self.assertExceptionIsLike(exc, FalsyEG("eg", [TypeError(1)])) 970 self.assertExceptionIsLike(tes, FalsyEG("eg", [TypeError(1)])) 971 self.assertExceptionIsLike(ves, FalsyEG("eg", [ValueError(2)])) 972 973 974class TestExceptStarCleanup(ExceptStarTest): 975 def test_sys_exception_restored(self): 976 try: 977 try: 978 raise ValueError(42) 979 except: 980 try: 981 raise TypeError(int) 982 except* Exception: 983 pass 984 1/0 985 except Exception as e: 986 exc = e 987 988 self.assertExceptionIsLike(exc, ZeroDivisionError('division by zero')) 989 self.assertExceptionIsLike(exc.__context__, ValueError(42)) 990 self.assertEqual(sys.exception(), None) 991 992 993class TestExceptStar_WeirdLeafExceptions(ExceptStarTest): 994 # Test that except* works when leaf exceptions are 995 # unhashable or have a bad custom __eq__ 996 997 class UnhashableExc(ValueError): 998 __hash__ = None 999 1000 class AlwaysEqualExc(ValueError): 1001 def __eq__(self, other): 1002 return True 1003 1004 class NeverEqualExc(ValueError): 1005 def __eq__(self, other): 1006 return False 1007 1008 class BrokenEqualExc(ValueError): 1009 def __eq__(self, other): 1010 raise RuntimeError() 1011 1012 def setUp(self): 1013 self.bad_types = [self.UnhashableExc, 1014 self.AlwaysEqualExc, 1015 self.NeverEqualExc, 1016 self.BrokenEqualExc] 1017 1018 def except_type(self, eg, type): 1019 match, rest = None, None 1020 try: 1021 try: 1022 raise eg 1023 except* type as e: 1024 match = e 1025 except Exception as e: 1026 rest = e 1027 return match, rest 1028 1029 def test_catch_unhashable_leaf_exception(self): 1030 for Bad in self.bad_types: 1031 with self.subTest(Bad): 1032 eg = ExceptionGroup("eg", [TypeError(1), Bad(2)]) 1033 match, rest = self.except_type(eg, Bad) 1034 self.assertExceptionIsLike( 1035 match, ExceptionGroup("eg", [Bad(2)])) 1036 self.assertExceptionIsLike( 1037 rest, ExceptionGroup("eg", [TypeError(1)])) 1038 1039 def test_propagate_unhashable_leaf(self): 1040 for Bad in self.bad_types: 1041 with self.subTest(Bad): 1042 eg = ExceptionGroup("eg", [TypeError(1), Bad(2)]) 1043 match, rest = self.except_type(eg, TypeError) 1044 self.assertExceptionIsLike( 1045 match, ExceptionGroup("eg", [TypeError(1)])) 1046 self.assertExceptionIsLike( 1047 rest, ExceptionGroup("eg", [Bad(2)])) 1048 1049 def test_catch_nothing_unhashable_leaf(self): 1050 for Bad in self.bad_types: 1051 with self.subTest(Bad): 1052 eg = ExceptionGroup("eg", [TypeError(1), Bad(2)]) 1053 match, rest = self.except_type(eg, OSError) 1054 self.assertIsNone(match) 1055 self.assertExceptionIsLike(rest, eg) 1056 1057 def test_catch_everything_unhashable_leaf(self): 1058 for Bad in self.bad_types: 1059 with self.subTest(Bad): 1060 eg = ExceptionGroup("eg", [TypeError(1), Bad(2)]) 1061 match, rest = self.except_type(eg, Exception) 1062 self.assertExceptionIsLike(match, eg) 1063 self.assertIsNone(rest) 1064 1065 def test_reraise_unhashable_leaf(self): 1066 for Bad in self.bad_types: 1067 with self.subTest(Bad): 1068 eg = ExceptionGroup( 1069 "eg", [TypeError(1), Bad(2), ValueError(3)]) 1070 1071 try: 1072 try: 1073 raise eg 1074 except* TypeError: 1075 pass 1076 except* Bad: 1077 raise 1078 except Exception as e: 1079 exc = e 1080 1081 self.assertExceptionIsLike( 1082 exc, ExceptionGroup("eg", [Bad(2), ValueError(3)])) 1083 1084 1085class TestExceptStar_WeirdExceptionGroupSubclass(ExceptStarTest): 1086 # Test that except* works with exception groups that are 1087 # unhashable or have a bad custom __eq__ 1088 1089 class UnhashableEG(ExceptionGroup): 1090 __hash__ = None 1091 1092 def derive(self, excs): 1093 return type(self)(self.message, excs) 1094 1095 class AlwaysEqualEG(ExceptionGroup): 1096 def __eq__(self, other): 1097 return True 1098 1099 def derive(self, excs): 1100 return type(self)(self.message, excs) 1101 1102 class NeverEqualEG(ExceptionGroup): 1103 def __eq__(self, other): 1104 return False 1105 1106 def derive(self, excs): 1107 return type(self)(self.message, excs) 1108 1109 class BrokenEqualEG(ExceptionGroup): 1110 def __eq__(self, other): 1111 raise RuntimeError() 1112 1113 def derive(self, excs): 1114 return type(self)(self.message, excs) 1115 1116 def setUp(self): 1117 self.bad_types = [self.UnhashableEG, 1118 self.AlwaysEqualEG, 1119 self.NeverEqualEG, 1120 self.BrokenEqualEG] 1121 1122 def except_type(self, eg, type): 1123 match, rest = None, None 1124 try: 1125 try: 1126 raise eg 1127 except* type as e: 1128 match = e 1129 except Exception as e: 1130 rest = e 1131 return match, rest 1132 1133 def test_catch_some_unhashable_exception_group_subclass(self): 1134 for BadEG in self.bad_types: 1135 with self.subTest(BadEG): 1136 eg = BadEG("eg", 1137 [TypeError(1), 1138 BadEG("nested", [ValueError(2)])]) 1139 1140 match, rest = self.except_type(eg, TypeError) 1141 self.assertExceptionIsLike(match, BadEG("eg", [TypeError(1)])) 1142 self.assertExceptionIsLike(rest, 1143 BadEG("eg", [BadEG("nested", [ValueError(2)])])) 1144 1145 def test_catch_none_unhashable_exception_group_subclass(self): 1146 for BadEG in self.bad_types: 1147 with self.subTest(BadEG): 1148 1149 eg = BadEG("eg", 1150 [TypeError(1), 1151 BadEG("nested", [ValueError(2)])]) 1152 1153 match, rest = self.except_type(eg, OSError) 1154 self.assertIsNone(match) 1155 self.assertExceptionIsLike(rest, eg) 1156 1157 def test_catch_all_unhashable_exception_group_subclass(self): 1158 for BadEG in self.bad_types: 1159 with self.subTest(BadEG): 1160 1161 eg = BadEG("eg", 1162 [TypeError(1), 1163 BadEG("nested", [ValueError(2)])]) 1164 1165 match, rest = self.except_type(eg, Exception) 1166 self.assertExceptionIsLike(match, eg) 1167 self.assertIsNone(rest) 1168 1169 def test_reraise_unhashable_eg(self): 1170 for BadEG in self.bad_types: 1171 with self.subTest(BadEG): 1172 1173 eg = BadEG("eg", 1174 [TypeError(1), ValueError(2), 1175 BadEG("nested", [ValueError(3), OSError(4)])]) 1176 1177 try: 1178 try: 1179 raise eg 1180 except* ValueError: 1181 pass 1182 except* OSError: 1183 raise 1184 except Exception as e: 1185 exc = e 1186 1187 self.assertExceptionIsLike( 1188 exc, BadEG("eg", [TypeError(1), 1189 BadEG("nested", [OSError(4)])])) 1190 1191 1192if __name__ == '__main__': 1193 unittest.main() 1194