Author: Armin Rigo <ar...@tunes.org>
Branch: py3.5
Changeset: r90218:3910e862f7e9
Date: 2017-02-20 10:06 +0100
http://bitbucket.org/pypy/pypy/changeset/3910e862f7e9/

Log:    test and fix

diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -93,8 +93,7 @@
             if space.is_w(w_result, space.w_None):
                 raise OperationError(space.w_StopIteration, space.w_None)
             else:
-                raise OperationError(space.w_StopIteration,
-                        space.call_function(space.w_StopIteration, w_result))
+                raise stopiteration_value(space, w_result)
         else:
             return w_result     # YIELDed
 
@@ -442,7 +441,14 @@
         return self
 
     def descr__next__(self, space):
-        raise OperationError(space.w_StopIteration, self.w_aiter)
+        raise stopiteration_value(space, self.w_aiter)
+
+def stopiteration_value(space, w_value):
+    # Mess.  The obvious line, "OperationError(w_StopIteration, w_value)",
+    # fails for some types of w_value.  E.g. if it's a subclass of
+    # tuple, it will be unpacked as individual arguments.
+    raise OperationError(space.w_StopIteration,
+                         space.call_function(space.w_StopIteration, w_value))
 
 
 @specialize.memo()
diff --git a/pypy/interpreter/test/test_coroutine.py 
b/pypy/interpreter/test/test_coroutine.py
--- a/pypy/interpreter/test/test_coroutine.py
+++ b/pypy/interpreter/test/test_coroutine.py
@@ -177,3 +177,29 @@
         assert str(w).startswith("coroutine ")
         assert str(w).endswith("foobaz' was never awaited")
         """
+
+    def test_async_for_with_tuple_subclass(self): """
+        class Done(Exception): pass
+
+        class AIter(tuple):
+            i = 0
+            def __aiter__(self):
+                return self
+            async def __anext__(self):
+                if self.i >= len(self):
+                    raise StopAsyncIteration
+                self.i += 1
+                return self[self.i - 1]
+
+        result = []
+        async def foo():
+            async for i in AIter([42]):
+                result.append(i)
+            raise Done
+
+        try:
+            foo().send(None)
+        except Done:
+            pass
+        assert result == [42]
+        """
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to