mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
"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.
This commit is contained in:
parent
06b711cb6d
commit
0628dcfe1f
1 changed files with 37 additions and 1 deletions
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue