Merged revisions 70931 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r70931 | jack.diederich | 2009-03-31 19:46:48 -0400 (Tue, 31 Mar 2009) | 1 line

  #5228: add pickle support to functools.partial
........
diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
index 369eb5c..5f389a9 100644
--- a/Modules/_functoolsmodule.c
+++ b/Modules/_functoolsmodule.c
@@ -196,6 +196,53 @@
 	{NULL} /* Sentinel */
 };
 
+/* Pickle strategy:
+   __reduce__ by itself doesn't support getting kwargs in the unpickle
+   operation so we define a __setstate__ that replaces all the information
+   about the partial.  If we only replaced part of it someone would use
+   it as a hook to do stange things.
+ */
+
+PyObject *
+partial_reduce(partialobject *pto, PyObject *unused)
+{
+	return Py_BuildValue("O(O)(OOOO)", Py_TYPE(pto), pto->fn, pto->fn, 
+			     pto->args, pto->kw,
+			     pto->dict ? pto->dict : Py_None);
+}
+
+PyObject *
+partial_setstate(partialobject *pto, PyObject *args)
+{
+	PyObject *fn, *fnargs, *kw, *dict;
+	if (!PyArg_ParseTuple(args, "(OOOO):__setstate__", 
+			      &fn, &fnargs, &kw, &dict))
+		return NULL;
+	Py_XDECREF(pto->fn);
+	Py_XDECREF(pto->args);
+	Py_XDECREF(pto->kw);
+	Py_XDECREF(pto->dict);
+	pto->fn = fn;
+	pto->args = fnargs;
+	pto->kw = kw;
+	if (dict != Py_None) {
+	  pto->dict = dict;
+	  Py_INCREF(dict);
+	} else {
+	  pto->dict = NULL;
+	}
+	Py_INCREF(fn);
+	Py_INCREF(fnargs);
+	Py_INCREF(kw);
+	Py_RETURN_NONE;
+}
+
+static PyMethodDef partial_methods[] = {
+	{"__reduce__", (PyCFunction)partial_reduce, METH_NOARGS},
+	{"__setstate__", (PyCFunction)partial_setstate, METH_VARARGS},
+	{NULL,		NULL}		/* sentinel */
+};
+
 static PyTypeObject partial_type = {
 	PyVarObject_HEAD_INIT(NULL, 0)
 	"functools.partial",		/* tp_name */
@@ -226,7 +273,7 @@
 	offsetof(partialobject, weakreflist),	/* tp_weaklistoffset */
 	0,				/* tp_iter */
 	0,				/* tp_iternext */
-	0,				/* tp_methods */
+	partial_methods,		/* tp_methods */
 	partial_memberlist,		/* tp_members */
 	partial_getsetlist,		/* tp_getset */
 	0,				/* tp_base */