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