diff -r b541ecd32115 Doc/library/itertools.rst --- a/Doc/library/itertools.rst Fri Feb 07 16:11:17 2014 -0800 +++ b/Doc/library/itertools.rst Sat Feb 08 18:09:48 2014 +0800 @@ -524,25 +524,34 @@ .. 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:: + Return an iterator which yields the object for the specified number of + times. If times is unspecified, yields the object forever. If times is + negative, behave as if times is 0. - def repeat(object, times=None): - # repeat(10, 3) --> 10 10 10 - if times is None: - while True: - yield object - else: - for i in range(times): - yield object + Equivalent to:: - A common use for *repeat* is to supply a stream of constant values to *map* - or *zip*:: + def repeat(object, times=None): + # repeat(10, 3) --> 10 10 10 + if times is None: + while True: + yield object + else: + for i in range(times): + yield object - >>> list(map(pow, range(10), repeat(2))) - [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] + A common use for repeat is to supply a stream of constant values to map or + zip: + + >>> list(map(pow, range(10), repeat(2))) + [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] + + .. note:: + + If "times" is specified using a keyword argument, and provided with a + negative value, repeat yields the object forever. This is a bug, its + use is unsupported, and this behavior may be removed in a future version + of Python. + .. function:: starmap(function, iterable) diff -r b541ecd32115 Lib/test/test_itertools.py --- a/Lib/test/test_itertools.py Fri Feb 07 16:11:17 2014 -0800 +++ b/Lib/test/test_itertools.py Sat Feb 08 18:09:48 2014 +0800 @@ -960,6 +960,10 @@ list(r) self.assertEqual(repr(r), 'repeat((1+0j), 0)') + # Test negative value times sent via keyword (issue #19145). + self.assertEqual(repr(repeat(1, times=-1)), 'repeat(1)') + self.assertEqual(repr(repeat(1, times=-2)), 'repeat(1, -2)') + # check copy, deepcopy, pickle c = repeat(object='a', times=10) self.assertEqual(next(c), 'a') diff -r b541ecd32115 Modules/itertoolsmodule.c --- a/Modules/itertoolsmodule.c Fri Feb 07 16:11:17 2014 -0800 +++ b/Modules/itertoolsmodule.c Sat Feb 08 18:09:48 2014 +0800 @@ -4097,6 +4097,10 @@ &element, &cnt)) return NULL; + /* There is a leak here. If negative value sent to times via keyword, the + * cnt will be negative. It should be 0. This bug is preserved because of + * backward compatibility concern (issue #19145). + */ if (PyTuple_Size(args) == 2 && cnt < 0) cnt = 0; @@ -4175,9 +4179,10 @@ }; 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."); +"repeat(object [,times]) -> iterator\n\n\ +Return an iterator which yields the object for the specified number of times.\n\ +If times is unspecified, yields the object forever. If times is negative,\n\ +behave as if times is 0."); static PyTypeObject repeat_type = { PyVarObject_HEAD_INIT(NULL, 0)