]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
backport gvanrossum's checkin of
authorMichael W. Hudson <mwh@python.net>
Sat, 16 Mar 2002 17:56:51 +0000 (17:56 +0000)
committerMichael W. Hudson <mwh@python.net>
Sat, 16 Mar 2002 17:56:51 +0000 (17:56 +0000)
    revision 2.129 of typeobject.c

"Fix" for SF bug #520644: __slots__ are not pickled.

As promised in my response to the bug report, I'm not really fixing
it; in fact, one could argule over what the proper fix should do.
Instead, I'm adding a little magic that raises TypeError if you try to
pickle an instance of a class that has __slots__ but doesn't define or
override __getstate__.  This is done by adding a bozo __getstate__
that always raises TypeError.

Objects/typeobject.c

index 2ad1638a29dc9cc0b9fd1f23084c79968a460d0f..ca7e64d8cfb1c809ae7813d72b6d6adea78f6a4c 100644 (file)
@@ -850,6 +850,21 @@ static PyGetSetDef subtype_getsets[] = {
        {0},
 };
 
+/* bozo: __getstate__ that raises TypeError */
+
+static PyObject *
+bozo_func(PyObject *self, PyObject *args)
+{
+       PyErr_SetString(PyExc_TypeError,
+                       "a class that defines __slots__ without "
+                       "defining __getstate__ cannot be pickled");
+       return NULL;
+}
+
+static PyMethodDef bozo_ml = {"__getstate__", bozo_func};
+
+static PyObject *bozo_obj = NULL;
+
 static PyObject *
 type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
 {
@@ -973,6 +988,27 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
                        /* XXX Check against null bytes in name */
                }
        }
+       if (slots != NULL) {
+               /* See if *this* class defines __getstate__ */
+               PyObject *getstate = PyDict_GetItemString(dict,
+                                                         "__getstate__");
+               if (getstate == NULL) {
+                       /* If not, provide a bozo that raises TypeError */
+                       if (bozo_obj == NULL) {
+                               bozo_obj = PyCFunction_New(&bozo_ml, NULL);
+                               if (bozo_obj == NULL) {
+                                       /* XXX decref various things */
+                                       return NULL;
+                               }
+                       }
+                       if (PyDict_SetItemString(dict,
+                                                "__getstate__",
+                                                bozo_obj) < 0) {
+                               /* XXX decref various things */
+                               return NULL;
+                       }
+               }
+       }
        if (slots == NULL && base->tp_dictoffset == 0 &&
            (base->tp_setattro == PyObject_GenericSetAttr ||
             base->tp_setattro == NULL)) {
@@ -1654,7 +1690,7 @@ add_methods(PyTypeObject *type, PyMethodDef *meth)
                descr = PyDescr_NewMethod(type, meth);
                if (descr == NULL)
                        return -1;
-               if (PyDict_SetItemString(dict,meth->ml_name,descr) < 0)
+               if (PyDict_SetItemString(dict,meth->ml_name, descr) < 0)
                        return -1;
                Py_DECREF(descr);
        }