[3.11] gh-103590: do not wrap a single exception raised from a try-except* (#104094)

This commit is contained in:
Irit Katriel 2023-05-02 19:24:02 +01:00 committed by GitHub
parent f9231a09be
commit 5386730cdd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 25 deletions

View file

@ -365,6 +365,10 @@ Any remaining exceptions that were not handled by any :keyword:`!except*`
clause are re-raised at the end, combined into an exception group along with
all exceptions that were raised from within :keyword:`!except*` clauses.
From version 3.11.4, when the entire :exc:`ExceptionGroup` is handled and
only one exception is raised from an :keyword:`!except*` clause, this
exception is no longer wrapped to form a new :exc:`ExceptionGroup`.
If the raised exception is not an exception group and its type matches
one of the :keyword:`!except*` clauses, it is caught and wrapped by an
exception group with an empty message string. ::

View file

@ -636,18 +636,17 @@ def test_raise_handle_all_raise_one_named(self):
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)])
@ -656,18 +655,17 @@ def test_raise_handle_all_raise_one_unnamed(self):
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)])
@ -791,23 +789,22 @@ def test_raise_handle_all_raise_one_named(self):
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)])
@ -817,23 +814,22 @@ def test_raise_handle_all_raise_one_unnamed(self):
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)])

View file

@ -0,0 +1 @@
Do not wrap a single exception raised from a ``try-except*`` construct in an :exc:`ExceptionGroup`.

View file

@ -1423,7 +1423,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;
}