diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py index dbc941fd77e..2ba1e8ee414 100644 --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -5,6 +5,8 @@ from weakref import proxy import sys import operator import random +import copy +import pickle maxsize = test_support.MAX_Py_ssize_t minsize = -maxsize-1 @@ -215,6 +217,13 @@ class TestBasicOps(unittest.TestCase): r2 = 'count(%r)'.__mod__(i).replace('L', '') self.assertEqual(r1, r2) + # check copy, deepcopy, pickle + for value in -3, 3, sys.maxint-5, sys.maxint+5: + c = count(value) + self.assertEqual(next(copy.copy(c)), value) + self.assertEqual(next(copy.deepcopy(c)), value) + self.assertEqual(next(pickle.loads(pickle.dumps(c))), value) + def test_cycle(self): self.assertEqual(take(10, cycle('abc')), list('abcabcabca')) self.assertEqual(list(cycle('')), []) diff --git a/Misc/NEWS b/Misc/NEWS index ca36adcdb79..8df76747e87 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -33,6 +33,8 @@ Core and Builtins Library ------- +- Issue #7410: deepcopy of itertools.count() erroneously reset the count. + - Issue #7403: logging: Fixed possible race condition in lock creation. - Issue #7341: Close the internal file object in the TarFile constructor in diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index dc8a92acfd4..046548df2c7 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -2906,6 +2906,21 @@ count_repr(countobject *lz) return result; } +static PyObject * +count_reduce(countobject *lz) +{ + if (lz->cnt == PY_SSIZE_T_MAX) + return Py_BuildValue("O(O)", Py_TYPE(lz), lz->long_cnt); + return Py_BuildValue("O(n)", Py_TYPE(lz), lz->cnt); +} + +PyDoc_STRVAR(count_reduce_doc, "Return state information for pickling."); + +static PyMethodDef count_methods[] = { + {"__reduce__", (PyCFunction)count_reduce, METH_NOARGS, + count_reduce_doc}, +}; + PyDoc_STRVAR(count_doc, "count([firstval]) --> count object\n\ \n\ @@ -2941,7 +2956,7 @@ static PyTypeObject count_type = { 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)count_next, /* tp_iternext */ - 0, /* tp_methods */ + count_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */