Author: Brian Kearns <bdkea...@gmail.com>
Branch: stdlib-2.7.8
Changeset: r73022:5a56be10c6e7
Date: 2014-08-24 10:55 -0400
http://bitbucket.org/pypy/pypy/changeset/5a56be10c6e7/

Log:    have islice release reference to source iterator when exhausted

diff --git a/pypy/module/itertools/interp_itertools.py 
b/pypy/module/itertools/interp_itertools.py
--- a/pypy/module/itertools/interp_itertools.py
+++ b/pypy/module/itertools/interp_itertools.py
@@ -391,16 +391,31 @@
                                 # has no effect any more
                 if stop > 0:
                     self._ignore_items(stop)
+                self.iterable = None
                 raise OperationError(self.space.w_StopIteration,
                                      self.space.w_None)
             self.stop = stop - (ignore + 1)
         if ignore > 0:
             self._ignore_items(ignore)
-        return self.space.next(self.iterable)
+        if self.iterable is None:
+            raise OperationError(self.space.w_StopIteration, self.space.w_None)
+        try:
+            return self.space.next(self.iterable)
+        except OperationError as e:
+            if e.match(self.space, self.space.w_StopIteration):
+                self.iterable = None
+            raise
 
     def _ignore_items(self, num):
+        if self.iterable is None:
+            raise OperationError(self.space.w_StopIteration, self.space.w_None)
         while True:
-            self.space.next(self.iterable)
+            try:
+                self.space.next(self.iterable)
+            except OperationError as e:
+                if e.match(self.space, self.space.w_StopIteration):
+                    self.iterable = None
+                raise
             num -= 1
             if num <= 0:
                 break
diff --git a/pypy/module/itertools/test/test_itertools.py 
b/pypy/module/itertools/test/test_itertools.py
--- a/pypy/module/itertools/test/test_itertools.py
+++ b/pypy/module/itertools/test/test_itertools.py
@@ -237,6 +237,18 @@
         assert list(itertools.islice(xrange(10), None,None)) == range(10)
         assert list(itertools.islice(xrange(10), None,None,None)) == range(10)
 
+        # check source iterator is not referenced from islice()
+        # after the latter has been exhausted
+        import weakref
+        for args in [(1,), (None,), (0, None, 2)]:
+            it = (x for x in (1, 2, 3))
+            wr = weakref.ref(it)
+            it = itertools.islice(it, *args)
+            assert wr() is not None
+            list(it)  # exhaust the iterator
+            assert wr() is None
+            raises(StopIteration, next, it)
+
     def test_islice_dropitems_exact(self):
         import itertools
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to