summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael W. Hudson <mwh@python.net>2002-03-16 17:56:51 (GMT)
committerMichael W. Hudson <mwh@python.net>2002-03-16 17:56:51 (GMT)
commit18d81afd2364a4f21ad4d5a63eb7604ff019229f (patch)
treeb0d68ac6745b7edd58811a6ad5619a85262145e1
parent3df46a80289790a3fbb26b7eafa7070373a8539e (diff)
downloadcpython-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.c38
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);
}