summaryrefslogtreecommitdiffstats
path: root/Modules/itertoolsmodule.c
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2014-04-29 10:13:46 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2014-04-29 10:13:46 (GMT)
commit26f82efe591a997bcf62111d1776c296f8088623 (patch)
tree61dc8b3bb00326ce373ec0edb5414b8a825edcf4 /Modules/itertoolsmodule.c
parent9cc9026294bfd2b65e5a66a455f4982e8b3dbce7 (diff)
downloadcpython-26f82efe591a997bcf62111d1776c296f8088623.zip
cpython-26f82efe591a997bcf62111d1776c296f8088623.tar.gz
cpython-26f82efe591a997bcf62111d1776c296f8088623.tar.bz2
Issue #21321: itertools.islice() now releases the reference to the source iterator when the slice is exhausted.
Patch by Anton Afanasyev.
Diffstat (limited to 'Modules/itertoolsmodule.c')
-rw-r--r--Modules/itertoolsmodule.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index db7cdfe..cec1f87 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -1492,19 +1492,22 @@ islice_next(isliceobject *lz)
Py_ssize_t oldnext;
PyObject *(*iternext)(PyObject *);
+ if (it == NULL)
+ return NULL;
+
iternext = *Py_TYPE(it)->tp_iternext;
while (lz->cnt < lz->next) {
item = iternext(it);
if (item == NULL)
- return NULL;
+ goto empty;
Py_DECREF(item);
lz->cnt++;
}
if (stop != -1 && lz->cnt >= stop)
- return NULL;
+ goto empty;
item = iternext(it);
if (item == NULL)
- return NULL;
+ goto empty;
lz->cnt++;
oldnext = lz->next;
/* The (size_t) cast below avoids the danger of undefined
@@ -1513,6 +1516,10 @@ islice_next(isliceobject *lz)
if (lz->next < oldnext || (stop != -1 && lz->next > stop))
lz->next = stop;
return item;
+
+empty:
+ Py_CLEAR(lz->it);
+ return NULL;
}
static PyObject *
@@ -1522,6 +1529,18 @@ islice_reduce(isliceobject *lz)
* then 'setstate' with the next and count
*/
PyObject *stop;
+ if (lz->it == NULL) {
+ PyObject *empty_list;
+ PyObject *empty_it;
+ empty_list = PyList_New(0);
+ if (empty_list == NULL)
+ return NULL;
+ empty_it = PyObject_GetIter(empty_list);
+ Py_DECREF(empty_list);
+ if (empty_it == NULL)
+ return NULL;
+ return Py_BuildValue("O(Nn)n", Py_TYPE(lz), empty_it, 0, 0);
+ }
if (lz->stop == -1) {
stop = Py_None;
Py_INCREF(stop);