Make built-in methods picklable through the reduce protocol.
This commit is contained in:
parent
d606ba7f55
commit
4c05d3bc56
|
@ -23,7 +23,7 @@ Misc variables:
|
|||
|
||||
"""
|
||||
|
||||
from types import FunctionType, BuiltinFunctionType, ModuleType
|
||||
from types import FunctionType, ModuleType
|
||||
from copyreg import dispatch_table
|
||||
from copyreg import _extension_registry, _inverted_registry, _extension_cache
|
||||
from itertools import islice
|
||||
|
@ -962,14 +962,7 @@ class _Pickler:
|
|||
|
||||
self.memoize(obj)
|
||||
|
||||
def save_method(self, obj):
|
||||
if obj.__self__ is None or type(obj.__self__) is ModuleType:
|
||||
self.save_global(obj)
|
||||
else:
|
||||
self.save_reduce(getattr, (obj.__self__, obj.__name__), obj=obj)
|
||||
|
||||
dispatch[FunctionType] = save_global
|
||||
dispatch[BuiltinFunctionType] = save_method
|
||||
dispatch[type] = save_global
|
||||
|
||||
|
||||
|
|
|
@ -3513,34 +3513,6 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
save_method(PicklerObject *self, PyObject *obj)
|
||||
{
|
||||
PyObject *method_self = PyCFunction_GET_SELF(obj);
|
||||
|
||||
if (method_self == NULL || PyModule_Check(method_self)) {
|
||||
return save_global(self, obj, NULL);
|
||||
}
|
||||
else {
|
||||
PyObject *builtins;
|
||||
PyObject *getattr;
|
||||
PyObject *reduce_value;
|
||||
int status = -1;
|
||||
_Py_IDENTIFIER(getattr);
|
||||
|
||||
builtins = PyEval_GetBuiltins();
|
||||
getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
|
||||
reduce_value = \
|
||||
Py_BuildValue("O(Os)", getattr, method_self,
|
||||
((PyCFunctionObject *)obj)->m_ml->ml_name);
|
||||
if (reduce_value != NULL) {
|
||||
status = save_reduce(self, reduce_value, obj);
|
||||
Py_DECREF(reduce_value);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
save(PicklerObject *self, PyObject *obj, int pers_save)
|
||||
{
|
||||
|
@ -3652,10 +3624,6 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
|
|||
goto done;
|
||||
}
|
||||
}
|
||||
else if (type == &PyCFunction_Type) {
|
||||
status = save_method(self, obj);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* XXX: This part needs some unit tests. */
|
||||
|
||||
|
|
|
@ -159,6 +159,26 @@ meth_dealloc(PyCFunctionObject *m)
|
|||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
meth_reduce(PyCFunctionObject *m)
|
||||
{
|
||||
PyObject *builtins;
|
||||
PyObject *getattr;
|
||||
_Py_IDENTIFIER(getattr);
|
||||
|
||||
if (m->m_self == NULL || PyModule_Check(m->m_self))
|
||||
return PyUnicode_FromString(m->m_ml->ml_name);
|
||||
|
||||
builtins = PyEval_GetBuiltins();
|
||||
getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
|
||||
return Py_BuildValue("O(Os)", getattr, m->m_self, m->m_ml->ml_name);
|
||||
}
|
||||
|
||||
static PyMethodDef meth_methods[] = {
|
||||
{"__reduce__", (PyCFunction)meth_reduce, METH_NOARGS, NULL},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/*
|
||||
* finds the docstring's introspection signature.
|
||||
* if present, returns a pointer pointing to the first '('.
|
||||
|
@ -394,7 +414,7 @@ PyTypeObject PyCFunction_Type = {
|
|||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
meth_methods, /* tp_methods */
|
||||
meth_members, /* tp_members */
|
||||
meth_getsets, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
|
|
Loading…
Reference in New Issue