Issue #25718: Fixed pickling and copying the accumulate() iterator with total is None.

This commit is contained in:
Serhiy Storchaka 2016-03-06 14:02:26 +02:00
commit 5608411a96
3 changed files with 30 additions and 0 deletions

View File

@ -1448,6 +1448,16 @@ class TestExamples(unittest.TestCase):
self.assertEqual(list(copy.deepcopy(it)), accumulated[1:])
self.assertEqual(list(copy.copy(it)), accumulated[1:])
def test_accumulate_reducible_none(self):
# Issue #25718: total is None
it = accumulate([None, None, None], operator.is_)
self.assertEqual(next(it), None)
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
it_copy = pickle.loads(pickle.dumps(it, proto))
self.assertEqual(list(it_copy), [True, False])
self.assertEqual(list(copy.deepcopy(it)), [True, False])
self.assertEqual(list(copy.copy(it)), [True, False])
def test_chain(self):
self.assertEqual(''.join(chain('ABC', 'DEF')), 'ABCDEF')

View File

@ -201,6 +201,9 @@ Core and Builtins
Library
-------
- Issue #25718: Fixed pickling and copying the accumulate() iterator with
total is None.
- Issue #26475: Fixed debugging output for regular expressions with the (?x)
flag.

View File

@ -3464,6 +3464,23 @@ accumulate_next(accumulateobject *lz)
static PyObject *
accumulate_reduce(accumulateobject *lz)
{
if (lz->total == Py_None) {
PyObject *it;
if (PyType_Ready(&chain_type) < 0)
return NULL;
if (PyType_Ready(&islice_type) < 0)
return NULL;
it = PyObject_CallFunction((PyObject *)&chain_type, "(O)O",
lz->total, lz->it);
if (it == NULL)
return NULL;
it = PyObject_CallFunction((PyObject *)Py_TYPE(lz), "NO",
it, lz->binop ? lz->binop : Py_None);
if (it == NULL)
return NULL;
return Py_BuildValue("O(NiO)", &islice_type, it, 1, Py_None);
}
return Py_BuildValue("O(OO)O", Py_TYPE(lz),
lz->it, lz->binop?lz->binop:Py_None,
lz->total?lz->total:Py_None);