diff options
author | Michael W. Hudson <mwh@python.net> | 2002-03-16 17:56:51 (GMT) |
---|---|---|
committer | Michael W. Hudson <mwh@python.net> | 2002-03-16 17:56:51 (GMT) |
commit | 18d81afd2364a4f21ad4d5a63eb7604ff019229f (patch) | |
tree | b0d68ac6745b7edd58811a6ad5619a85262145e1 | |
parent | 3df46a80289790a3fbb26b7eafa7070373a8539e (diff) | |
download | cpython-18d81afd2364a4f21ad4d5a63eb7604ff019229f.zip cpython-18d81afd2364a4f21ad4d5a63eb7604ff019229f.tar.gz cpython-18d81afd2364a4f21ad4d5a63eb7604ff019229f.tar.bz2 |
backport gvanrossum's checkin of
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.
-rw-r--r-- | Objects/typeobject.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 2ad1638..ca7e64d 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -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); } |