summaryrefslogtreecommitdiffstats
path: root/Objects/exceptions.c
diff options
context:
space:
mode:
authorCharles Machalow <csm10495@gmail.com>2023-05-12 20:33:23 (GMT)
committerGitHub <noreply@github.com>2023-05-12 20:33:23 (GMT)
commit79b17f2cf0e1a2688bd91df02744f461835c4253 (patch)
treecb576467384cd2f4f2080184472e806af26b37f9 /Objects/exceptions.c
parentcf720acfcbd8c9c25a706a4b6df136465a803992 (diff)
downloadcpython-79b17f2cf0e1a2688bd91df02744f461835c4253.zip
cpython-79b17f2cf0e1a2688bd91df02744f461835c4253.tar.gz
cpython-79b17f2cf0e1a2688bd91df02744f461835c4253.tar.bz2
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>
Diffstat (limited to 'Objects/exceptions.c')
-rw-r--r--Objects/exceptions.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index ba5ee29..59c63f4 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -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,