Author: Ronan Lamy <[email protected]>
Branch: py3.5
Changeset: r92428:1184b9d1641d
Date: 2017-09-21 04:39 +0100
http://bitbucket.org/pypy/pypy/changeset/1184b9d1641d/

Log:    Add async slot functions

diff --git a/pypy/module/cpyext/test/test_eval.py 
b/pypy/module/cpyext/test/test_eval.py
--- a/pypy/module/cpyext/test/test_eval.py
+++ b/pypy/module/cpyext/test/test_eval.py
@@ -373,6 +373,7 @@
         assert 'while calling recurse' in str(excinfo.value)
 
     def test_build_class(self):
+            """
             # make sure PyObject_Call generates a proper PyTypeObject,
             # along the way verify that userslot has iter and next
             module = self.import_extension('foo', [
@@ -397,7 +398,35 @@
                         return NULL;
                     }
                     return args->ob_type->tp_iternext(args);
-                 '''),])
+                 '''),
+                ('await_', "METH_O",
+                 '''
+                    if (NULL == args->ob_type->tp_as_async->am_await)
+                    {
+                        PyErr_SetString(PyExc_TypeError, "NULL am_await");
+                        return NULL;
+                    }
+                    return args->ob_type->tp_as_async->am_await(args);
+                 '''),
+                ('aiter', "METH_O",
+                 '''
+                    if (NULL == args->ob_type->tp_as_async->am_aiter)
+                    {
+                        PyErr_SetString(PyExc_TypeError, "NULL am_aiter");
+                        return NULL;
+                    }
+                    return args->ob_type->tp_as_async->am_aiter(args);
+                 '''),
+                ('anext', "METH_O",
+                 '''
+                    if (NULL == args->ob_type->tp_as_async->am_anext)
+                    {
+                        PyErr_SetString(PyExc_TypeError, "NULL am_anext");
+                        return NULL;
+                    }
+                    return args->ob_type->tp_as_async->am_anext(args);
+                 '''),
+            ])
             def __init__(self, N):
                 self.N = N
                 self.i = 0
@@ -424,3 +453,59 @@
             except StopIteration:
                 pass
             assert out == [0, 1, 2, 3, 4]
+
+            def run_async(coro):
+                buffer = []
+                result = None
+                while True:
+                    try:
+                        buffer.append(coro.send(None))
+                    except StopIteration as ex:
+                        result = ex.value
+                        break
+                return buffer, result
+
+            def __await__(self):
+                yield 42
+                return 100
+
+            Awaitable = module.object_call((
+                'Awaitable', (object,), {'__await__': __await__}))
+
+            async def wrapper():
+                return await Awaitable()
+
+            assert run_async(module.await_(Awaitable())) == ([42], 100)
+            assert run_async(wrapper()) == ([42], 100)
+
+            def __aiter__(self):
+                return self
+
+            async def __anext__(self):
+                if self.i < self.N:
+                    res = self.i
+                    self.i += 1
+                    return res
+                raise StopAsyncIteration
+
+            AIter = module.object_call(('AIter', (object,),
+                {'__init__': __init__, '__aiter__': __aiter__,
+                 '__anext__': __anext__}))
+
+            async def list1():
+                s = []
+                async for i in AIter(3):
+                    s.append(i)
+                return s
+            async def list2():
+                s = []
+                ait = module.aiter(AIter(3))
+                try:
+                    while True:
+                        s.append(await module.anext(ait))
+                except StopAsyncIteration:
+                    return s
+
+            assert run_async(list1()) == ([], [0, 1, 2])
+            assert run_async(list2()) == ([], [0, 1, 2])
+            """
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -643,6 +643,7 @@
     pto.c_ob_pypy_link = 0
     pto.c_ob_type = metatype
     pto.c_tp_flags |= Py_TPFLAGS_HEAPTYPE
+    pto.c_tp_as_async = heaptype.c_as_async
     pto.c_tp_as_number = heaptype.c_as_number
     pto.c_tp_as_sequence = heaptype.c_as_sequence
     pto.c_tp_as_mapping = heaptype.c_as_mapping
diff --git a/pypy/module/cpyext/userslot.py b/pypy/module/cpyext/userslot.py
--- a/pypy/module/cpyext/userslot.py
+++ b/pypy/module/cpyext/userslot.py
@@ -130,3 +130,27 @@
 @slot_function([PyObject], PyObject)
 def slot_tp_iternext(space, w_self):
     return space.next(w_self)
+
+@slot_function([PyObject], PyObject)
+def slot_am_await(space, w_self):
+    w_await = space.lookup(w_self, "__await__")
+    if w_await is None:
+        raise oefmt(space.w_TypeError,
+            "object %T does not have __await__ method", w_self)
+    return space.get_and_call_function(w_await, w_self)
+
+@slot_function([PyObject], PyObject)
+def slot_am_aiter(space, w_self):
+    w_aiter = space.lookup(w_self, "__aiter__")
+    if w_aiter is None:
+        raise oefmt(space.w_TypeError,
+            "object %T does not have __aiter__ method", w_self)
+    return space.get_and_call_function(w_aiter, w_self)
+
+@slot_function([PyObject], PyObject)
+def slot_am_anext(space, w_self):
+    w_anext = space.lookup(w_self, "__anext__")
+    if w_anext is None:
+        raise oefmt(space.w_TypeError,
+            "object %T does not have __anext__ method", w_self)
+    return space.get_and_call_function(w_anext, w_self)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to