]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Make built-in methods picklable through the reduce protocol.
authorAlexandre Vassalotti <alexandre@peadrop.com>
Sun, 24 Nov 2013 10:41:05 +0000 (02:41 -0800)
committerAlexandre Vassalotti <alexandre@peadrop.com>
Sun, 24 Nov 2013 10:41:05 +0000 (02:41 -0800)
Lib/pickle.py
Modules/_pickle.c
Objects/methodobject.c

index 8449340e7f49e4de3291ebbb52c7f0b207a643bc..d4aa13bd0c635ad6a7caea9059f539c8fa34c68a 100644 (file)
@@ -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
 
 
index 741cb8a7a2e93b3b3973359b0bf4985dea6fd5fd..f0c918f87e036a78d99a7afac6d56afa0e1c1e39 100644 (file)
@@ -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. */
 
index ca21a68e2e04a564dfff57b3459f0a944833bac8..55a7d6a35eaf06544f7f2f901893c79395d82be7 100644 (file)
@@ -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 */