diff -r 8d572bf526e6 Doc/library/itertools.rst --- a/Doc/library/itertools.rst Sun Jan 26 21:35:22 2014 -0500 +++ b/Doc/library/itertools.rst Mon Jan 27 15:31:38 2014 +0800 @@ -525,7 +525,8 @@ .. 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 + unless the *times* argument is specified and is not ``None``. Negative + *times* means zero repetitions. 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:: diff -r 8d572bf526e6 Lib/test/test_itertools.py --- a/Lib/test/test_itertools.py Sun Jan 26 21:35:22 2014 -0500 +++ b/Lib/test/test_itertools.py Mon Jan 27 15:31:38 2014 +0800 @@ -949,7 +949,11 @@ self.assertEqual(list(repeat('a', 3)), ['a', 'a', 'a']) self.assertEqual(take(3, repeat('a')), ['a', 'a', 'a']) self.assertEqual(list(repeat('a', 0)), []) + self.assertEqual(list(repeat('a', -1)), []) self.assertEqual(list(repeat('a', -3)), []) + self.assertEqual(list(repeat(object='a', times=0)), []) + self.assertEqual(list(repeat(object='a', times=-1)), []) + self.assertEqual(list(repeat(object='a', times=-3)), []) self.assertRaises(TypeError, repeat) self.assertRaises(TypeError, repeat, None, 3, 4) self.assertRaises(TypeError, repeat, None, 'a') @@ -960,6 +964,11 @@ list(r) self.assertEqual(repr(r), 'repeat((1+0j), 0)') + # None value for times represents endless repetitions + self.assertEqual(repr(repeat('a')), "repeat('a')") + self.assertEqual(repr(repeat('a', None)), "repeat('a')") + self.assertEqual(repr(repeat('a', times=None)), "repeat('a')") + # check copy, deepcopy, pickle c = repeat(object='a', times=10) self.assertEqual(next(c), 'a') diff -r 8d572bf526e6 Modules/itertoolsmodule.c --- a/Modules/itertoolsmodule.c Sun Jan 26 21:35:22 2014 -0500 +++ b/Modules/itertoolsmodule.c Mon Jan 27 15:31:38 2014 +0800 @@ -4090,15 +4090,27 @@ { repeatobject *ro; PyObject *element; + PyObject *count_object = Py_None; Py_ssize_t cnt = -1; static char *kwargs[] = {"object", "times", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:repeat", kwargs, - &element, &cnt)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:repeat", kwargs, + &element, &count_object)) return NULL; - if (PyTuple_Size(args) == 2 && cnt < 0) - cnt = 0; + if (count_object == Py_None) + cnt = -1; + else { + cnt = PyLong_AsSsize_t(count_object); + if ((cnt == -1) && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_TypeError)) + PyErr_SetString(PyExc_TypeError, + "times must be integer or None"); + return NULL; + } + if (cnt < 0) + cnt = 0; + } ro = (repeatobject *)type->tp_alloc(type, 0); if (ro == NULL) @@ -4175,9 +4187,9 @@ }; 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=None) -> create an iterator which returns the object\n\ +for the specified number of times. If times is not specified or None,\n\ +returns the object endlessly. Negative times means zero repetitions."); static PyTypeObject repeat_type = { PyVarObject_HEAD_INIT(NULL, 0)