[Python-checkins] r70941 - in python/branches/py3k: Lib/test/test_functools.py Misc/ACKS Misc/NEWS Modules/_functoolsmodule.c

jack.diederich python-checkins at python.org
Wed Apr 1 06:27:09 CEST 2009


Author: jack.diederich
Date: Wed Apr 1 06:27:09 2009
New Revision: 70941
Log:
Merged revisions 70931 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/trunk
........
 r70931 | jack.diederich | 2009年03月31日 19:46:48 -0400 (2009年3月31日) | 1 line
 
 #5228: add pickle support to functools.partial
........
Modified:
 python/branches/py3k/ (props changed)
 python/branches/py3k/Lib/test/test_functools.py
 python/branches/py3k/Misc/ACKS
 python/branches/py3k/Misc/NEWS
 python/branches/py3k/Modules/_functoolsmodule.c
Modified: python/branches/py3k/Lib/test/test_functools.py
==============================================================================
--- python/branches/py3k/Lib/test/test_functools.py	(original)
+++ python/branches/py3k/Lib/test/test_functools.py	Wed Apr 1 06:27:09 2009
@@ -2,6 +2,7 @@
 import unittest
 from test import support
 from weakref import proxy
+import pickle
 
 @staticmethod
 def PythonPartial(func, *args, **keywords):
@@ -19,6 +20,9 @@
 """capture all positional and keyword arguments"""
 return args, kw
 
+def signature(part):
+ """ return the signature of a partial object """
+ return (part.func, part.args, part.keywords, part.__dict__)
 
 class TestPartial(unittest.TestCase):
 
@@ -141,6 +145,12 @@
 join = self.thetype(''.join)
 self.assertEqual(join(data), '0123456789')
 
+ def test_pickle(self):
+ f = self.thetype(signature, 'asdf', bar=True)
+ f.add_something_to__dict__ = True
+ f_copy = pickle.loads(pickle.dumps(f))
+ self.assertEqual(signature(f), signature(f_copy))
+
 class PartialSubclass(functools.partial):
 pass
 
@@ -148,11 +158,13 @@
 
 thetype = PartialSubclass
 
-
 class TestPythonPartial(TestPartial):
 
 thetype = PythonPartial
 
+ # the python version isn't picklable
+ def test_pickle(self): pass
+
 class TestUpdateWrapper(unittest.TestCase):
 
 def check_wrapper(self, wrapper, wrapped,
Modified: python/branches/py3k/Misc/ACKS
==============================================================================
--- python/branches/py3k/Misc/ACKS	(original)
+++ python/branches/py3k/Misc/ACKS	Wed Apr 1 06:27:09 2009
@@ -167,6 +167,7 @@
 Raghuram Devarakonda
 Toby Dickenson
 Mark Dickinson
+Jack Diederich
 Humberto Diogenes
 Yves Dionne
 Daniel Dittmar
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Wed Apr 1 06:27:09 2009
@@ -726,6 +726,8 @@
 buffer.
 
 
+- Issue #5228: Make functools.partial objects can now be pickled.
+
 Tests
 -----
 
Modified: python/branches/py3k/Modules/_functoolsmodule.c
==============================================================================
--- python/branches/py3k/Modules/_functoolsmodule.c	(original)
+++ python/branches/py3k/Modules/_functoolsmodule.c	Wed Apr 1 06:27:09 2009
@@ -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 */


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /