diff -r eb251e3624df Doc/library/itertools.rst --- a/Doc/library/itertools.rst Fri Jan 24 00:33:25 2014 -0500 +++ b/Doc/library/itertools.rst Fri Jan 24 18:15:05 2014 +0800 @@ -525,13 +525,15 @@ .. function:: repeat(object[, times]) Make an iterator that returns *object* over and over again. Runs indefinitely - unless the *times* argument is specified. Used as argument to :func:`map` for - invariant parameters to the called function. Also used with :func:`zip` to - create an invariant part of a tuple record. Equivalent to:: + unless the *times* argument is specified. Negative *times* is same as 0. + Used as argument to :func:`map` for invariant parameters to the called + function. Also used with :func:`zip` to create an invariant part of a tuple + record. Equivalent to:: - def repeat(object, times=None): + sentinel = [] + def repeat(object, times=sentinel): # repeat(10, 3) --> 10 10 10 - if times is None: + if times is sentinel: while True: yield object else: diff -r eb251e3624df Lib/test/test_itertools.py --- a/Lib/test/test_itertools.py Fri Jan 24 00:33:25 2014 -0500 +++ b/Lib/test/test_itertools.py Fri Jan 24 18:15:05 2014 +0800 @@ -967,6 +967,12 @@ self.assertEqual(take(2, copy.deepcopy(c)), list('a' * 2)) self.pickletest(repeat(object='a', times=10)) + def test_repeat_with_negative_times(self): + self.assertEqual(repr(repeat('a', -1)), "repeat('a', 0)") + self.assertEqual(repr(repeat('a', -2)), "repeat('a', 0)") + self.assertEqual(repr(repeat('a', times=-1)), "repeat('a', 0)") + self.assertEqual(repr(repeat('a', times=-2)), "repeat('a', 0)") + def test_map(self): self.assertEqual(list(map(operator.pow, range(3), range(1,7))), [0**1, 1**2, 2**3]) @@ -1732,8 +1738,15 @@ def test_repeat(self): self.assertEqual(operator.length_hint(repeat(None, 50)), 50) + self.assertEqual(operator.length_hint(repeat(None, 0)), 0) self.assertEqual(operator.length_hint(repeat(None), 12), 12) + def test_repeat_with_negative_times(self): + self.assertEqual(operator.length_hint(repeat(None, -1)), 0) + self.assertEqual(operator.length_hint(repeat(None, -2)), 0) + self.assertEqual(operator.length_hint(repeat(None, times=-1)), 0) + self.assertEqual(operator.length_hint(repeat(None, times=-2)), 0) + class RegressionTests(unittest.TestCase): def test_sf_793826(self): diff -r eb251e3624df Modules/itertoolsmodule.c --- a/Modules/itertoolsmodule.c Fri Jan 24 00:33:25 2014 -0500 +++ b/Modules/itertoolsmodule.c Fri Jan 24 18:15:05 2014 +0800 @@ -4090,14 +4090,17 @@ { repeatobject *ro; PyObject *element; - Py_ssize_t cnt = -1; + Py_ssize_t cnt = -1, n_kwds = 0; static char *kwargs[] = {"object", "times", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:repeat", kwargs, &element, &cnt)) return NULL; - if (PyTuple_Size(args) == 2 && cnt < 0) + if (kwds != NULL) + n_kwds = PyDict_Size(kwds); + /* Does user supply times argument? */ + if ((PyTuple_Size(args) + n_kwds == 2) && cnt < 0) cnt = 0; ro = (repeatobject *)type->tp_alloc(type, 0); @@ -4177,7 +4180,7 @@ PyDoc_STRVAR(repeat_doc, "repeat(object [,times]) -> create an iterator which returns the object\n\ for the specified number of times. If not specified, returns the object\n\ -endlessly."); +endlessly. Negative times is same as zero."); static PyTypeObject repeat_type = { PyVarObject_HEAD_INIT(NULL, 0)