Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c53f009

Browse files
committed
Introducing __reduce_ex__, which is called with a protocol number argument
if it exists in preference over __reduce__. Now Tim can go implement this in cPickle.c.
1 parent 2b0643a commit c53f009

4 files changed

Lines changed: 36 additions & 19 deletions

File tree

Lib/copy_reg.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,17 @@ def _better_reduce(obj):
109109
dictitems = obj.iteritems()
110110
return __newobj__, (cls,) + args, state, listitems, dictitems
111111

112+
# Extended reduce:
113+
114+
def _reduce_ex(obj, proto=0):
115+
obj_reduce = getattr(obj, "__reduce__", None)
116+
if obj_reduce and obj.__class__.__reduce__ is not object.__reduce__:
117+
return obj_reduce()
118+
elif proto < 2:
119+
return _reduce(obj)
120+
else:
121+
return _better_reduce(obj)
122+
112123
def _slotnames(cls):
113124
"""Return a list of slot names for a given class.
114125

Lib/pickle.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -304,21 +304,20 @@ def save(self, obj):
304304

305305
# Check copy_reg.dispatch_table
306306
reduce = dispatch_table.get(t)
307-
if not reduce:
308-
# Check for a __reduce__ method.
309-
# Subtle: get the unbound method from the class, so that
310-
# protocol 2 can override the default __reduce__ that all
311-
# classes inherit from object. This has the added
312-
# advantage that the call always has the form reduce(obj)
313-
reduce = getattr(t, "__reduce__", None)
314-
if self.proto >= 2:
315-
# Protocol 2 can do better than the default __reduce__
316-
if reduce is object.__reduce__:
317-
reduce = _better_reduce
318-
if not reduce:
319-
raise PicklingError("Can't pickle %r object: %r" %
320-
(t.__name__, obj))
321-
rv = reduce(obj)
307+
if reduce:
308+
rv = reduce(obj)
309+
else:
310+
# Check for a __reduce_ex__ method, fall back to __reduce__
311+
reduce = getattr(obj, "__reduce_ex__", None)
312+
if reduce:
313+
rv = reduce(self.proto)
314+
else:
315+
reduce = getattr(obj, "__reduce__", None)
316+
if reduce:
317+
rv = reduce()
318+
else:
319+
raise PicklingError("Can't pickle %r object: %r" %
320+
(t.__name__, obj))
322321

323322
# Check for string returned by reduce(), meaning "save as global"
324323
if type(rv) is StringType:

Lib/test/test_descrtut.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ def merge(self, other):
210210
'__ne__',
211211
'__new__',
212212
'__reduce__',
213+
'__reduce_ex__',
213214
'__repr__',
214215
'__rmul__',
215216
'__setattr__',

Objects/typeobject.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2441,11 +2441,15 @@ static PyGetSetDef object_getsets[] = {
24412441
};
24422442

24432443
static PyObject *
2444-
object_reduce(PyObject *self, PyObject *args)
2444+
object_reduce_ex(PyObject *self, PyObject *args)
24452445
{
2446-
/* Call copy_reg._reduce(self) */
2446+
/* Call copy_reg._reduce_ex(self, proto) */
24472447
static PyObject *copy_reg_str;
24482448
PyObject *copy_reg, *res;
2449+
int proto = 0;
2450+
2451+
if (!PyArg_ParseTuple(args, "|i:__reduce_ex__", &proto))
2452+
return NULL;
24492453

24502454
if (!copy_reg_str) {
24512455
copy_reg_str = PyString_InternFromString("copy_reg");
@@ -2455,13 +2459,15 @@ object_reduce(PyObject *self, PyObject *args)
24552459
copy_reg = PyImport_Import(copy_reg_str);
24562460
if (!copy_reg)
24572461
return NULL;
2458-
res = PyEval_CallMethod(copy_reg, "_reduce", "(O)", self);
2462+
res = PyEval_CallMethod(copy_reg, "_reduce_ex", "(Oi)", self, proto);
24592463
Py_DECREF(copy_reg);
24602464
return res;
24612465
}
24622466

24632467
static PyMethodDef object_methods[] = {
2464-
{"__reduce__", object_reduce, METH_NOARGS,
2468+
{"__reduce_ex__", object_reduce_ex, METH_VARARGS,
2469+
PyDoc_STR("helper for pickle")},
2470+
{"__reduce__", object_reduce_ex, METH_VARARGS,
24652471
PyDoc_STR("helper for pickle")},
24662472
{0}
24672473
};

0 commit comments

Comments
 (0)