summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Objects/exceptions.c
diff options
context:
space:
mode:
authorshadchin <[email protected]>2026-02-07 19:56:35 +0300
committershadchin <[email protected]>2026-02-07 20:23:53 +0300
commit19d43a3e6fb4cb8ea11747d7d7bca7a3542fbb44 (patch)
tree0b1418938140a0b6470953bef6069454ffdf1bd0 /contrib/tools/python3/Objects/exceptions.c
parent0879409bfc0891ab8103828a3bdbf0e960475fec (diff)
Update Python 3 to 3.13.12
commit_hash:71d3efea437a769b2b7910d196120bb02587046e
Diffstat (limited to 'contrib/tools/python3/Objects/exceptions.c')
-rw-r--r--contrib/tools/python3/Objects/exceptions.c90
1 files changed, 77 insertions, 13 deletions
diff --git a/contrib/tools/python3/Objects/exceptions.c b/contrib/tools/python3/Objects/exceptions.c
index a1fda3c1fd1..db2774d3d6a 100644
--- a/contrib/tools/python3/Objects/exceptions.c
+++ b/contrib/tools/python3/Objects/exceptions.c
@@ -531,13 +531,13 @@ PyTypeObject _PyExc_ ## EXCNAME = { \
#define ComplexExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCNEW, \
EXCMETHODS, EXCMEMBERS, EXCGETSET, \
- EXCSTR, EXCDOC) \
+ EXCSTR, EXCREPR, EXCDOC) \
static PyTypeObject _PyExc_ ## EXCNAME = { \
PyVarObject_HEAD_INIT(NULL, 0) \
# EXCNAME, \
sizeof(Py ## EXCSTORE ## Object), 0, \
- (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- (reprfunc)EXCSTR, 0, 0, 0, \
+ (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, (reprfunc)EXCREPR, 0, 0, 0, \
+ 0, 0, (reprfunc)EXCSTR, 0, 0, 0, \
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \
PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \
(inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, EXCMETHODS, \
@@ -619,7 +619,7 @@ StopIteration_traverse(PyStopIterationObject *self, visitproc visit, void *arg)
}
ComplexExtendsException(PyExc_Exception, StopIteration, StopIteration,
- 0, 0, StopIteration_members, 0, 0,
+ 0, 0, StopIteration_members, 0, 0, 0,
"Signal the end from iterator.__next__().");
@@ -682,7 +682,7 @@ static PyMemberDef SystemExit_members[] = {
};
ComplexExtendsException(PyExc_BaseException, SystemExit, SystemExit,
- 0, 0, SystemExit_members, 0, 0,
+ 0, 0, SystemExit_members, 0, 0, 0,
"Request to exit from the interpreter.");
/*
@@ -707,6 +707,7 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyObject *message = NULL;
PyObject *exceptions = NULL;
+ PyObject *exceptions_str = NULL;
if (!PyArg_ParseTuple(args,
"UO:BaseExceptionGroup.__new__",
@@ -722,6 +723,18 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return NULL;
}
+ /* Save initial exceptions sequence as a string in case sequence is mutated */
+ if (!PyList_Check(exceptions) && !PyTuple_Check(exceptions)) {
+ exceptions_str = PyObject_Repr(exceptions);
+ if (exceptions_str == NULL) {
+ /* We don't hold a reference to exceptions, so clear it before
+ * attempting a decref in the cleanup.
+ */
+ exceptions = NULL;
+ goto error;
+ }
+ }
+
exceptions = PySequence_Tuple(exceptions);
if (!exceptions) {
return NULL;
@@ -805,9 +818,11 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
self->msg = Py_NewRef(message);
self->excs = exceptions;
+ self->excs_str = exceptions_str;
return (PyObject*)self;
error:
- Py_DECREF(exceptions);
+ Py_XDECREF(exceptions);
+ Py_XDECREF(exceptions_str);
return NULL;
}
@@ -846,6 +861,7 @@ BaseExceptionGroup_clear(PyBaseExceptionGroupObject *self)
{
Py_CLEAR(self->msg);
Py_CLEAR(self->excs);
+ Py_CLEAR(self->excs_str);
return BaseException_clear((PyBaseExceptionObject *)self);
}
@@ -863,6 +879,7 @@ BaseExceptionGroup_traverse(PyBaseExceptionGroupObject *self,
{
Py_VISIT(self->msg);
Py_VISIT(self->excs);
+ Py_VISIT(self->excs_str);
return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
}
@@ -880,6 +897,53 @@ BaseExceptionGroup_str(PyBaseExceptionGroupObject *self)
}
static PyObject *
+BaseExceptionGroup_repr(PyBaseExceptionGroupObject *self)
+{
+ assert(self->msg);
+
+ PyObject *exceptions_str = NULL;
+
+ /* Use the saved exceptions string for custom sequences. */
+ if (self->excs_str) {
+ exceptions_str = Py_NewRef(self->excs_str);
+ }
+ else {
+ assert(self->excs);
+
+ /* Older versions delegated to BaseException, inserting the current
+ * value of self.args[1]; but this can be mutable and go out-of-sync
+ * with self.exceptions. Instead, use self.exceptions for accuracy,
+ * making it look like self.args[1] for backwards compatibility. */
+ if (PyList_Check(PyTuple_GET_ITEM(self->args, 1))) {
+ PyObject *exceptions_list = PySequence_List(self->excs);
+ if (!exceptions_list) {
+ return NULL;
+ }
+
+ exceptions_str = PyObject_Repr(exceptions_list);
+ Py_DECREF(exceptions_list);
+ }
+ else {
+ exceptions_str = PyObject_Repr(self->excs);
+ }
+
+ if (!exceptions_str) {
+ return NULL;
+ }
+ }
+
+ assert(exceptions_str != NULL);
+
+ const char *name = _PyType_Name(Py_TYPE(self));
+ PyObject *repr = PyUnicode_FromFormat(
+ "%s(%R, %U)", name,
+ self->msg, exceptions_str);
+
+ Py_DECREF(exceptions_str);
+ return repr;
+}
+
+static PyObject *
BaseExceptionGroup_derive(PyObject *self_, PyObject *excs)
{
PyBaseExceptionGroupObject *self = _PyBaseExceptionGroupObject_cast(self_);
@@ -1487,7 +1551,7 @@ static PyMethodDef BaseExceptionGroup_methods[] = {
ComplexExtendsException(PyExc_BaseException, BaseExceptionGroup,
BaseExceptionGroup, BaseExceptionGroup_new /* new */,
BaseExceptionGroup_methods, BaseExceptionGroup_members,
- 0 /* getset */, BaseExceptionGroup_str,
+ 0 /* getset */, BaseExceptionGroup_str, BaseExceptionGroup_repr,
"A combination of multiple unrelated exceptions.");
/*
@@ -1664,7 +1728,7 @@ static PyMethodDef ImportError_methods[] = {
ComplexExtendsException(PyExc_Exception, ImportError,
ImportError, 0 /* new */,
ImportError_methods, ImportError_members,
- 0 /* getset */, ImportError_str,
+ 0 /* getset */, ImportError_str, 0,
"Import can't find module, or can't find name in "
"module.");
@@ -2124,7 +2188,7 @@ static PyGetSetDef OSError_getset[] = {
ComplexExtendsException(PyExc_Exception, OSError,
OSError, OSError_new,
OSError_methods, OSError_members, OSError_getset,
- OSError_str,
+ OSError_str, 0,
"Base class for I/O related errors.");
@@ -2255,7 +2319,7 @@ static PyMethodDef NameError_methods[] = {
ComplexExtendsException(PyExc_Exception, NameError,
NameError, 0,
NameError_methods, NameError_members,
- 0, BaseException_str, "Name not found globally.");
+ 0, BaseException_str, 0, "Name not found globally.");
/*
* UnboundLocalError extends NameError
@@ -2377,7 +2441,7 @@ static PyMethodDef AttributeError_methods[] = {
ComplexExtendsException(PyExc_Exception, AttributeError,
AttributeError, 0,
AttributeError_methods, AttributeError_members,
- 0, BaseException_str, "Attribute not found.");
+ 0, BaseException_str, 0, "Attribute not found.");
/*
* SyntaxError extends Exception
@@ -2558,7 +2622,7 @@ static PyMemberDef SyntaxError_members[] = {
ComplexExtendsException(PyExc_Exception, SyntaxError, SyntaxError,
0, 0, SyntaxError_members, 0,
- SyntaxError_str, "Invalid syntax.");
+ SyntaxError_str, 0, "Invalid syntax.");
/*
@@ -2616,7 +2680,7 @@ KeyError_str(PyBaseExceptionObject *self)
}
ComplexExtendsException(PyExc_LookupError, KeyError, BaseException,
- 0, 0, 0, 0, KeyError_str, "Mapping key not found.");
+ 0, 0, 0, 0, KeyError_str, 0, "Mapping key not found.");
/*