Commit c39b0766 authored by Stefan Behnel's avatar Stefan Behnel

adapt coroutine implementation to latest Py3.5

parent 72e7dda3
......@@ -86,7 +86,6 @@ static CYTHON_INLINE PyObject *__Pyx_Coroutine_GetAwaitableIter(PyObject *o); /*
static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *o); /*proto*/
//////////////////// GetAwaitIter ////////////////////
//@requires: Coroutine
//@requires: ObjectHandling.c::PyObjectGetAttrStr
//@requires: ObjectHandling.c::PyObjectCallNoArg
//@requires: ObjectHandling.c::PyObjectCallOneArg
......@@ -109,19 +108,21 @@ static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *obj) {
if (likely(am && am->am_await)) {
res = (*am->am_await)(obj);
} else
#endif
#if (CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500B2) || defined(PyCoro_CheckExact)
if (PyCoro_CheckExact(obj)) {
Py_INCREF(obj);
return obj;
} else
#endif
#if CYTHON_COMPILING_IN_CPYTHON && defined(CO_ITERABLE_COROUTINE)
if (PyGen_CheckExact(obj) && ((PyGenObject*)obj)->gi_code && ((PyCodeObject *)((PyGenObject*)obj)->gi_code)->co_flags & CO_ITERABLE_COROUTINE) {
// Python generator marked with "@types.coroutine" decorator
Py_INCREF(obj);
return obj;
} else
#endif
{
#if PY_VERSION_HEX >= 0x030500B1
#if CYTHON_COMPILING_IN_CPYTHON
if (PyGen_CheckCoroutineExact(obj)) {
// Python generator marked with "@types.coroutine" decorator
Py_INCREF(obj);
return obj;
}
#endif
// no slot => no method
goto slot_error;
#else
PyObject *method = __Pyx_PyObject_GetAttrStr(obj, PYIDENT("__await__"));
if (unlikely(!method)) goto slot_error;
#if CYTHON_COMPILING_IN_CPYTHON
......@@ -136,7 +137,6 @@ static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *obj) {
#endif
res = __Pyx_PyObject_CallNoArg(method);
Py_DECREF(method);
#endif
}
if (unlikely(!res)) goto bad;
if (!PyIter_Check(res)) {
......@@ -149,8 +149,8 @@ static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *obj) {
#ifdef __Pyx_Coroutine_USED
is_coroutine |= __Pyx_Coroutine_CheckExact(res);
#endif
#if PY_VERSION_HEX >= 0x030500B1
is_coroutine |= PyGen_CheckCoroutineExact(res);
#if (CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500B2) || defined(PyCoro_CheckExact)
is_coroutine |= PyCoro_CheckExact(res);
#endif
if (unlikely(is_coroutine)) {
/* __await__ must return an *iterator*, not
......@@ -1009,15 +1009,18 @@ static PyObject *__Pyx_CoroutineAwait_no_new(CYTHON_UNUSED PyTypeObject *type, C
}
static PyMethodDef __pyx_CoroutineAwait_methods[] = {
{"send", (PyCFunction) __Pyx_CoroutineAwait_Send, METH_O, 0},
{"throw", (PyCFunction) __Pyx_CoroutineAwait_Throw, METH_VARARGS, 0},
{"close", (PyCFunction) __Pyx_CoroutineAwait_Close, METH_NOARGS, 0},
{"send", (PyCFunction) __Pyx_CoroutineAwait_Send, METH_O,
(char*) PyDoc_STR("send(arg) -> send 'arg' into coroutine,\nreturn next yielded value or raise StopIteration.")},
{"throw", (PyCFunction) __Pyx_CoroutineAwait_Throw, METH_VARARGS,
(char*) PyDoc_STR("throw(typ[,val[,tb]]) -> raise exception in coroutine,\nreturn next yielded value or raise StopIteration.")},
{"close", (PyCFunction) __Pyx_CoroutineAwait_Close, METH_NOARGS,
(char*) PyDoc_STR("close() -> raise GeneratorExit inside coroutine.")},
{0, 0, 0, 0}
};
static PyTypeObject __pyx_CoroutineAwaitType_type = {
PyVarObject_HEAD_INIT(0, 0)
"coroutine_await", /*tp_name*/
"coroutine_wrapper", /*tp_name*/
sizeof(__pyx_CoroutineAwaitObject), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor) __Pyx_CoroutineAwait_dealloc,/*tp_dealloc*/
......@@ -1154,11 +1157,15 @@ static PyObject *__Pyx_Coroutine_compare(PyObject *obj, PyObject *other, int op)
#endif
static PyMethodDef __pyx_Coroutine_methods[] = {
{"send", (PyCFunction) __Pyx_Coroutine_Send, METH_O, 0},
{"throw", (PyCFunction) __Pyx_Coroutine_Throw, METH_VARARGS, 0},
{"close", (PyCFunction) __Pyx_Coroutine_Close, METH_NOARGS, 0},
{"send", (PyCFunction) __Pyx_Coroutine_Send, METH_O,
(char*) PyDoc_STR("send(arg) -> send 'arg' into coroutine,\nreturn next yielded value or raise StopIteration.")},
{"throw", (PyCFunction) __Pyx_Coroutine_Throw, METH_VARARGS,
(char*) PyDoc_STR("throw(typ[,val[,tb]]) -> raise exception in coroutine,\nreturn next yielded value or raise StopIteration.")},
{"close", (PyCFunction) __Pyx_Coroutine_Close, METH_NOARGS,
(char*) PyDoc_STR("close() -> raise GeneratorExit inside coroutine.")},
#if PY_VERSION_HEX < 0x030500B1
{"__await__", (PyCFunction) __Pyx_Coroutine_await, METH_NOARGS, 0},
{"__await__", (PyCFunction) __Pyx_Coroutine_await, METH_NOARGS,
(char*) PyDoc_STR("")},
#endif
{0, 0, 0, 0}
};
......@@ -1270,9 +1277,12 @@ static int __pyx_Coroutine_init(void) {
//@requires: PatchGeneratorABC
static PyMethodDef __pyx_Generator_methods[] = {
{"send", (PyCFunction) __Pyx_Coroutine_Send, METH_O, 0},
{"throw", (PyCFunction) __Pyx_Coroutine_Throw, METH_VARARGS, 0},
{"close", (PyCFunction) __Pyx_Coroutine_Close, METH_NOARGS, 0},
{"send", (PyCFunction) __Pyx_Coroutine_Send, METH_O,
(char*) PyDoc_STR("send(arg) -> send 'arg' into generator,\nreturn next yielded value or raise StopIteration.")},
{"throw", (PyCFunction) __Pyx_Coroutine_Throw, METH_VARARGS,
(char*) PyDoc_STR("throw(typ[,val[,tb]]) -> raise exception in generator,\nreturn next yielded value or raise StopIteration.")},
{"close", (PyCFunction) __Pyx_Coroutine_Close, METH_NOARGS,
(char*) PyDoc_STR("close() -> raise GeneratorExit inside generator.")},
{0, 0, 0, 0}
};
......
......@@ -333,6 +333,8 @@ VER_DEP_MODULES = {
]),
(3,4): (operator.lt, lambda x: x in ['run.py34_signature',
]),
(3,5): (operator.lt, lambda x: x in ['run.py35_pep492_interop',
]),
}
INCLUDE_DIRS = [ d for d in os.getenv('INCLUDE', '').split(os.pathsep) if d ]
......
# cython: language_level=3, binding=True
# mode: run
# tag: pep492, asyncfor, await
import types
def run_async(coro):
#assert coro.__class__ is types.GeneratorType
assert coro.__class__.__name__ in ('coroutine', 'GeneratorWrapper'), coro.__class__.__name__
buffer = []
result = None
while True:
try:
buffer.append(coro.send(None))
except StopIteration as ex:
result = ex.args[0] if ex.args else None
break
return buffer, result
def run_async__await__(coro):
assert coro.__class__.__name__ in ('coroutine', 'GeneratorWrapper'), coro.__class__.__name__
aw = coro.__await__()
buffer = []
result = None
i = 0
while True:
try:
if i % 2:
buffer.append(next(aw))
else:
buffer.append(aw.send(None))
i += 1
except StopIteration as ex:
result = ex.args[0] if ex.args else None
break
return buffer, result
async def await_pyobject(awaitable):
"""
>>> async def simple():
... return 10
>>> buffer, result = run_async(await_pyobject(simple()))
>>> result
10
>>> async def awaiting(awaitable):
... return await awaitable
>>> buffer, result = run_async(await_pyobject(awaiting(simple())))
>>> result
10
"""
return await awaitable
def await_cyobject():
"""
>>> async def run_await(awaitable):
... return await awaitable
>>> simple, awaiting = await_cyobject()
>>> buffer, result = run_async(run_await(simple()))
>>> result
10
>>> buffer, result = run_async(run_await(awaiting(simple())))
>>> result
10
"""
async def simple():
return 10
async def awaiting(awaitable):
return await awaitable
return simple, awaiting
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment