| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203 |
- import sys
- import unittest
- import textwrap
- class TestInvalidExceptStar(unittest.TestCase):
- def test_mixed_except_and_except_star_is_syntax_error(self):
- errors = [
- "try: pass\nexcept ValueError: pass\nexcept* TypeError: pass\n",
- "try: pass\nexcept* ValueError: pass\nexcept TypeError: pass\n",
- "try: pass\nexcept ValueError as e: pass\nexcept* TypeError: pass\n",
- "try: pass\nexcept* ValueError as e: pass\nexcept TypeError: pass\n",
- "try: pass\nexcept ValueError: pass\nexcept* TypeError as e: pass\n",
- "try: pass\nexcept* ValueError: pass\nexcept TypeError as e: pass\n",
- "try: pass\nexcept ValueError: pass\nexcept*: pass\n",
- "try: pass\nexcept* ValueError: pass\nexcept: pass\n",
- ]
- for err in errors:
- with self.assertRaises(SyntaxError):
- compile(err, "<string>", "exec")
- def test_except_star_ExceptionGroup_is_runtime_error_single(self):
- with self.assertRaises(TypeError):
- try:
- raise OSError("blah")
- except* ExceptionGroup as e:
- pass
- def test_except_star_ExceptionGroup_is_runtime_error_tuple(self):
- with self.assertRaises(TypeError):
- try:
- raise ExceptionGroup("eg", [ValueError(42)])
- except* (TypeError, ExceptionGroup):
- pass
- def test_except_star_invalid_exception_type(self):
- with self.assertRaises(TypeError):
- try:
- raise ValueError
- except* 42:
- pass
- with self.assertRaises(TypeError):
- try:
- raise ValueError
- except* (ValueError, 42):
- pass
- class TestBreakContinueReturnInExceptStarBlock(unittest.TestCase):
- MSG = (r"'break', 'continue' and 'return'"
- r" cannot appear in an except\* block")
- def check_invalid(self, src):
- with self.assertRaisesRegex(SyntaxError, self.MSG):
- compile(textwrap.dedent(src), "<string>", "exec")
- def test_break_in_except_star(self):
- self.check_invalid(
- """
- try:
- raise ValueError
- except* Exception as e:
- break
- """)
- self.check_invalid(
- """
- for i in range(5):
- try:
- pass
- except* Exception as e:
- if i == 2:
- break
- """)
- self.check_invalid(
- """
- for i in range(5):
- try:
- pass
- except* Exception as e:
- if i == 2:
- break
- finally:
- return 0
- """)
- def test_continue_in_except_star_block_invalid(self):
- self.check_invalid(
- """
- for i in range(5):
- try:
- raise ValueError
- except* Exception as e:
- continue
- """)
- self.check_invalid(
- """
- for i in range(5):
- try:
- pass
- except* Exception as e:
- if i == 2:
- continue
- """)
- self.check_invalid(
- """
- for i in range(5):
- try:
- pass
- except* Exception as e:
- if i == 2:
- continue
- finally:
- return 0
- """)
- def test_return_in_except_star_block_invalid(self):
- self.check_invalid(
- """
- def f():
- try:
- raise ValueError
- except* Exception as e:
- return 42
- """)
- self.check_invalid(
- """
- def f():
- try:
- pass
- except* Exception as e:
- return 42
- finally:
- finished = True
- """)
- def test_break_continue_in_except_star_block_valid(self):
- try:
- raise ValueError(42)
- except* Exception as e:
- count = 0
- for i in range(5):
- if i == 0:
- continue
- if i == 4:
- break
- count += 1
- self.assertEqual(count, 3)
- self.assertEqual(i, 4)
- exc = e
- self.assertIsInstance(exc, ExceptionGroup)
- def test_return_in_except_star_block_valid(self):
- try:
- raise ValueError(42)
- except* Exception as e:
- def f(x):
- return 2*x
- r = f(3)
- exc = e
- self.assertEqual(r, 6)
- self.assertIsInstance(exc, ExceptionGroup)
- class ExceptStarTest(unittest.TestCase):
- def assertExceptionIsLike(self, exc, template):
- if exc is None and template is None:
- return
- if template is None:
- self.fail(f"unexpected exception: {exc}")
- if exc is None:
- self.fail(f"expected an exception like {template!r}, got None")
- if not isinstance(exc, ExceptionGroup):
- self.assertEqual(exc.__class__, template.__class__)
- self.assertEqual(exc.args[0], template.args[0])
- else:
- self.assertEqual(exc.message, template.message)
- self.assertEqual(len(exc.exceptions), len(template.exceptions))
- for e, t in zip(exc.exceptions, template.exceptions):
- self.assertExceptionIsLike(e, t)
- def assertMetadataEqual(self, e1, e2):
- if e1 is None or e2 is None:
- self.assertTrue(e1 is None and e2 is None)
- else:
- self.assertEqual(e1.__context__, e2.__context__)
- self.assertEqual(e1.__cause__, e2.__cause__)
- self.assertEqual(e1.__traceback__, e2.__traceback__)
- def assertMetadataNotEqual(self, e1, e2):
- if e1 is None or e2 is None:
- self.assertNotEqual(e1, e2)
- else:
- return not (e1.__context__ == e2.__context__
- and e1.__cause__ == e2.__cause__
- and e1.__traceback__ == e2.__traceback__)
- class TestExceptStarSplitSemantics(ExceptStarTest):
- def doSplitTestNamed(self, exc, T, match_template, rest_template):
- initial_exc_info = sys.exc_info()
- exc_info = match = rest = None
- try:
- try:
- raise exc
- except* T as e:
- exc_info = sys.exc_info()
- match = e
- except BaseException as e:
- rest = e
- if match_template:
- self.assertEqual(exc_info[1], match)
- else:
- self.assertIsNone(exc_info)
- self.assertExceptionIsLike(match, match_template)
- self.assertExceptionIsLike(rest, rest_template)
- self.assertEqual(sys.exc_info(), initial_exc_info)
- def doSplitTestUnnamed(self, exc, T, match_template, rest_template):
- initial_exc_info = sys.exc_info()
- exc_info = match = rest = None
- try:
- try:
- raise exc
- except* T:
- exc_info = sys.exc_info()
- match = sys.exc_info()[1]
- else:
- if rest_template:
- self.fail("Exception not raised")
- except BaseException as e:
- rest = e
- self.assertExceptionIsLike(match, match_template)
- if match_template:
- self.assertEqual(exc_info[0], type(match_template))
- self.assertExceptionIsLike(rest, rest_template)
- self.assertEqual(sys.exc_info(), initial_exc_info)
- def doSplitTestInExceptHandler(self, exc, T, match_template, rest_template):
- try:
- raise ExceptionGroup('eg', [TypeError(1), ValueError(2)])
- except Exception:
- self.doSplitTestNamed(exc, T, match_template, rest_template)
- self.doSplitTestUnnamed(exc, T, match_template, rest_template)
- def doSplitTestInExceptStarHandler(self, exc, T, match_template, rest_template):
- try:
- raise ExceptionGroup('eg', [TypeError(1), ValueError(2)])
- except* Exception:
- self.doSplitTestNamed(exc, T, match_template, rest_template)
- self.doSplitTestUnnamed(exc, T, match_template, rest_template)
- def doSplitTest(self, exc, T, match_template, rest_template):
- self.doSplitTestNamed(exc, T, match_template, rest_template)
- self.doSplitTestUnnamed(exc, T, match_template, rest_template)
- self.doSplitTestInExceptHandler(exc, T, match_template, rest_template)
- self.doSplitTestInExceptStarHandler(exc, T, match_template, rest_template)
- def test_no_match_single_type(self):
- self.doSplitTest(
- ExceptionGroup("test1", [ValueError("V"), TypeError("T")]),
- SyntaxError,
- None,
- ExceptionGroup("test1", [ValueError("V"), TypeError("T")]))
- def test_match_single_type(self):
- self.doSplitTest(
- ExceptionGroup("test2", [ValueError("V1"), ValueError("V2")]),
- ValueError,
- ExceptionGroup("test2", [ValueError("V1"), ValueError("V2")]),
- None)
- def test_match_single_type_partial_match(self):
- self.doSplitTest(
- ExceptionGroup(
- "test3",
- [ValueError("V1"), OSError("OS"), ValueError("V2")]),
- ValueError,
- ExceptionGroup("test3", [ValueError("V1"), ValueError("V2")]),
- ExceptionGroup("test3", [OSError("OS")]))
- def test_match_single_type_nested(self):
- self.doSplitTest(
- ExceptionGroup(
- "g1", [
- ValueError("V1"),
- OSError("OS1"),
- ExceptionGroup(
- "g2", [
- OSError("OS2"),
- ValueError("V2"),
- TypeError("T")])]),
- ValueError,
- ExceptionGroup(
- "g1", [
- ValueError("V1"),
- ExceptionGroup("g2", [ValueError("V2")])]),
- ExceptionGroup("g1", [
- OSError("OS1"),
- ExceptionGroup("g2", [
- OSError("OS2"), TypeError("T")])]))
- def test_match_type_tuple_nested(self):
- self.doSplitTest(
- ExceptionGroup(
- "h1", [
- ValueError("V1"),
- OSError("OS1"),
- ExceptionGroup(
- "h2", [OSError("OS2"), ValueError("V2"), TypeError("T")])]),
- (ValueError, TypeError),
- ExceptionGroup(
- "h1", [
- ValueError("V1"),
- ExceptionGroup("h2", [ValueError("V2"), TypeError("T")])]),
- ExceptionGroup(
- "h1", [
- OSError("OS1"),
- ExceptionGroup("h2", [OSError("OS2")])]))
- def test_empty_groups_removed(self):
- self.doSplitTest(
- ExceptionGroup(
- "eg", [
- ExceptionGroup("i1", [ValueError("V1")]),
- ExceptionGroup("i2", [ValueError("V2"), TypeError("T1")]),
- ExceptionGroup("i3", [TypeError("T2")])]),
- TypeError,
- ExceptionGroup("eg", [
- ExceptionGroup("i2", [TypeError("T1")]),
- ExceptionGroup("i3", [TypeError("T2")])]),
- ExceptionGroup("eg", [
- ExceptionGroup("i1", [ValueError("V1")]),
- ExceptionGroup("i2", [ValueError("V2")])]))
- def test_singleton_groups_are_kept(self):
- self.doSplitTest(
- ExceptionGroup("j1", [
- ExceptionGroup("j2", [
- ExceptionGroup("j3", [ValueError("V1")]),
- ExceptionGroup("j4", [TypeError("T")])])]),
- TypeError,
- ExceptionGroup(
- "j1",
- [ExceptionGroup("j2", [ExceptionGroup("j4", [TypeError("T")])])]),
- ExceptionGroup(
- "j1",
- [ExceptionGroup("j2", [ExceptionGroup("j3", [ValueError("V1")])])]))
- def test_naked_exception_matched_wrapped1(self):
- self.doSplitTest(
- ValueError("V"),
- ValueError,
- ExceptionGroup("", [ValueError("V")]),
- None)
- def test_naked_exception_matched_wrapped2(self):
- self.doSplitTest(
- ValueError("V"),
- Exception,
- ExceptionGroup("", [ValueError("V")]),
- None)
- def test_exception_group_except_star_Exception_not_wrapped(self):
- self.doSplitTest(
- ExceptionGroup("eg", [ValueError("V")]),
- Exception,
- ExceptionGroup("eg", [ValueError("V")]),
- None)
- def test_plain_exception_not_matched(self):
- self.doSplitTest(
- ValueError("V"),
- TypeError,
- None,
- ValueError("V"))
- def test_match__supertype(self):
- self.doSplitTest(
- ExceptionGroup("st", [BlockingIOError("io"), TypeError("T")]),
- OSError,
- ExceptionGroup("st", [BlockingIOError("io")]),
- ExceptionGroup("st", [TypeError("T")]))
- def test_multiple_matches_named(self):
- try:
- raise ExceptionGroup("mmn", [OSError("os"), BlockingIOError("io")])
- except* BlockingIOError as e:
- self.assertExceptionIsLike(e,
- ExceptionGroup("mmn", [BlockingIOError("io")]))
- except* OSError as e:
- self.assertExceptionIsLike(e,
- ExceptionGroup("mmn", [OSError("os")]))
- else:
- self.fail("Exception not raised")
- def test_multiple_matches_unnamed(self):
- try:
- raise ExceptionGroup("mmu", [OSError("os"), BlockingIOError("io")])
- except* BlockingIOError:
- e = sys.exc_info()[1]
- self.assertExceptionIsLike(e,
- ExceptionGroup("mmu", [BlockingIOError("io")]))
- except* OSError:
- e = sys.exc_info()[1]
- self.assertExceptionIsLike(e,
- ExceptionGroup("mmu", [OSError("os")]))
- else:
- self.fail("Exception not raised")
- def test_first_match_wins_named(self):
- try:
- raise ExceptionGroup("fst", [BlockingIOError("io")])
- except* OSError as e:
- self.assertExceptionIsLike(e,
- ExceptionGroup("fst", [BlockingIOError("io")]))
- except* BlockingIOError:
- self.fail("Should have been matched as OSError")
- else:
- self.fail("Exception not raised")
- def test_first_match_wins_unnamed(self):
- try:
- raise ExceptionGroup("fstu", [BlockingIOError("io")])
- except* OSError:
- e = sys.exc_info()[1]
- self.assertExceptionIsLike(e,
- ExceptionGroup("fstu", [BlockingIOError("io")]))
- except* BlockingIOError:
- pass
- else:
- self.fail("Exception not raised")
- def test_nested_except_stars(self):
- try:
- raise ExceptionGroup("n", [BlockingIOError("io")])
- except* BlockingIOError:
- try:
- raise ExceptionGroup("n", [ValueError("io")])
- except* ValueError:
- pass
- else:
- self.fail("Exception not raised")
- e = sys.exc_info()[1]
- self.assertExceptionIsLike(e,
- ExceptionGroup("n", [BlockingIOError("io")]))
- else:
- self.fail("Exception not raised")
- def test_nested_in_loop(self):
- for _ in range(2):
- try:
- raise ExceptionGroup("nl", [BlockingIOError("io")])
- except* BlockingIOError:
- pass
- else:
- self.fail("Exception not raised")
- class TestExceptStarReraise(ExceptStarTest):
- def test_reraise_all_named(self):
- try:
- try:
- raise ExceptionGroup(
- "eg", [TypeError(1), ValueError(2), OSError(3)])
- except* TypeError as e:
- raise
- except* ValueError as e:
- raise
- # OSError not handled
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc,
- ExceptionGroup("eg", [TypeError(1), ValueError(2), OSError(3)]))
- def test_reraise_all_unnamed(self):
- try:
- try:
- raise ExceptionGroup(
- "eg", [TypeError(1), ValueError(2), OSError(3)])
- except* TypeError:
- raise
- except* ValueError:
- raise
- # OSError not handled
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc,
- ExceptionGroup("eg", [TypeError(1), ValueError(2), OSError(3)]))
- def test_reraise_some_handle_all_named(self):
- try:
- try:
- raise ExceptionGroup(
- "eg", [TypeError(1), ValueError(2), OSError(3)])
- except* TypeError as e:
- raise
- except* ValueError as e:
- pass
- # OSError not handled
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("eg", [TypeError(1), OSError(3)]))
- def test_reraise_partial_handle_all_unnamed(self):
- try:
- try:
- raise ExceptionGroup(
- "eg", [TypeError(1), ValueError(2)])
- except* TypeError:
- raise
- except* ValueError:
- pass
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("eg", [TypeError(1)]))
- def test_reraise_partial_handle_some_named(self):
- try:
- try:
- raise ExceptionGroup(
- "eg", [TypeError(1), ValueError(2), OSError(3)])
- except* TypeError as e:
- raise
- except* ValueError as e:
- pass
- # OSError not handled
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("eg", [TypeError(1), OSError(3)]))
- def test_reraise_partial_handle_some_unnamed(self):
- try:
- try:
- raise ExceptionGroup(
- "eg", [TypeError(1), ValueError(2), OSError(3)])
- except* TypeError:
- raise
- except* ValueError:
- pass
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("eg", [TypeError(1), OSError(3)]))
- def test_reraise_plain_exception_named(self):
- try:
- try:
- raise ValueError(42)
- except* ValueError as e:
- raise
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("", [ValueError(42)]))
- def test_reraise_plain_exception_unnamed(self):
- try:
- try:
- raise ValueError(42)
- except* ValueError:
- raise
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("", [ValueError(42)]))
- class TestExceptStarRaise(ExceptStarTest):
- def test_raise_named(self):
- orig = ExceptionGroup("eg", [ValueError(1), OSError(2)])
- try:
- try:
- raise orig
- except* OSError as e:
- raise TypeError(3)
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc,
- ExceptionGroup(
- "", [TypeError(3), ExceptionGroup("eg", [ValueError(1)])]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
- ExceptionGroup("eg", [OSError(2)]))
- self.assertMetadataNotEqual(orig, exc)
- self.assertMetadataEqual(orig, exc.exceptions[0].__context__)
- def test_raise_unnamed(self):
- orig = ExceptionGroup("eg", [ValueError(1), OSError(2)])
- try:
- try:
- raise orig
- except* OSError:
- raise TypeError(3)
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc,
- ExceptionGroup(
- "", [TypeError(3), ExceptionGroup("eg", [ValueError(1)])]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
- ExceptionGroup("eg", [OSError(2)]))
- self.assertMetadataNotEqual(orig, exc)
- self.assertMetadataEqual(orig, exc.exceptions[0].__context__)
- def test_raise_handle_all_raise_one_named(self):
- orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)])
- try:
- try:
- raise orig
- except* (TypeError, ValueError) as e:
- raise SyntaxError(3)
- except BaseException as e:
- exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("", [SyntaxError(3)]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
- ExceptionGroup("eg", [TypeError(1), ValueError(2)]))
- self.assertMetadataNotEqual(orig, exc)
- self.assertMetadataEqual(orig, exc.exceptions[0].__context__)
- def test_raise_handle_all_raise_one_unnamed(self):
- orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)])
- try:
- try:
- raise orig
- except* (TypeError, ValueError) as e:
- raise SyntaxError(3)
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("", [SyntaxError(3)]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
- ExceptionGroup("eg", [TypeError(1), ValueError(2)]))
- self.assertMetadataNotEqual(orig, exc)
- self.assertMetadataEqual(orig, exc.exceptions[0].__context__)
- def test_raise_handle_all_raise_two_named(self):
- orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)])
- try:
- try:
- raise orig
- except* TypeError as e:
- raise SyntaxError(3)
- except* ValueError as e:
- raise SyntaxError(4)
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("", [SyntaxError(3), SyntaxError(4)]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
- ExceptionGroup("eg", [TypeError(1)]))
- self.assertExceptionIsLike(
- exc.exceptions[1].__context__,
- ExceptionGroup("eg", [ValueError(2)]))
- self.assertMetadataNotEqual(orig, exc)
- self.assertMetadataEqual(orig, exc.exceptions[0].__context__)
- self.assertMetadataEqual(orig, exc.exceptions[1].__context__)
- def test_raise_handle_all_raise_two_unnamed(self):
- orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)])
- try:
- try:
- raise orig
- except* TypeError:
- raise SyntaxError(3)
- except* ValueError:
- raise SyntaxError(4)
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("", [SyntaxError(3), SyntaxError(4)]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
- ExceptionGroup("eg", [TypeError(1)]))
- self.assertExceptionIsLike(
- exc.exceptions[1].__context__,
- ExceptionGroup("eg", [ValueError(2)]))
- self.assertMetadataNotEqual(orig, exc)
- self.assertMetadataEqual(orig, exc.exceptions[0].__context__)
- self.assertMetadataEqual(orig, exc.exceptions[1].__context__)
- class TestExceptStarRaiseFrom(ExceptStarTest):
- def test_raise_named(self):
- orig = ExceptionGroup("eg", [ValueError(1), OSError(2)])
- try:
- try:
- raise orig
- except* OSError as e:
- raise TypeError(3) from e
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc,
- ExceptionGroup(
- "", [TypeError(3), ExceptionGroup("eg", [ValueError(1)])]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
- ExceptionGroup("eg", [OSError(2)]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__cause__,
- ExceptionGroup("eg", [OSError(2)]))
- self.assertMetadataNotEqual(orig, exc)
- self.assertMetadataEqual(orig, exc.exceptions[0].__context__)
- self.assertMetadataEqual(orig, exc.exceptions[0].__cause__)
- self.assertMetadataNotEqual(orig, exc.exceptions[1].__context__)
- self.assertMetadataNotEqual(orig, exc.exceptions[1].__cause__)
- def test_raise_unnamed(self):
- orig = ExceptionGroup("eg", [ValueError(1), OSError(2)])
- try:
- try:
- raise orig
- except* OSError:
- e = sys.exc_info()[1]
- raise TypeError(3) from e
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc,
- ExceptionGroup(
- "", [TypeError(3), ExceptionGroup("eg", [ValueError(1)])]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
- ExceptionGroup("eg", [OSError(2)]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__cause__,
- ExceptionGroup("eg", [OSError(2)]))
- self.assertMetadataNotEqual(orig, exc)
- self.assertMetadataEqual(orig, exc.exceptions[0].__context__)
- self.assertMetadataEqual(orig, exc.exceptions[0].__cause__)
- self.assertMetadataNotEqual(orig, exc.exceptions[1].__context__)
- self.assertMetadataNotEqual(orig, exc.exceptions[1].__cause__)
- def test_raise_handle_all_raise_one_named(self):
- orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)])
- try:
- try:
- raise orig
- except* (TypeError, ValueError) as e:
- raise SyntaxError(3) from e
- except BaseException as e:
- exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("", [SyntaxError(3)]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
- ExceptionGroup("eg", [TypeError(1), ValueError(2)]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__cause__,
- ExceptionGroup("eg", [TypeError(1), ValueError(2)]))
- self.assertMetadataNotEqual(orig, exc)
- self.assertMetadataEqual(orig, exc.exceptions[0].__context__)
- self.assertMetadataEqual(orig, exc.exceptions[0].__cause__)
- def test_raise_handle_all_raise_one_unnamed(self):
- orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)])
- try:
- try:
- raise orig
- except* (TypeError, ValueError) as e:
- e = sys.exc_info()[1]
- raise SyntaxError(3) from e
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("", [SyntaxError(3)]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
- ExceptionGroup("eg", [TypeError(1), ValueError(2)]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__cause__,
- ExceptionGroup("eg", [TypeError(1), ValueError(2)]))
- self.assertMetadataNotEqual(orig, exc)
- self.assertMetadataEqual(orig, exc.exceptions[0].__context__)
- self.assertMetadataEqual(orig, exc.exceptions[0].__cause__)
- def test_raise_handle_all_raise_two_named(self):
- orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)])
- try:
- try:
- raise orig
- except* TypeError as e:
- raise SyntaxError(3) from e
- except* ValueError as e:
- raise SyntaxError(4) from e
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("", [SyntaxError(3), SyntaxError(4)]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
- ExceptionGroup("eg", [TypeError(1)]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__cause__,
- ExceptionGroup("eg", [TypeError(1)]))
- self.assertExceptionIsLike(
- exc.exceptions[1].__context__,
- ExceptionGroup("eg", [ValueError(2)]))
- self.assertExceptionIsLike(
- exc.exceptions[1].__cause__,
- ExceptionGroup("eg", [ValueError(2)]))
- self.assertMetadataNotEqual(orig, exc)
- self.assertMetadataEqual(orig, exc.exceptions[0].__context__)
- self.assertMetadataEqual(orig, exc.exceptions[0].__cause__)
- def test_raise_handle_all_raise_two_unnamed(self):
- orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)])
- try:
- try:
- raise orig
- except* TypeError:
- e = sys.exc_info()[1]
- raise SyntaxError(3) from e
- except* ValueError:
- e = sys.exc_info()[1]
- raise SyntaxError(4) from e
- except ExceptionGroup as e:
- exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("", [SyntaxError(3), SyntaxError(4)]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
- ExceptionGroup("eg", [TypeError(1)]))
- self.assertExceptionIsLike(
- exc.exceptions[0].__cause__,
- ExceptionGroup("eg", [TypeError(1)]))
- self.assertExceptionIsLike(
- exc.exceptions[1].__context__,
- ExceptionGroup("eg", [ValueError(2)]))
- self.assertExceptionIsLike(
- exc.exceptions[1].__cause__,
- ExceptionGroup("eg", [ValueError(2)]))
- self.assertMetadataNotEqual(orig, exc)
- self.assertMetadataEqual(orig, exc.exceptions[0].__context__)
- self.assertMetadataEqual(orig, exc.exceptions[0].__cause__)
- self.assertMetadataEqual(orig, exc.exceptions[1].__context__)
- self.assertMetadataEqual(orig, exc.exceptions[1].__cause__)
- class TestExceptStarExceptionGroupSubclass(ExceptStarTest):
- def test_except_star_EG_subclass(self):
- class EG(ExceptionGroup):
- def __new__(cls, message, excs, code):
- obj = super().__new__(cls, message, excs)
- obj.code = code
- return obj
- def derive(self, excs):
- return EG(self.message, excs, self.code)
- try:
- try:
- try:
- try:
- raise TypeError(2)
- except TypeError as te:
- raise EG("nested", [te], 101) from None
- except EG as nested:
- try:
- raise ValueError(1)
- except ValueError as ve:
- raise EG("eg", [ve, nested], 42)
- except* ValueError as eg:
- veg = eg
- except EG as eg:
- teg = eg
- self.assertIsInstance(veg, EG)
- self.assertIsInstance(teg, EG)
- self.assertIsInstance(teg.exceptions[0], EG)
- self.assertMetadataEqual(veg, teg)
- self.assertEqual(veg.code, 42)
- self.assertEqual(teg.code, 42)
- self.assertEqual(teg.exceptions[0].code, 101)
- def test_falsy_exception_group_subclass(self):
- class FalsyEG(ExceptionGroup):
- def __bool__(self):
- return False
- def derive(self, excs):
- return FalsyEG(self.message, excs)
- try:
- try:
- raise FalsyEG("eg", [TypeError(1), ValueError(2)])
- except *TypeError as e:
- tes = e
- raise
- except *ValueError as e:
- ves = e
- pass
- except Exception as e:
- exc = e
- for e in [tes, ves, exc]:
- self.assertFalse(e)
- self.assertIsInstance(e, FalsyEG)
- self.assertExceptionIsLike(exc, FalsyEG("eg", [TypeError(1)]))
- self.assertExceptionIsLike(tes, FalsyEG("eg", [TypeError(1)]))
- self.assertExceptionIsLike(ves, FalsyEG("eg", [ValueError(2)]))
- class TestExceptStarCleanup(ExceptStarTest):
- def test_exc_info_restored(self):
- try:
- try:
- raise ValueError(42)
- except:
- try:
- raise TypeError(int)
- except* Exception:
- pass
- 1/0
- except Exception as e:
- exc = e
- self.assertExceptionIsLike(exc, ZeroDivisionError('division by zero'))
- self.assertExceptionIsLike(exc.__context__, ValueError(42))
- self.assertEqual(sys.exc_info(), (None, None, None))
- class TestExceptStar_WeirdLeafExceptions(ExceptStarTest):
- # Test that except* works when leaf exceptions are
- # unhashable or have a bad custom __eq__
- class UnhashableExc(ValueError):
- __hash__ = None
- class AlwaysEqualExc(ValueError):
- def __eq__(self, other):
- return True
- class NeverEqualExc(ValueError):
- def __eq__(self, other):
- return False
- class BrokenEqualExc(ValueError):
- def __eq__(self, other):
- raise RuntimeError()
- def setUp(self):
- self.bad_types = [self.UnhashableExc,
- self.AlwaysEqualExc,
- self.NeverEqualExc,
- self.BrokenEqualExc]
- def except_type(self, eg, type):
- match, rest = None, None
- try:
- try:
- raise eg
- except* type as e:
- match = e
- except Exception as e:
- rest = e
- return match, rest
- def test_catch_unhashable_leaf_exception(self):
- for Bad in self.bad_types:
- with self.subTest(Bad):
- eg = ExceptionGroup("eg", [TypeError(1), Bad(2)])
- match, rest = self.except_type(eg, Bad)
- self.assertExceptionIsLike(
- match, ExceptionGroup("eg", [Bad(2)]))
- self.assertExceptionIsLike(
- rest, ExceptionGroup("eg", [TypeError(1)]))
- def test_propagate_unhashable_leaf(self):
- for Bad in self.bad_types:
- with self.subTest(Bad):
- eg = ExceptionGroup("eg", [TypeError(1), Bad(2)])
- match, rest = self.except_type(eg, TypeError)
- self.assertExceptionIsLike(
- match, ExceptionGroup("eg", [TypeError(1)]))
- self.assertExceptionIsLike(
- rest, ExceptionGroup("eg", [Bad(2)]))
- def test_catch_nothing_unhashable_leaf(self):
- for Bad in self.bad_types:
- with self.subTest(Bad):
- eg = ExceptionGroup("eg", [TypeError(1), Bad(2)])
- match, rest = self.except_type(eg, OSError)
- self.assertIsNone(match)
- self.assertExceptionIsLike(rest, eg)
- def test_catch_everything_unhashable_leaf(self):
- for Bad in self.bad_types:
- with self.subTest(Bad):
- eg = ExceptionGroup("eg", [TypeError(1), Bad(2)])
- match, rest = self.except_type(eg, Exception)
- self.assertExceptionIsLike(match, eg)
- self.assertIsNone(rest)
- def test_reraise_unhashable_leaf(self):
- for Bad in self.bad_types:
- with self.subTest(Bad):
- eg = ExceptionGroup(
- "eg", [TypeError(1), Bad(2), ValueError(3)])
- try:
- try:
- raise eg
- except* TypeError:
- pass
- except* Bad:
- raise
- except Exception as e:
- exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("eg", [Bad(2), ValueError(3)]))
- class TestExceptStar_WeirdExceptionGroupSubclass(ExceptStarTest):
- # Test that except* works with exception groups that are
- # unhashable or have a bad custom __eq__
- class UnhashableEG(ExceptionGroup):
- __hash__ = None
- def derive(self, excs):
- return type(self)(self.message, excs)
- class AlwaysEqualEG(ExceptionGroup):
- def __eq__(self, other):
- return True
- def derive(self, excs):
- return type(self)(self.message, excs)
- class NeverEqualEG(ExceptionGroup):
- def __eq__(self, other):
- return False
- def derive(self, excs):
- return type(self)(self.message, excs)
- class BrokenEqualEG(ExceptionGroup):
- def __eq__(self, other):
- raise RuntimeError()
- def derive(self, excs):
- return type(self)(self.message, excs)
- def setUp(self):
- self.bad_types = [self.UnhashableEG,
- self.AlwaysEqualEG,
- self.NeverEqualEG,
- self.BrokenEqualEG]
- def except_type(self, eg, type):
- match, rest = None, None
- try:
- try:
- raise eg
- except* type as e:
- match = e
- except Exception as e:
- rest = e
- return match, rest
- def test_catch_some_unhashable_exception_group_subclass(self):
- for BadEG in self.bad_types:
- with self.subTest(BadEG):
- eg = BadEG("eg",
- [TypeError(1),
- BadEG("nested", [ValueError(2)])])
- match, rest = self.except_type(eg, TypeError)
- self.assertExceptionIsLike(match, BadEG("eg", [TypeError(1)]))
- self.assertExceptionIsLike(rest,
- BadEG("eg", [BadEG("nested", [ValueError(2)])]))
- def test_catch_none_unhashable_exception_group_subclass(self):
- for BadEG in self.bad_types:
- with self.subTest(BadEG):
- eg = BadEG("eg",
- [TypeError(1),
- BadEG("nested", [ValueError(2)])])
- match, rest = self.except_type(eg, OSError)
- self.assertIsNone(match)
- self.assertExceptionIsLike(rest, eg)
- def test_catch_all_unhashable_exception_group_subclass(self):
- for BadEG in self.bad_types:
- with self.subTest(BadEG):
- eg = BadEG("eg",
- [TypeError(1),
- BadEG("nested", [ValueError(2)])])
- match, rest = self.except_type(eg, Exception)
- self.assertExceptionIsLike(match, eg)
- self.assertIsNone(rest)
- def test_reraise_unhashable_eg(self):
- for BadEG in self.bad_types:
- with self.subTest(BadEG):
- eg = BadEG("eg",
- [TypeError(1), ValueError(2),
- BadEG("nested", [ValueError(3), OSError(4)])])
- try:
- try:
- raise eg
- except* ValueError:
- pass
- except* OSError:
- raise
- except Exception as e:
- exc = e
- self.assertExceptionIsLike(
- exc, BadEG("eg", [TypeError(1),
- BadEG("nested", [OSError(4)])]))
- if __name__ == '__main__':
- unittest.main()
|