aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Objects/exceptions.c
diff options
context:
space:
mode:
authorshadchin <shadchin@yandex-team.com>2024-02-12 07:53:52 +0300
committerDaniil Cherednik <dcherednik@ydb.tech>2024-02-14 14:26:16 +0000
commit31f2a419764a8ba77c2a970cfc80056c6cd06756 (patch)
treec1995d239eba8571cefc640f6648e1d5dd4ce9e2 /contrib/tools/python3/src/Objects/exceptions.c
parentfe2ef02b38d9c85d80060963b265a1df9f38c3bb (diff)
downloadydb-31f2a419764a8ba77c2a970cfc80056c6cd06756.tar.gz
Update Python from 3.11.8 to 3.12.2
Diffstat (limited to 'contrib/tools/python3/src/Objects/exceptions.c')
-rw-r--r--contrib/tools/python3/src/Objects/exceptions.c458
1 files changed, 210 insertions, 248 deletions
diff --git a/contrib/tools/python3/src/Objects/exceptions.c b/contrib/tools/python3/src/Objects/exceptions.c
index 86cabbf3f1..e3217c922e 100644
--- a/contrib/tools/python3/src/Objects/exceptions.c
+++ b/contrib/tools/python3/src/Objects/exceptions.c
@@ -8,6 +8,7 @@
#include <Python.h>
#include <stdbool.h>
#include "pycore_ceval.h" // _Py_EnterRecursiveCall
+#include "pycore_pyerrors.h" // struct _PyErr_SetRaisedException
#include "pycore_exceptions.h" // struct _Py_exc_state
#include "pycore_initconfig.h"
#include "pycore_object.h"
@@ -53,8 +54,7 @@ BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
self->suppress_context = 0;
if (args) {
- self->args = args;
- Py_INCREF(args);
+ self->args = Py_NewRef(args);
return (PyObject *)self;
}
@@ -73,9 +73,7 @@ BaseException_init(PyBaseExceptionObject *self, PyObject *args, PyObject *kwds)
if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds))
return -1;
- Py_INCREF(args);
- Py_XSETREF(self->args, args);
-
+ Py_XSETREF(self->args, Py_NewRef(args));
return 0;
}
@@ -185,8 +183,7 @@ BaseException_with_traceback(PyObject *self, PyObject *tb) {
if (PyException_SetTraceback(self, tb))
return NULL;
- Py_INCREF(self);
- return self;
+ return Py_NewRef(self);
}
PyDoc_STRVAR(with_traceback_doc,
@@ -257,8 +254,7 @@ BaseException_get_args(PyBaseExceptionObject *self, void *Py_UNUSED(ignored))
if (self->args == NULL) {
Py_RETURN_NONE;
}
- Py_INCREF(self->args);
- return self->args;
+ return Py_NewRef(self->args);
}
static int
@@ -282,8 +278,7 @@ BaseException_get_tb(PyBaseExceptionObject *self, void *Py_UNUSED(ignored))
if (self->traceback == NULL) {
Py_RETURN_NONE;
}
- Py_INCREF(self->traceback);
- return self->traceback;
+ return Py_NewRef(self->traceback);
}
static int
@@ -293,14 +288,17 @@ BaseException_set_tb(PyBaseExceptionObject *self, PyObject *tb, void *Py_UNUSED(
PyErr_SetString(PyExc_TypeError, "__traceback__ may not be deleted");
return -1;
}
- else if (!(tb == Py_None || PyTraceBack_Check(tb))) {
+ if (PyTraceBack_Check(tb)) {
+ Py_XSETREF(self->traceback, Py_NewRef(tb));
+ }
+ else if (tb == Py_None) {
+ Py_CLEAR(self->traceback);
+ }
+ else {
PyErr_SetString(PyExc_TypeError,
"__traceback__ must be a traceback or None");
return -1;
}
-
- Py_INCREF(tb);
- Py_XSETREF(self->traceback, tb);
return 0;
}
@@ -379,8 +377,7 @@ PyObject *
PyException_GetTraceback(PyObject *self)
{
PyBaseExceptionObject *base_self = _PyBaseExceptionObject_cast(self);
- Py_XINCREF(base_self->traceback);
- return base_self->traceback;
+ return Py_XNewRef(base_self->traceback);
}
@@ -394,8 +391,7 @@ PyObject *
PyException_GetCause(PyObject *self)
{
PyObject *cause = _PyBaseExceptionObject_cast(self)->cause;
- Py_XINCREF(cause);
- return cause;
+ return Py_XNewRef(cause);
}
/* Steals a reference to cause */
@@ -411,8 +407,7 @@ PyObject *
PyException_GetContext(PyObject *self)
{
PyObject *context = _PyBaseExceptionObject_cast(self)->context;
- Py_XINCREF(context);
- return context;
+ return Py_XNewRef(context);
}
/* Steals a reference to context */
@@ -422,6 +417,20 @@ PyException_SetContext(PyObject *self, PyObject *context)
Py_XSETREF(_PyBaseExceptionObject_cast(self)->context, context);
}
+PyObject *
+PyException_GetArgs(PyObject *self)
+{
+ PyObject *args = _PyBaseExceptionObject_cast(self)->args;
+ return Py_NewRef(args);
+}
+
+void
+PyException_SetArgs(PyObject *self, PyObject *args)
+{
+ Py_INCREF(args);
+ Py_XSETREF(_PyBaseExceptionObject_cast(self)->args, args);
+}
+
const char *
PyExceptionClass_Name(PyObject *ob)
{
@@ -578,8 +587,7 @@ StopIteration_init(PyStopIterationObject *self, PyObject *args, PyObject *kwds)
value = PyTuple_GET_ITEM(args, 0);
else
value = Py_None;
- Py_INCREF(value);
- self->value = value;
+ self->value = Py_NewRef(value);
return 0;
}
@@ -605,17 +613,9 @@ StopIteration_traverse(PyStopIterationObject *self, visitproc visit, void *arg)
return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
}
-ComplexExtendsException(
- PyExc_Exception, /* base */
- StopIteration, /* name */
- StopIteration, /* prefix for *_init, etc */
- 0, /* new */
- 0, /* methods */
- StopIteration_members, /* members */
- 0, /* getset */
- 0, /* str */
- "Signal the end from iterator.__next__()."
-);
+ComplexExtendsException(PyExc_Exception, StopIteration, StopIteration,
+ 0, 0, StopIteration_members, 0, 0,
+ "Signal the end from iterator.__next__().");
/*
@@ -640,12 +640,10 @@ SystemExit_init(PySystemExitObject *self, PyObject *args, PyObject *kwds)
if (size == 0)
return 0;
if (size == 1) {
- Py_INCREF(PyTuple_GET_ITEM(args, 0));
- Py_XSETREF(self->code, PyTuple_GET_ITEM(args, 0));
+ Py_XSETREF(self->code, Py_NewRef(PyTuple_GET_ITEM(args, 0)));
}
else { /* size > 1 */
- Py_INCREF(args);
- Py_XSETREF(self->code, args);
+ Py_XSETREF(self->code, Py_NewRef(args));
}
return 0;
}
@@ -1352,7 +1350,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);
@@ -1439,6 +1440,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")},
@@ -1497,11 +1534,12 @@ SimpleExtendsException(PyExc_BaseException, KeyboardInterrupt,
static int
ImportError_init(PyImportErrorObject *self, PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = {"name", "path", 0};
+ static char *kwlist[] = {"name", "path", "name_from", 0};
PyObject *empty_tuple;
PyObject *msg = NULL;
PyObject *name = NULL;
PyObject *path = NULL;
+ PyObject *name_from = NULL;
if (BaseException_init((PyBaseExceptionObject *)self, args, NULL) == -1)
return -1;
@@ -1509,22 +1547,19 @@ ImportError_init(PyImportErrorObject *self, PyObject *args, PyObject *kwds)
empty_tuple = PyTuple_New(0);
if (!empty_tuple)
return -1;
- if (!PyArg_ParseTupleAndKeywords(empty_tuple, kwds, "|$OO:ImportError", kwlist,
- &name, &path)) {
+ if (!PyArg_ParseTupleAndKeywords(empty_tuple, kwds, "|$OOO:ImportError", kwlist,
+ &name, &path, &name_from)) {
Py_DECREF(empty_tuple);
return -1;
}
Py_DECREF(empty_tuple);
- Py_XINCREF(name);
- Py_XSETREF(self->name, name);
-
- Py_XINCREF(path);
- Py_XSETREF(self->path, path);
+ Py_XSETREF(self->name, Py_XNewRef(name));
+ Py_XSETREF(self->path, Py_XNewRef(path));
+ Py_XSETREF(self->name_from, Py_XNewRef(name_from));
if (PyTuple_GET_SIZE(args) == 1) {
- msg = PyTuple_GET_ITEM(args, 0);
- Py_INCREF(msg);
+ msg = Py_NewRef(PyTuple_GET_ITEM(args, 0));
}
Py_XSETREF(self->msg, msg);
@@ -1537,6 +1572,7 @@ ImportError_clear(PyImportErrorObject *self)
Py_CLEAR(self->msg);
Py_CLEAR(self->name);
Py_CLEAR(self->path);
+ Py_CLEAR(self->name_from);
return BaseException_clear((PyBaseExceptionObject *)self);
}
@@ -1554,6 +1590,7 @@ ImportError_traverse(PyImportErrorObject *self, visitproc visit, void *arg)
Py_VISIT(self->msg);
Py_VISIT(self->name);
Py_VISIT(self->path);
+ Py_VISIT(self->name_from);
return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
}
@@ -1561,8 +1598,7 @@ static PyObject *
ImportError_str(PyImportErrorObject *self)
{
if (self->msg && PyUnicode_CheckExact(self->msg)) {
- Py_INCREF(self->msg);
- return self->msg;
+ return Py_NewRef(self->msg);
}
else {
return BaseException_str((PyBaseExceptionObject *)self);
@@ -1573,7 +1609,7 @@ static PyObject *
ImportError_getstate(PyImportErrorObject *self)
{
PyObject *dict = ((PyBaseExceptionObject *)self)->dict;
- if (self->name || self->path) {
+ if (self->name || self->path || self->name_from) {
dict = dict ? PyDict_Copy(dict) : PyDict_New();
if (dict == NULL)
return NULL;
@@ -1585,11 +1621,14 @@ ImportError_getstate(PyImportErrorObject *self)
Py_DECREF(dict);
return NULL;
}
+ if (self->name_from && PyDict_SetItem(dict, &_Py_ID(name_from), self->name_from) < 0) {
+ Py_DECREF(dict);
+ return NULL;
+ }
return dict;
}
else if (dict) {
- Py_INCREF(dict);
- return dict;
+ return Py_NewRef(dict);
}
else {
Py_RETURN_NONE;
@@ -1621,6 +1660,8 @@ static PyMemberDef ImportError_members[] = {
PyDoc_STR("module name")},
{"path", T_OBJECT, offsetof(PyImportErrorObject, path), 0,
PyDoc_STR("module path")},
+ {"name_from", T_OBJECT, offsetof(PyImportErrorObject, name_from), 0,
+ PyDoc_STR("name imported from module")},
{NULL} /* Sentinel */
};
@@ -1714,8 +1755,7 @@ oserror_parse_args(PyObject **p_args,
PyTuple_SET_ITEM(newargs, 0, *myerrno);
for (i = 1; i < nargs; i++) {
PyObject *val = PyTuple_GET_ITEM(args, i);
- Py_INCREF(val);
- PyTuple_SET_ITEM(newargs, i, val);
+ PyTuple_SET_ITEM(newargs, i, Py_NewRef(val));
}
Py_DECREF(args);
args = *p_args = newargs;
@@ -1750,12 +1790,10 @@ oserror_init(PyOSErrorObject *self, PyObject **p_args,
return -1;
}
else {
- Py_INCREF(filename);
- self->filename = filename;
+ self->filename = Py_NewRef(filename);
if (filename2 && filename2 != Py_None) {
- Py_INCREF(filename2);
- self->filename2 = filename2;
+ self->filename2 = Py_NewRef(filename2);
}
if (nargs >= 2 && nargs <= 5) {
@@ -1770,15 +1808,10 @@ oserror_init(PyOSErrorObject *self, PyObject **p_args,
}
}
}
- Py_XINCREF(myerrno);
- self->myerrno = myerrno;
-
- Py_XINCREF(strerror);
- self->strerror = strerror;
-
+ self->myerrno = Py_XNewRef(myerrno);
+ self->strerror = Py_XNewRef(strerror);
#ifdef MS_WINDOWS
- Py_XINCREF(winerror);
- self->winerror = winerror;
+ self->winerror = Py_XNewRef(winerror);
#endif
/* Steals the reference to args */
@@ -2004,7 +2037,7 @@ static PyObject *
OSError_reduce(PyOSErrorObject *self, PyObject *Py_UNUSED(ignored))
{
PyObject *args = self->args;
- PyObject *res = NULL, *tmp;
+ PyObject *res = NULL;
/* self->args is only the first two real arguments if there was a
* file name given to OSError. */
@@ -2014,16 +2047,9 @@ OSError_reduce(PyOSErrorObject *self, PyObject *Py_UNUSED(ignored))
if (!args)
return NULL;
- tmp = PyTuple_GET_ITEM(self->args, 0);
- Py_INCREF(tmp);
- PyTuple_SET_ITEM(args, 0, tmp);
-
- tmp = PyTuple_GET_ITEM(self->args, 1);
- Py_INCREF(tmp);
- PyTuple_SET_ITEM(args, 1, tmp);
-
- Py_INCREF(self->filename);
- PyTuple_SET_ITEM(args, 2, self->filename);
+ PyTuple_SET_ITEM(args, 0, Py_NewRef(PyTuple_GET_ITEM(self->args, 0)));
+ PyTuple_SET_ITEM(args, 1, Py_NewRef(PyTuple_GET_ITEM(self->args, 1)));
+ PyTuple_SET_ITEM(args, 2, Py_NewRef(self->filename));
if (self->filename2) {
/*
@@ -2031,12 +2057,10 @@ OSError_reduce(PyOSErrorObject *self, PyObject *Py_UNUSED(ignored))
* So, to recreate filename2, we need to pass in
* winerror as well.
*/
- Py_INCREF(Py_None);
- PyTuple_SET_ITEM(args, 3, Py_None);
+ PyTuple_SET_ITEM(args, 3, Py_NewRef(Py_None));
/* filename2 */
- Py_INCREF(self->filename2);
- PyTuple_SET_ITEM(args, 4, self->filename2);
+ PyTuple_SET_ITEM(args, 4, Py_NewRef(self->filename2));
}
} else
Py_INCREF(args);
@@ -2197,8 +2221,7 @@ NameError_init(PyNameErrorObject *self, PyObject *args, PyObject *kwds)
}
Py_DECREF(empty_tuple);
- Py_XINCREF(name);
- Py_XSETREF(self->name, name);
+ Py_XSETREF(self->name, Py_XNewRef(name));
return 0;
}
@@ -2272,11 +2295,8 @@ AttributeError_init(PyAttributeErrorObject *self, PyObject *args, PyObject *kwds
}
Py_DECREF(empty_tuple);
- Py_XINCREF(name);
- Py_XSETREF(self->name, name);
-
- Py_XINCREF(obj);
- Py_XSETREF(self->obj, obj);
+ Py_XSETREF(self->name, Py_XNewRef(name));
+ Py_XSETREF(self->obj, Py_XNewRef(obj));
return 0;
}
@@ -2305,6 +2325,48 @@ AttributeError_traverse(PyAttributeErrorObject *self, visitproc visit, void *arg
return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
}
+/* Pickling support */
+static PyObject *
+AttributeError_getstate(PyAttributeErrorObject *self, PyObject *Py_UNUSED(ignored))
+{
+ PyObject *dict = ((PyAttributeErrorObject *)self)->dict;
+ if (self->name || self->args) {
+ dict = dict ? PyDict_Copy(dict) : PyDict_New();
+ if (dict == NULL) {
+ return NULL;
+ }
+ if (self->name && PyDict_SetItemString(dict, "name", self->name) < 0) {
+ Py_DECREF(dict);
+ return NULL;
+ }
+ /* We specifically are not pickling the obj attribute since there are many
+ cases where it is unlikely to be picklable. See GH-103352.
+ */
+ if (self->args && PyDict_SetItemString(dict, "args", self->args) < 0) {
+ Py_DECREF(dict);
+ return NULL;
+ }
+ return dict;
+ }
+ else if (dict) {
+ return Py_NewRef(dict);
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+AttributeError_reduce(PyAttributeErrorObject *self, PyObject *Py_UNUSED(ignored))
+{
+ PyObject *state = AttributeError_getstate(self, NULL);
+ if (state == NULL) {
+ return NULL;
+ }
+
+ PyObject *return_value = PyTuple_Pack(3, Py_TYPE(self), self->args, state);
+ Py_DECREF(state);
+ return return_value;
+}
+
static PyMemberDef AttributeError_members[] = {
{"name", T_OBJECT, offsetof(PyAttributeErrorObject, name), 0, PyDoc_STR("attribute name")},
{"obj", T_OBJECT, offsetof(PyAttributeErrorObject, obj), 0, PyDoc_STR("object")},
@@ -2312,7 +2374,9 @@ static PyMemberDef AttributeError_members[] = {
};
static PyMethodDef AttributeError_methods[] = {
- {NULL} /* Sentinel */
+ {"__getstate__", (PyCFunction)AttributeError_getstate, METH_NOARGS},
+ {"__reduce__", (PyCFunction)AttributeError_reduce, METH_NOARGS },
+ {NULL}
};
ComplexExtendsException(PyExc_Exception, AttributeError,
@@ -2334,8 +2398,7 @@ SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds)
return -1;
if (lenargs >= 1) {
- Py_INCREF(PyTuple_GET_ITEM(args, 0));
- Py_XSETREF(self->msg, PyTuple_GET_ITEM(args, 0));
+ Py_XSETREF(self->msg, Py_NewRef(PyTuple_GET_ITEM(args, 0)));
}
if (lenargs == 2) {
info = PyTuple_GET_ITEM(args, 1);
@@ -2431,8 +2494,7 @@ my_basename(PyObject *name)
return PyUnicode_Substring(name, offset, size);
}
else {
- Py_INCREF(name);
- return name;
+ return Py_NewRef(name);
}
}
@@ -2584,8 +2646,7 @@ get_string(PyObject *attr, const char *name)
PyErr_Format(PyExc_TypeError, "%.200s attribute must be bytes", name);
return NULL;
}
- Py_INCREF(attr);
- return attr;
+ return Py_NewRef(attr);
}
static PyObject *
@@ -2601,8 +2662,7 @@ get_unicode(PyObject *attr, const char *name)
"%.200s attribute must be unicode", name);
return NULL;
}
- Py_INCREF(attr);
- return attr;
+ return Py_NewRef(attr);
}
static int
@@ -3235,19 +3295,18 @@ SimpleExtendsException(PyExc_Exception, ReferenceError,
#define MEMERRORS_SAVE 16
static PyObject *
-MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+get_memory_error(int allow_allocation, PyObject *args, PyObject *kwds)
{
PyBaseExceptionObject *self;
-
- /* If this is a subclass of MemoryError, don't use the freelist
- * and just return a fresh object */
- if (type != (PyTypeObject *) PyExc_MemoryError) {
- return BaseException_new(type, args, kwds);
- }
-
struct _Py_exc_state *state = get_exc_state();
if (state->memerrors_freelist == NULL) {
- return BaseException_new(type, args, kwds);
+ if (!allow_allocation) {
+ PyInterpreterState *interp = _PyInterpreterState_GET();
+ return Py_NewRef(
+ &_Py_INTERP_SINGLETON(interp, last_resort_memory_error));
+ }
+ PyObject *result = BaseException_new((PyTypeObject *)PyExc_MemoryError, args, kwds);
+ return result;
}
/* Fetch object from freelist and revive it */
@@ -3267,6 +3326,33 @@ MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return (PyObject *)self;
}
+static PyObject *
+MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ /* If this is a subclass of MemoryError, don't use the freelist
+ * and just return a fresh object */
+ if (type != (PyTypeObject *) PyExc_MemoryError) {
+ return BaseException_new(type, args, kwds);
+ }
+ return get_memory_error(1, args, kwds);
+}
+
+PyObject *
+_PyErr_NoMemory(PyThreadState *tstate)
+{
+ if (Py_IS_TYPE(PyExc_MemoryError, NULL)) {
+ /* PyErr_NoMemory() has been called before PyExc_MemoryError has been
+ initialized by _PyExc_Init() */
+ Py_FatalError("Out of memory and PyExc_MemoryError is not "
+ "initialized yet");
+ }
+ PyObject *err = get_memory_error(0, NULL, NULL);
+ if (err != NULL) {
+ _PyErr_SetRaisedException(tstate, err);
+ }
+ return NULL;
+}
+
static void
MemoryError_dealloc(PyBaseExceptionObject *self)
{
@@ -3298,6 +3384,7 @@ preallocate_memerrors(void)
/* We create enough MemoryErrors and then decref them, which will fill
up the freelist. */
int i;
+
PyObject *errors[MEMERRORS_SAVE];
for (i = 0; i < MEMERRORS_SAVE; i++) {
errors[i] = MemoryError_new((PyTypeObject *) PyExc_MemoryError,
@@ -3323,7 +3410,7 @@ free_preallocated_memerrors(struct _Py_exc_state *state)
}
-static PyTypeObject _PyExc_MemoryError = {
+PyTypeObject _PyExc_MemoryError = {
PyVarObject_HEAD_INIT(NULL, 0)
"MemoryError",
sizeof(PyBaseExceptionObject),
@@ -3591,14 +3678,9 @@ static struct static_exception static_exceptions[] = {
int
_PyExc_InitTypes(PyInterpreterState *interp)
{
- if (!_Py_IsMainInterpreter(interp)) {
- return 0;
- }
-
for (size_t i=0; i < Py_ARRAY_LENGTH(static_exceptions); i++) {
PyTypeObject *exc = static_exceptions[i].exc;
-
- if (PyType_Ready(exc) < 0) {
+ if (_PyStaticType_InitBuiltin(interp, exc) < 0) {
return -1;
}
}
@@ -3609,13 +3691,9 @@ _PyExc_InitTypes(PyInterpreterState *interp)
static void
_PyExc_FiniTypes(PyInterpreterState *interp)
{
- if (!_Py_IsMainInterpreter(interp)) {
- return;
- }
-
for (Py_ssize_t i=Py_ARRAY_LENGTH(static_exceptions) - 1; i >= 0; i--) {
PyTypeObject *exc = static_exceptions[i].exc;
- _PyStaticType_Dealloc(exc);
+ _PyStaticType_Dealloc(interp, exc);
}
}
@@ -3623,10 +3701,6 @@ _PyExc_FiniTypes(PyInterpreterState *interp)
PyStatus
_PyExc_InitGlobalObjects(PyInterpreterState *interp)
{
- if (!_Py_IsMainInterpreter(interp)) {
- return _PyStatus_OK();
- }
-
if (preallocate_memerrors() < 0) {
return _PyStatus_NO_MEMORY();
}
@@ -3750,130 +3824,18 @@ _PyExc_Fini(PyInterpreterState *interp)
_PyExc_FiniTypes(interp);
}
-/* Helper to do the equivalent of "raise X from Y" in C, but always using
- * the current exception rather than passing one in.
- *
- * We currently limit this to *only* exceptions that use the BaseException
- * tp_init and tp_new methods, since we can be reasonably sure we can wrap
- * those correctly without losing data and without losing backwards
- * compatibility.
- *
- * We also aim to rule out *all* exceptions that might be storing additional
- * state, whether by having a size difference relative to BaseException,
- * additional arguments passed in during construction or by having a
- * non-empty instance dict.
- *
- * We need to be very careful with what we wrap, since changing types to
- * a broader exception type would be backwards incompatible for
- * existing codecs, and with different init or new method implementations
- * may either not support instantiation with PyErr_Format or lose
- * information when instantiated that way.
- *
- * XXX (ncoghlan): This could be made more comprehensive by exploiting the
- * fact that exceptions are expected to support pickling. If more builtin
- * exceptions (e.g. AttributeError) start to be converted to rich
- * exceptions with additional attributes, that's probably a better approach
- * to pursue over adding special cases for particular stateful subclasses.
- *
- * Returns a borrowed reference to the new exception (if any), NULL if the
- * existing exception was left in place.
- */
-PyObject *
-_PyErr_TrySetFromCause(const char *format, ...)
-{
- PyObject* msg_prefix;
- PyObject *exc, *val, *tb;
- PyTypeObject *caught_type;
- PyObject *instance_args;
- Py_ssize_t num_args, caught_type_size, base_exc_size;
- PyObject *new_exc, *new_val, *new_tb;
- va_list vargs;
- int same_basic_size;
-
- PyErr_Fetch(&exc, &val, &tb);
- caught_type = (PyTypeObject *)exc;
- /* Ensure type info indicates no extra state is stored at the C level
- * and that the type can be reinstantiated using PyErr_Format
- */
- caught_type_size = caught_type->tp_basicsize;
- base_exc_size = _PyExc_BaseException.tp_basicsize;
- same_basic_size = (
- caught_type_size == base_exc_size ||
- (_PyType_SUPPORTS_WEAKREFS(caught_type) &&
- (caught_type_size == base_exc_size + (Py_ssize_t)sizeof(PyObject *))
- )
- );
- if (caught_type->tp_init != (initproc)BaseException_init ||
- caught_type->tp_new != BaseException_new ||
- !same_basic_size ||
- caught_type->tp_itemsize != _PyExc_BaseException.tp_itemsize) {
- /* We can't be sure we can wrap this safely, since it may contain
- * more state than just the exception type. Accordingly, we just
- * leave it alone.
- */
- PyErr_Restore(exc, val, tb);
- return NULL;
- }
-
- /* Check the args are empty or contain a single string */
- PyErr_NormalizeException(&exc, &val, &tb);
- instance_args = ((PyBaseExceptionObject *)val)->args;
- num_args = PyTuple_GET_SIZE(instance_args);
- if (num_args > 1 ||
- (num_args == 1 &&
- !PyUnicode_CheckExact(PyTuple_GET_ITEM(instance_args, 0)))) {
- /* More than 1 arg, or the one arg we do have isn't a string
- */
- PyErr_Restore(exc, val, tb);
- return NULL;
- }
-
- /* Ensure the instance dict is also empty */
- if (!_PyObject_IsInstanceDictEmpty(val)) {
- /* While we could potentially copy a non-empty instance dictionary
- * to the replacement exception, for now we take the more
- * conservative path of leaving exceptions with attributes set
- * alone.
- */
- PyErr_Restore(exc, val, tb);
- return NULL;
- }
-
- /* For exceptions that we can wrap safely, we chain the original
- * exception to a new one of the exact same type with an
- * error message that mentions the additional details and the
- * original exception.
- *
- * It would be nice to wrap OSError and various other exception
- * types as well, but that's quite a bit trickier due to the extra
- * state potentially stored on OSError instances.
- */
- /* Ensure the traceback is set correctly on the existing exception */
- if (tb != NULL) {
- PyException_SetTraceback(val, tb);
- Py_DECREF(tb);
- }
-
-#ifdef HAVE_STDARG_PROTOTYPES
- va_start(vargs, format);
-#else
- va_start(vargs);
-#endif
- msg_prefix = PyUnicode_FromFormatV(format, vargs);
- va_end(vargs);
- if (msg_prefix == NULL) {
- Py_DECREF(exc);
- Py_DECREF(val);
- return NULL;
+int
+_PyException_AddNote(PyObject *exc, PyObject *note)
+{
+ if (!PyExceptionInstance_Check(exc)) {
+ PyErr_Format(PyExc_TypeError,
+ "exc must be an exception, not '%s'",
+ Py_TYPE(exc)->tp_name);
+ return -1;
}
-
- PyErr_Format(exc, "%U (%s: %S)",
- msg_prefix, Py_TYPE(val)->tp_name, val);
- Py_DECREF(exc);
- Py_DECREF(msg_prefix);
- PyErr_Fetch(&new_exc, &new_val, &new_tb);
- PyErr_NormalizeException(&new_exc, &new_val, &new_tb);
- PyException_SetCause(new_val, val);
- PyErr_Restore(new_exc, new_val, new_tb);
- return new_val;
+ PyObject *r = BaseException_add_note(exc, note);
+ int res = r == NULL ? -1 : 0;
+ Py_XDECREF(r);
+ return res;
}
+