diff options
author | Irit Katriel <1055913+iritkatriel@users.noreply.github.com> | 2023-05-30 15:50:23 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-30 15:50:23 (GMT) |
commit | b45df737d43e809b1c41b9b2056ecb28c3cfb288 (patch) | |
tree | 70cc61338652bffc07f89a304d0e2c1c045e7d87 /Objects/exceptions.c | |
parent | 7899fac3c5fba3b8258cdd72562230c51164d778 (diff) | |
download | cpython-b45df737d43e809b1c41b9b2056ecb28c3cfb288.zip cpython-b45df737d43e809b1c41b9b2056ecb28c3cfb288.tar.gz cpython-b45df737d43e809b1c41b9b2056ecb28c3cfb288.tar.bz2 |
[3.12] gh-105071: add PyUnstable_Exc_PrepReraiseStar to expose except* implementation in the unstable API (GH-105072) (#105095)
(cherry picked from commit b7aadb4583b040ddc8564896b91f4e5e571c82d6)
Diffstat (limited to 'Objects/exceptions.c')
-rw-r--r-- | Objects/exceptions.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/Objects/exceptions.c b/Objects/exceptions.c index a8d4e3a..7bec739 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -1351,7 +1351,10 @@ is_same_exception_metadata(PyObject *exc1, PyObject *exc2) PyObject * _PyExc_PrepReraiseStar(PyObject *orig, PyObject *excs) { + /* orig must be a raised & caught exception, so it has a traceback */ assert(PyExceptionInstance_Check(orig)); + assert(_PyBaseExceptionObject_cast(orig)->traceback != NULL); + assert(PyList_Check(excs)); Py_ssize_t numexcs = PyList_GET_SIZE(excs); @@ -1438,6 +1441,42 @@ done: return result; } +PyObject * +PyUnstable_Exc_PrepReraiseStar(PyObject *orig, PyObject *excs) +{ + if (orig == NULL || !PyExceptionInstance_Check(orig)) { + PyErr_SetString(PyExc_TypeError, "orig must be an exception instance"); + return NULL; + } + if (excs == NULL || !PyList_Check(excs)) { + PyErr_SetString(PyExc_TypeError, + "excs must be a list of exception instances"); + return NULL; + } + Py_ssize_t numexcs = PyList_GET_SIZE(excs); + for (Py_ssize_t i = 0; i < numexcs; i++) { + PyObject *exc = PyList_GET_ITEM(excs, i); + if (exc == NULL || !(PyExceptionInstance_Check(exc) || Py_IsNone(exc))) { + PyErr_Format(PyExc_TypeError, + "item %d of excs is not an exception", i); + return NULL; + } + } + + /* Make sure that orig has something as traceback, in the interpreter + * it always does becuase it's a raised exception. + */ + PyObject *tb = PyException_GetTraceback(orig); + + if (tb == NULL) { + PyErr_Format(PyExc_ValueError, "orig must be a raised exception"); + return NULL; + } + Py_DECREF(tb); + + return _PyExc_PrepReraiseStar(orig, excs); +} + static PyMemberDef BaseExceptionGroup_members[] = { {"message", T_OBJECT, offsetof(PyBaseExceptionGroupObject, msg), READONLY, PyDoc_STR("exception message")}, |