Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
c39b0766
Commit
c39b0766
authored
Jun 23, 2015
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
adapt coroutine implementation to latest Py3.5
parent
72e7dda3
Changes
4
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
302 additions
and
42 deletions
+302
-42
Cython/Utility/Coroutine.c
Cython/Utility/Coroutine.c
+36
-26
runtests.py
runtests.py
+2
-0
tests/run/py35_pep492_interop.pyx
tests/run/py35_pep492_interop.pyx
+84
-0
tests/run/test_coroutines_pep492.pyx
tests/run/test_coroutines_pep492.pyx
+180
-16
No files found.
Cython/Utility/Coroutine.c
View file @
c39b0766
...
...
@@ -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
|=
Py
Gen_CheckCoroutine
Exact
(
res
);
#if
(CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500B2) || defined(PyCoro_CheckExact)
is_coroutine
|=
Py
Coro_Check
Exact
(
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,
\n
return next yielded value or raise StopIteration."
)},
{
"throw"
,
(
PyCFunction
)
__Pyx_CoroutineAwait_Throw
,
METH_VARARGS
,
(
char
*
)
PyDoc_STR
(
"throw(typ[,val[,tb]]) -> raise exception in coroutine,
\n
return 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,
\n
return next yielded value or raise StopIteration."
)},
{
"throw"
,
(
PyCFunction
)
__Pyx_Coroutine_Throw
,
METH_VARARGS
,
(
char
*
)
PyDoc_STR
(
"throw(typ[,val[,tb]]) -> raise exception in coroutine,
\n
return 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,
\n
return next yielded value or raise StopIteration."
)},
{
"throw"
,
(
PyCFunction
)
__Pyx_Coroutine_Throw
,
METH_VARARGS
,
(
char
*
)
PyDoc_STR
(
"throw(typ[,val[,tb]]) -> raise exception in generator,
\n
return 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
}
};
...
...
runtests.py
View file @
c39b0766
...
...
@@ -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 ]
...
...
tests/run/py35_pep492_interop.pyx
0 → 100644
View file @
c39b0766
# 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
tests/run/test_coroutines_pep492.pyx
View file @
c39b0766
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment