mirror of
https://github.com/python/cpython.git
synced 2025-12-08 02:08:20 +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},
|
{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 *
|
static PyObject *
|
||||||
type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
|
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 */
|
/* 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 &&
|
if (slots == NULL && base->tp_dictoffset == 0 &&
|
||||||
(base->tp_setattro == PyObject_GenericSetAttr ||
|
(base->tp_setattro == PyObject_GenericSetAttr ||
|
||||||
base->tp_setattro == NULL)) {
|
base->tp_setattro == NULL)) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue