gh-103333: Pickle the keyword attributes of AttributeError (#103352)

* Pickle the `name` and `args` attributes of AttributeError when present.

Co-authored-by: Gregory P. Smith <greg@krypto.org>
Co-authored-by: Erlend E. Aasland <erlend.aasland@protonmail.com>
This commit is contained in:
Charles Machalow 2023-05-12 13:33:23 -07:00 committed by GitHub
parent cf720acfcb
commit 79b17f2cf0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 78 additions and 28 deletions

View file

@ -2287,6 +2287,46 @@ 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;
}
return PyTuple_Pack(3, Py_TYPE(self), self->args, state);
}
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")},
@ -2294,7 +2334,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,