[pypy-commit] pypy stdlib-2.7.12: ensure reversed types always free their sequence when finished

pjenvey pypy.commits at gmail.com
Sun Oct 2 13:37:17 EDT 2016


Author: Philip Jenvey <pjenvey at underboss.org>
Branch: stdlib-2.7.12
Changeset: r87520:b6a910081211
Date: 2016-10-01 17:27 -0700
http://bitbucket.org/pypy/pypy/changeset/b6a910081211/

Log:	ensure reversed types always free their sequence when finished

diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py
--- a/pypy/module/__builtin__/functional.py
+++ b/pypy/module/__builtin__/functional.py
@@ -371,6 +371,7 @@
 
         # Done
         self.remaining = -1
+        self.w_sequence = None
         raise OperationError(space.w_StopIteration, space.w_None)
 
     def descr___reduce__(self, space):
diff --git a/pypy/objspace/std/iterobject.py b/pypy/objspace/std/iterobject.py
--- a/pypy/objspace/std/iterobject.py
+++ b/pypy/objspace/std/iterobject.py
@@ -147,17 +147,21 @@
         return self
 
     def descr_next(self, space):
-        if self.w_seq is None or self.index < 0:
-            raise OperationError(space.w_StopIteration, space.w_None)
-        try:
-            w_item = space.getitem(self.w_seq, space.wrap(self.index))
-            self.index -= 1
-        except OperationError as e:
-            self.w_seq = None
-            if not e.match(space, space.w_IndexError):
-                raise
-            raise OperationError(space.w_StopIteration, space.w_None)
-        return w_item
+        if self.index >= 0:
+            w_index = space.wrap(self.index)
+            try:
+                w_item = space.getitem(self.w_seq, w_index)
+            except OperationError as e:
+                if not e.match(space, space.w_IndexError):
+                    raise
+            else:
+                self.index -= 1
+                return w_item
+
+        # Done
+        self.index = -1
+        self.w_seq = None
+        raise OperationError(space.w_StopIteration, space.w_None)
 
 W_ReverseSeqIterObject.typedef = TypeDef(
     "reversesequenceiterator",
diff --git a/pypy/objspace/std/test/test_iterobject.py b/pypy/objspace/std/test/test_iterobject.py
--- a/pypy/objspace/std/test/test_iterobject.py
+++ b/pypy/objspace/std/test/test_iterobject.py
@@ -90,6 +90,18 @@
         raises(TypeError, len, reversed(iterable))
         del sys.modules['collections']
 
+    def test_reversed_frees_empty(self):
+        import gc
+        for typ in list, unicode:
+            free = [False]
+            class U(typ):
+                def __del__(self):
+                    free[0] = True
+            r = reversed(U())
+            raises(StopIteration, next, r)
+            gc.collect(); gc.collect(); gc.collect()
+            assert free[0]
+
     def test_no_len_on_set_iter(self):
         iterable = set([1,2,3,4])
         raises(TypeError, len, iter(iterable))


More information about the pypy-commit mailing list