summaryrefslogtreecommitdiffstats
path: root/Objects/exceptions.c
diff options
context:
space:
mode:
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>2023-05-30 15:50:23 (GMT)
committerGitHub <noreply@github.com>2023-05-30 15:50:23 (GMT)
commitb45df737d43e809b1c41b9b2056ecb28c3cfb288 (patch)
tree70cc61338652bffc07f89a304d0e2c1c045e7d87 /Objects/exceptions.c
parent7899fac3c5fba3b8258cdd72562230c51164d778 (diff)
downloadcpython-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.c39
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")},