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
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gwenaël Samain
cython
Commits
c39b0766
Commit
c39b0766
authored
9 years ago
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
}
};
...
...
This diff is collapsed.
Click to expand it.
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 ]
...
...
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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