summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/whatsnew/3.12.rst5
-rw-r--r--Lib/test/test_except_star.py44
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-04-21-16-12-41.gh-issue-103590.7DHDOE.rst1
-rw-r--r--Objects/exceptions.c7
4 files changed, 32 insertions, 25 deletions
diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst
index ff631ab..2915005 100644
--- a/Doc/whatsnew/3.12.rst
+++ b/Doc/whatsnew/3.12.rst
@@ -237,6 +237,11 @@ Other Language Changes
wrapped by a :exc:`RuntimeError`. Context information is added to the
exception as a :pep:`678` note. (Contributed by Irit Katriel in :gh:`77757`.)
+* When a ``try-except*`` construct handles the entire :exc:`ExceptionGroup`
+ and raises one other exception, that exception is no longer wrapped in an
+ :exc:`ExceptionGroup`. (Contributed by Irit Katriel in :gh:`103590`.)
+
+
New Modules
===========
diff --git a/Lib/test/test_except_star.py b/Lib/test/test_except_star.py
index bc66f90..c49c600 100644
--- a/Lib/test/test_except_star.py
+++ b/Lib/test/test_except_star.py
@@ -618,18 +618,17 @@ class TestExceptStarRaise(ExceptStarTest):
raise orig
except* (TypeError, ValueError) as e:
raise SyntaxError(3)
- except BaseException as e:
+ except SyntaxError as e:
exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("", [SyntaxError(3)]))
+ self.assertExceptionIsLike(exc, SyntaxError(3))
self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
+ exc.__context__,
ExceptionGroup("eg", [TypeError(1), ValueError(2)]))
self.assertMetadataNotEqual(orig, exc)
- self.assertMetadataEqual(orig, exc.exceptions[0].__context__)
+ self.assertMetadataEqual(orig, exc.__context__)
def test_raise_handle_all_raise_one_unnamed(self):
orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)])
@@ -638,18 +637,17 @@ class TestExceptStarRaise(ExceptStarTest):
raise orig
except* (TypeError, ValueError) as e:
raise SyntaxError(3)
- except ExceptionGroup as e:
+ except SyntaxError as e:
exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("", [SyntaxError(3)]))
+ self.assertExceptionIsLike(exc, SyntaxError(3))
self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
+ exc.__context__,
ExceptionGroup("eg", [TypeError(1), ValueError(2)]))
self.assertMetadataNotEqual(orig, exc)
- self.assertMetadataEqual(orig, exc.exceptions[0].__context__)
+ self.assertMetadataEqual(orig, exc.__context__)
def test_raise_handle_all_raise_two_named(self):
orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)])
@@ -773,23 +771,22 @@ class TestExceptStarRaiseFrom(ExceptStarTest):
raise orig
except* (TypeError, ValueError) as e:
raise SyntaxError(3) from e
- except BaseException as e:
+ except SyntaxError as e:
exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("", [SyntaxError(3)]))
+ self.assertExceptionIsLike(exc, SyntaxError(3))
self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
+ exc.__context__,
ExceptionGroup("eg", [TypeError(1), ValueError(2)]))
self.assertExceptionIsLike(
- exc.exceptions[0].__cause__,
+ exc.__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__)
+ self.assertMetadataEqual(orig, exc.__context__)
+ self.assertMetadataEqual(orig, exc.__cause__)
def test_raise_handle_all_raise_one_unnamed(self):
orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)])
@@ -799,23 +796,22 @@ class TestExceptStarRaiseFrom(ExceptStarTest):
except* (TypeError, ValueError) as e:
e = sys.exception()
raise SyntaxError(3) from e
- except ExceptionGroup as e:
+ except SyntaxError as e:
exc = e
- self.assertExceptionIsLike(
- exc, ExceptionGroup("", [SyntaxError(3)]))
+ self.assertExceptionIsLike(exc, SyntaxError(3))
self.assertExceptionIsLike(
- exc.exceptions[0].__context__,
+ exc.__context__,
ExceptionGroup("eg", [TypeError(1), ValueError(2)]))
self.assertExceptionIsLike(
- exc.exceptions[0].__cause__,
+ exc.__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__)
+ self.assertMetadataEqual(orig, exc.__context__)
+ self.assertMetadataEqual(orig, exc.__cause__)
def test_raise_handle_all_raise_two_named(self):
orig = ExceptionGroup("eg", [TypeError(1), ValueError(2)])
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-21-16-12-41.gh-issue-103590.7DHDOE.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-21-16-12-41.gh-issue-103590.7DHDOE.rst
new file mode 100644
index 0000000..af733a8
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-04-21-16-12-41.gh-issue-103590.7DHDOE.rst
@@ -0,0 +1 @@
+Do not wrap a single exception raised from a ``try-except*`` construct in an :exc:`ExceptionGroup`.
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index a355244..55a6768 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -1421,7 +1421,12 @@ _PyExc_PrepReraiseStar(PyObject *orig, PyObject *excs)
if (res < 0) {
goto done;
}
- result = _PyExc_CreateExceptionGroup("", raised_list);
+ if (PyList_GET_SIZE(raised_list) > 1) {
+ result = _PyExc_CreateExceptionGroup("", raised_list);
+ }
+ else {
+ result = Py_NewRef(PyList_GetItem(raised_list, 0));
+ }
if (result == NULL) {
goto done;
}