1 import sys
2 import unittest
3 import textwrap
4
5 class ESC[4;38;5;81mTestInvalidExceptStar(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
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
50 class ESC[4;38;5;81mTestBreakContinueReturnInExceptStarBlock(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
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
172 class ESC[4;38;5;81mExceptStarTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
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
209 class ESC[4;38;5;81mTestExceptStarSplitSemantics(ESC[4;38;5;149mExceptStarTest):
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
465 class ESC[4;38;5;81mTestExceptStarReraise(ESC[4;38;5;149mExceptStarTest):
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
587 class ESC[4;38;5;81mTestExceptStarRaise(ESC[4;38;5;149mExceptStarTest):
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
725 class ESC[4;38;5;81mTestExceptStarRaiseFrom(ESC[4;38;5;149mExceptStarTest):
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
909 class ESC[4;38;5;81mTestExceptStarExceptionGroupSubclass(ESC[4;38;5;149mExceptStarTest):
910 def test_except_star_EG_subclass(self):
911 class ESC[4;38;5;81mEG(ESC[4;38;5;149mExceptionGroup):
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 ESC[4;38;5;81mFalsyEG(ESC[4;38;5;149mExceptionGroup):
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
974 class ESC[4;38;5;81mTestExceptStarCleanup(ESC[4;38;5;149mExceptStarTest):
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
993 class ESC[4;38;5;81mTestExceptStar_WeirdLeafExceptions(ESC[4;38;5;149mExceptStarTest):
994 # Test that except* works when leaf exceptions are
995 # unhashable or have a bad custom __eq__
996
997 class ESC[4;38;5;81mUnhashableExc(ESC[4;38;5;149mValueError):
998 __hash__ = None
999
1000 class ESC[4;38;5;81mAlwaysEqualExc(ESC[4;38;5;149mValueError):
1001 def __eq__(self, other):
1002 return True
1003
1004 class ESC[4;38;5;81mNeverEqualExc(ESC[4;38;5;149mValueError):
1005 def __eq__(self, other):
1006 return False
1007
1008 class ESC[4;38;5;81mBrokenEqualExc(ESC[4;38;5;149mValueError):
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
1085 class ESC[4;38;5;81mTestExceptStar_WeirdExceptionGroupSubclass(ESC[4;38;5;149mExceptStarTest):
1086 # Test that except* works with exception groups that are
1087 # unhashable or have a bad custom __eq__
1088
1089 class ESC[4;38;5;81mUnhashableEG(ESC[4;38;5;149mExceptionGroup):
1090 __hash__ = None
1091
1092 def derive(self, excs):
1093 return type(self)(self.message, excs)
1094
1095 class ESC[4;38;5;81mAlwaysEqualEG(ESC[4;38;5;149mExceptionGroup):
1096 def __eq__(self, other):
1097 return True
1098
1099 def derive(self, excs):
1100 return type(self)(self.message, excs)
1101
1102 class ESC[4;38;5;81mNeverEqualEG(ESC[4;38;5;149mExceptionGroup):
1103 def __eq__(self, other):
1104 return False
1105
1106 def derive(self, excs):
1107 return type(self)(self.message, excs)
1108
1109 class ESC[4;38;5;81mBrokenEqualEG(ESC[4;38;5;149mExceptionGroup):
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
1192 if __name__ == '__main__':
1193 unittest.main()