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); /* ...@@ -86,7 +86,6 @@ static CYTHON_INLINE PyObject *__Pyx_Coroutine_GetAwaitableIter(PyObject *o); /*
static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *o); /*proto*/ static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *o); /*proto*/
//////////////////// GetAwaitIter //////////////////// //////////////////// GetAwaitIter ////////////////////
//@requires: Coroutine
//@requires: ObjectHandling.c::PyObjectGetAttrStr //@requires: ObjectHandling.c::PyObjectGetAttrStr
//@requires: ObjectHandling.c::PyObjectCallNoArg //@requires: ObjectHandling.c::PyObjectCallNoArg
//@requires: ObjectHandling.c::PyObjectCallOneArg //@requires: ObjectHandling.c::PyObjectCallOneArg
...@@ -109,19 +108,21 @@ static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *obj) { ...@@ -109,19 +108,21 @@ static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *obj) {
if (likely(am && am->am_await)) { if (likely(am && am->am_await)) {
res = (*am->am_await)(obj); res = (*am->am_await)(obj);
} else } 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 #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__")); PyObject *method = __Pyx_PyObject_GetAttrStr(obj, PYIDENT("__await__"));
if (unlikely(!method)) goto slot_error; if (unlikely(!method)) goto slot_error;
#if CYTHON_COMPILING_IN_CPYTHON #if CYTHON_COMPILING_IN_CPYTHON
...@@ -136,7 +137,6 @@ static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *obj) { ...@@ -136,7 +137,6 @@ static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *obj) {
#endif #endif
res = __Pyx_PyObject_CallNoArg(method); res = __Pyx_PyObject_CallNoArg(method);
Py_DECREF(method); Py_DECREF(method);
#endif
} }
if (unlikely(!res)) goto bad; if (unlikely(!res)) goto bad;
if (!PyIter_Check(res)) { if (!PyIter_Check(res)) {
...@@ -149,8 +149,8 @@ static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *obj) { ...@@ -149,8 +149,8 @@ static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *obj) {
#ifdef __Pyx_Coroutine_USED #ifdef __Pyx_Coroutine_USED
is_coroutine |= __Pyx_Coroutine_CheckExact(res); is_coroutine |= __Pyx_Coroutine_CheckExact(res);
#endif #endif
#if PY_VERSION_HEX >= 0x030500B1 #if (CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500B2) || defined(PyCoro_CheckExact)
is_coroutine |= PyGen_CheckCoroutineExact(res); is_coroutine |= PyCoro_CheckExact(res);
#endif #endif
if (unlikely(is_coroutine)) { if (unlikely(is_coroutine)) {
/* __await__ must return an *iterator*, not /* __await__ must return an *iterator*, not
...@@ -1009,15 +1009,18 @@ static PyObject *__Pyx_CoroutineAwait_no_new(CYTHON_UNUSED PyTypeObject *type, C ...@@ -1009,15 +1009,18 @@ static PyObject *__Pyx_CoroutineAwait_no_new(CYTHON_UNUSED PyTypeObject *type, C
} }
static PyMethodDef __pyx_CoroutineAwait_methods[] = { static PyMethodDef __pyx_CoroutineAwait_methods[] = {
{"send", (PyCFunction) __Pyx_CoroutineAwait_Send, METH_O, 0}, {"send", (PyCFunction) __Pyx_CoroutineAwait_Send, METH_O,
{"throw", (PyCFunction) __Pyx_CoroutineAwait_Throw, METH_VARARGS, 0}, (char*) PyDoc_STR("send(arg) -> send 'arg' into coroutine,\nreturn next yielded value or raise StopIteration.")},
{"close", (PyCFunction) __Pyx_CoroutineAwait_Close, METH_NOARGS, 0}, {"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} {0, 0, 0, 0}
}; };
static PyTypeObject __pyx_CoroutineAwaitType_type = { static PyTypeObject __pyx_CoroutineAwaitType_type = {
PyVarObject_HEAD_INIT(0, 0) PyVarObject_HEAD_INIT(0, 0)
"coroutine_await", /*tp_name*/ "coroutine_wrapper", /*tp_name*/
sizeof(__pyx_CoroutineAwaitObject), /*tp_basicsize*/ sizeof(__pyx_CoroutineAwaitObject), /*tp_basicsize*/
0, /*tp_itemsize*/ 0, /*tp_itemsize*/
(destructor) __Pyx_CoroutineAwait_dealloc,/*tp_dealloc*/ (destructor) __Pyx_CoroutineAwait_dealloc,/*tp_dealloc*/
...@@ -1154,11 +1157,15 @@ static PyObject *__Pyx_Coroutine_compare(PyObject *obj, PyObject *other, int op) ...@@ -1154,11 +1157,15 @@ static PyObject *__Pyx_Coroutine_compare(PyObject *obj, PyObject *other, int op)
#endif #endif
static PyMethodDef __pyx_Coroutine_methods[] = { static PyMethodDef __pyx_Coroutine_methods[] = {
{"send", (PyCFunction) __Pyx_Coroutine_Send, METH_O, 0}, {"send", (PyCFunction) __Pyx_Coroutine_Send, METH_O,
{"throw", (PyCFunction) __Pyx_Coroutine_Throw, METH_VARARGS, 0}, (char*) PyDoc_STR("send(arg) -> send 'arg' into coroutine,\nreturn next yielded value or raise StopIteration.")},
{"close", (PyCFunction) __Pyx_Coroutine_Close, METH_NOARGS, 0}, {"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 #if PY_VERSION_HEX < 0x030500B1
{"__await__", (PyCFunction) __Pyx_Coroutine_await, METH_NOARGS, 0}, {"__await__", (PyCFunction) __Pyx_Coroutine_await, METH_NOARGS,
(char*) PyDoc_STR("")},
#endif #endif
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
...@@ -1270,9 +1277,12 @@ static int __pyx_Coroutine_init(void) { ...@@ -1270,9 +1277,12 @@ static int __pyx_Coroutine_init(void) {
//@requires: PatchGeneratorABC //@requires: PatchGeneratorABC
static PyMethodDef __pyx_Generator_methods[] = { static PyMethodDef __pyx_Generator_methods[] = {
{"send", (PyCFunction) __Pyx_Coroutine_Send, METH_O, 0}, {"send", (PyCFunction) __Pyx_Coroutine_Send, METH_O,
{"throw", (PyCFunction) __Pyx_Coroutine_Throw, METH_VARARGS, 0}, (char*) PyDoc_STR("send(arg) -> send 'arg' into generator,\nreturn next yielded value or raise StopIteration.")},
{"close", (PyCFunction) __Pyx_Coroutine_Close, METH_NOARGS, 0}, {"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} {0, 0, 0, 0}
}; };
......
...@@ -333,6 +333,8 @@ VER_DEP_MODULES = { ...@@ -333,6 +333,8 @@ VER_DEP_MODULES = {
]), ]),
(3,4): (operator.lt, lambda x: x in ['run.py34_signature', (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 ] 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