[pypy-commit] pypy py3.6: (vxgmichel, arigo)

arigo pypy.commits at gmail.com
Sun Jul 16 07:15:26 EDT 2017


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.6
Changeset: r91886:bc59a0b5e616
Date: 2017-07-16 13:14 +0200
http://bitbucket.org/pypy/pypy/changeset/bc59a0b5e616/

Log:	(vxgmichel, arigo)

	asend/send on async_generator objects

diff --git a/pypy/conftest.py b/pypy/conftest.py
--- a/pypy/conftest.py
+++ b/pypy/conftest.py
@@ -5,7 +5,7 @@
     # some tests fail otherwise
     sys.setrecursionlimit(2000)
 
-LOOK_FOR_PYTHON3 = 'python3.5'
+LOOK_FOR_PYTHON3 = 'python3.6'
 PYTHON3 = os.getenv('PYTHON3') or py.path.local.sysfind(LOOK_FOR_PYTHON3)
 if PYTHON3 is not None:
     PYTHON3 = str(PYTHON3)
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -593,16 +593,18 @@
         return self
 
     def descr__anext__(self):
-        return AsyncGenASend(self)
+        return AsyncGenASend(self, self.space.w_None)
 
     def descr_asend(self, w_arg):
-        XXX
-        return AsyncGenASend(w_arg)
+        return AsyncGenASend(self, w_arg)
 
     def descr_athrow(self, w_type, w_val=None, w_tb=None):
         XXX
         return AsyncGenAThrow(w_type, w_val, w_tb)
 
+    def descr_aclose(self):
+        XXX
+
 
 class AsyncGenValueWrapper(W_Root):
     def __init__(self, w_value):
@@ -610,9 +612,11 @@
 
 
 class AsyncGenASend(W_Root):
+    state = 0
 
-    def __init__(self, async_gen):
+    def __init__(self, async_gen, w_value_to_send):
         self.async_gen = async_gen
+        self.w_value_to_send = w_value_to_send
 
     def descr__iter__(self):
         return self
@@ -632,8 +636,29 @@
 
     def send_ex(self, w_arg_or_err):
         space = self.async_gen.space
-        w_value = self.async_gen.send_ex(w_arg_or_err)
-        if isinstance(w_value, AsyncGenValueWrapper):
-            raise OperationError(space.w_StopIteration, w_value.w_value)
-        else:
-            return w_value
+        if self.state == 2:
+            raise OperationError(space.w_StopIteration, space.w_None)
+
+        # We think that the code should look like this:
+        #if self.w_value_to_send is not None:
+        #    if not space.is_w(w_arg_or_err, space.w_None):
+        #        raise ...
+        #    w_arg_or_err = self.w_value_to_send
+        #    self.w_value_to_send = None
+
+        # But instead, CPython's logic is this, which we think is
+        # giving nonsense results for 'g.asend(42).send(43)':
+        if self.state == 0:
+            if space.is_w(w_arg_or_err, space.w_None):
+                w_arg_or_err = self.w_value_to_send
+            self.state = 1
+
+        try:
+            w_value = self.async_gen.send_ex(w_arg_or_err)
+            if isinstance(w_value, AsyncGenValueWrapper):
+                raise OperationError(space.w_StopIteration, w_value.w_value)
+            else:
+                return w_value
+        except OperationError as e:
+            self.state = 2
+            raise
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
@@ -276,3 +276,42 @@
         raises(Done, co.send, 93)
         assert result == [5, 6]
         """
+
+    def test_async_yield_with_explicit_send(self): """
+        class X:
+            def __await__(self):
+                i1 = yield 40
+                assert i1 == 82
+                i2 = yield 41
+                assert i2 == 93
+
+        async def mygen():
+            x = yield 5
+            assert x == 2189
+            await X()
+            y = yield 6
+            assert y == 319
+
+        result = []
+        async def foo():
+            gen = mygen()
+            result.append(await gen.asend(None))
+            result.append(await gen.asend(2189))
+            try:
+                await gen.asend(319)
+            except StopAsyncIteration:
+                return 42
+            else:
+                raise AssertionError
+
+        co = foo()
+        x = co.send(None)
+        assert x == 40
+        assert result == [5]
+        x = co.send(82)
+        assert x == 41
+        assert result == [5]
+        e = raises(StopIteration, co.send, 93)
+        assert e.value.args == (42,)
+        assert result == [5, 6]
+        """
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -857,11 +857,11 @@
     __repr__   = interp2app(AsyncGenerator.descr__repr__),
     #__reduce__   = interp2app(Coroutine.descr__reduce__),
     #__setstate__ = interp2app(Coroutine.descr__setstate__),
-    asend      = interp2app(AsyncGenerator.descr_send,
+    asend      = interp2app(AsyncGenerator.descr_asend,
                             descrmismatch='asend'),
-    athrow     = interp2app(AsyncGenerator.descr_throw,
+    athrow     = interp2app(AsyncGenerator.descr_athrow,
                             descrmismatch='athrow'),
-    aclose     = interp2app(AsyncGenerator.descr_close,
+    aclose     = interp2app(AsyncGenerator.descr_aclose,
                             descrmismatch='aclose'),
     __aiter__  = interp2app(AsyncGenerator.descr__aiter__,
                             descrmismatch='__aiter__'),


More information about the pypy-commit mailing list