test_except_star.py 39 KB

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