Skip to content

Commit b45402a

Browse files
committed
Store exceptions copy in BaseExceptionGroup->excs_orig and use in repr
1 parent 72918ea commit b45402a

File tree

2 files changed

+21
-4
lines changed

2 files changed

+21
-4
lines changed

Include/cpython/pyerrors.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ typedef struct {
1818
PyException_HEAD
1919
PyObject *msg;
2020
PyObject *excs;
21+
PyObject *excs_orig;
2122
} PyBaseExceptionGroupObject;
2223

2324
typedef struct {

Objects/exceptions.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -905,12 +905,22 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
905905
return NULL;
906906
}
907907

908-
exceptions = PySequence_Tuple(exceptions);
908+
/* Make a copy of the passed exceptions sequence, for use in the repr */
909+
PyObject *exceptions_copy = exceptions;
910+
if (PyList_Check(exceptions)) {
911+
exceptions_copy = PySequence_List(exceptions);
912+
} else {
913+
Py_INCREF(exceptions_copy);
914+
}
915+
916+
exceptions = PySequence_Tuple(exceptions_copy);
909917
if (!exceptions) {
910918
return NULL;
911919
}
912920

913-
/* We are now holding a ref to the exceptions tuple */
921+
/* We are now holding a ref to (a potential copy of) the original
922+
* exceptions sequence and to the exceptions tuple.
923+
*/
914924

915925
Py_ssize_t numexcs = PyTuple_GET_SIZE(exceptions);
916926
if (numexcs == 0) {
@@ -988,9 +998,11 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
988998

989999
self->msg = Py_NewRef(message);
9901000
self->excs = exceptions;
1001+
self->excs_orig = exceptions_copy;
9911002
return (PyObject*)self;
9921003
error:
9931004
Py_DECREF(exceptions);
1005+
Py_DECREF(exceptions_copy);
9941006
return NULL;
9951007
}
9961008

@@ -1029,6 +1041,7 @@ BaseExceptionGroup_clear(PyObject *op)
10291041
PyBaseExceptionGroupObject *self = PyBaseExceptionGroupObject_CAST(op);
10301042
Py_CLEAR(self->msg);
10311043
Py_CLEAR(self->excs);
1044+
Py_CLEAR(self->excs_orig);
10321045
return BaseException_clear(op);
10331046
}
10341047

@@ -1046,6 +1059,7 @@ BaseExceptionGroup_traverse(PyObject *op, visitproc visit, void *arg)
10461059
PyBaseExceptionGroupObject *self = PyBaseExceptionGroupObject_CAST(op);
10471060
Py_VISIT(self->msg);
10481061
Py_VISIT(self->excs);
1062+
Py_VISIT(self->excs_orig);
10491063
return BaseException_traverse(op, visit, arg);
10501064
}
10511065

@@ -1068,12 +1082,12 @@ BaseExceptionGroup_repr(PyObject *op)
10681082
{
10691083
PyBaseExceptionGroupObject *self = PyBaseExceptionGroupObject_CAST(op);
10701084
assert(self->msg);
1071-
assert(self->excs);
1085+
assert(self->excs_orig);
10721086

10731087
const char *name = _PyType_Name(Py_TYPE(self));
10741088
return PyUnicode_FromFormat(
10751089
"%s(%R, %R)", name,
1076-
self->msg, self->excs);
1090+
self->msg, self->excs_orig);
10771091
}
10781092

10791093
/*[clinic input]
@@ -1695,6 +1709,8 @@ static PyMemberDef BaseExceptionGroup_members[] = {
16951709
PyDoc_STR("exception message")},
16961710
{"exceptions", _Py_T_OBJECT, offsetof(PyBaseExceptionGroupObject, excs), Py_READONLY,
16971711
PyDoc_STR("nested exceptions")},
1712+
{"_excs_orig", _Py_T_OBJECT, offsetof(PyBaseExceptionGroupObject, excs_orig), Py_READONLY,
1713+
PyDoc_STR("private copy of original nested exceptions")},
16981714
{NULL} /* Sentinel */
16991715
};
17001716

0 commit comments

Comments
 (0)