//////////////////// GeneratorYieldFrom.proto ////////////////////
static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_CoroutineObject *gen, PyObject *source);
//////////////////// GeneratorYieldFrom ////////////////////
//@requires: Generator
static void __PyxPyIter_CheckErrorAndDecref(PyObject *source) {
PyErr_Format(PyExc_TypeError,
"iter() returned non-iterator of type '%.100s'",
Py_TYPE(source)->tp_name);
Py_DECREF(source);
}
static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_CoroutineObject *gen, PyObject *source) {
PyObject *source_gen, *retval;
#ifdef __Pyx_Coroutine_USED
if (__Pyx_Coroutine_Check(source)) {
// TODO: this should only happen for types.coroutine()ed generators, but we can't determine that here
Py_INCREF(source);
source_gen = source;
retval = __Pyx_Generator_Next(source);
} else
#endif
{
#if CYTHON_USE_TYPE_SLOTS
if (likely(Py_TYPE(source)->tp_iter)) {
source_gen = Py_TYPE(source)->tp_iter(source);
if (unlikely(!source_gen))
return NULL;
if (unlikely(!PyIter_Check(source_gen))) {
__PyxPyIter_CheckErrorAndDecref(source_gen);
return NULL;
}
} else
// CPython also allows non-iterable sequences to be iterated over
#endif
{
source_gen = PyObject_GetIter(source);
if (unlikely(!source_gen))
return NULL;
}
// source_gen is now the iterator, make the first next() call
#if CYTHON_USE_TYPE_SLOTS
retval = Py_TYPE(source_gen)->tp_iternext(source_gen);
#else
retval = PyIter_Next(source_gen);
#endif
}
if (likely(retval)) {
gen->yieldfrom = source_gen;
return retval;
}
Py_DECREF(source_gen);
return NULL;
}
//////////////////// CoroutineYieldFrom.proto ////////////////////
static CYTHON_INLINE PyObject* __Pyx_Coroutine_Yield_From(__pyx_CoroutineObject *gen, PyObject *source);
//////////////////// CoroutineYieldFrom ////////////////////
//@requires: Coroutine
//@requires: GetAwaitIter
static PyObject* __Pyx__Coroutine_Yield_From_Generic(__pyx_CoroutineObject *gen, PyObject *source) {
PyObject *retval;
PyObject *source_gen = __Pyx__Coroutine_GetAwaitableIter(source);
if (unlikely(!source_gen)) {
return NULL;
}
// source_gen is now the iterator, make the first next() call
if (__Pyx_Coroutine_Check(source_gen)) {
retval = __Pyx_Generator_Next(source_gen);
} else {
#if CYTHON_USE_TYPE_SLOTS
retval = Py_TYPE(source_gen)->tp_iternext(source_gen);
#else
retval = PyIter_Next(source_gen);
#endif
}
if (retval) {
gen->yieldfrom = source_gen;
return retval;
}
Py_DECREF(source_gen);
return NULL;
}
static CYTHON_INLINE PyObject* __Pyx_Coroutine_Yield_From(__pyx_CoroutineObject *gen, PyObject *source) {
PyObject *retval;
if (__Pyx_Coroutine_Check(source)) {
if (unlikely(((__pyx_CoroutineObject*)source)->yieldfrom)) {
PyErr_SetString(
PyExc_RuntimeError,
"coroutine is being awaited already");
return NULL;
}
retval = __Pyx_Generator_Next(source);
#ifdef __Pyx_AsyncGen_USED
// inlined "__pyx_PyAsyncGenASend" handling to avoid the series of generic calls
} else if (__pyx_PyAsyncGenASend_CheckExact(source)) {
retval = __Pyx_async_gen_asend_iternext(source);
#endif
} else {
return __Pyx__Coroutine_Yield_From_Generic(gen, source);
}
if (retval) {
Py_INCREF(source);
gen->yieldfrom = source;
}
return retval;
}
//////////////////// GetAwaitIter.proto ////////////////////
static CYTHON_INLINE PyObject *__Pyx_Coroutine_GetAwaitableIter(PyObject *o); /*proto*/
static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *o); /*proto*/
//////////////////// GetAwaitIter ////////////////////
//@requires: ObjectHandling.c::PyObjectGetAttrStr
//@requires: ObjectHandling.c::PyObjectCallNoArg
//@requires: ObjectHandling.c::PyObjectCallOneArg
static CYTHON_INLINE PyObject *__Pyx_Coroutine_GetAwaitableIter(PyObject *o) {
#ifdef __Pyx_Coroutine_USED
if (__Pyx_Coroutine_Check(o)) {
return __Pyx_NewRef(o);
}
#endif
return __Pyx__Coroutine_GetAwaitableIter(o);
}
static void __Pyx_Coroutine_AwaitableIterError(PyObject *source) {
#if PY_VERSION_HEX >= 0x030600B3 || defined(_PyErr_FormatFromCause)
_PyErr_FormatFromCause(
PyExc_TypeError,
"'async for' received an invalid object "
"from __anext__: %.100s",
Py_TYPE(source)->tp_name);
#elif PY_MAJOR_VERSION >= 3
PyObject *exc, *val, *val2, *tb;
assert(PyErr_Occurred());
PyErr_Fetch(&exc, &val, &tb);
PyErr_NormalizeException(&exc, &val, &tb);
if (tb != NULL) {
PyException_SetTraceback(val, tb);
Py_DECREF(tb);
}
Py_DECREF(exc);
assert(!PyErr_Occurred());
PyErr_Format(
PyExc_TypeError,
"'async for' received an invalid object "
"from __anext__: %.100s",
Py_TYPE(source)->tp_name);
PyErr_Fetch(&exc, &val2, &tb);
PyErr_NormalizeException(&exc, &val2, &tb);
Py_INCREF(val);
PyException_SetCause(val2, val);
PyException_SetContext(val2, val);
PyErr_Restore(exc, val2, tb);
#else
// since Py2 does not have exception chaining, it's better to avoid shadowing exceptions there
source++;
#endif
}
// adapted from genobject.c in Py3.5
static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *obj) {
PyObject *res;
#if CYTHON_USE_ASYNC_SLOTS
__Pyx_PyAsyncMethodsStruct* am = __Pyx_PyType_AsAsync(obj);
if (likely(am && am->am_await)) {
res = (*am->am_await)(obj);
} else
#endif
#if PY_VERSION_HEX >= 0x030500B2 || defined(PyCoro_CheckExact)
if (PyCoro_CheckExact(obj)) {
return __Pyx_NewRef(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
return __Pyx_NewRef(obj);
} else
#endif
{
PyObject *method = __Pyx_PyObject_GetAttrStr(obj, PYIDENT("__await__"));
if (unlikely(!method)) goto slot_error;
#if CYTHON_UNPACK_METHODS
if (likely(PyMethod_Check(method))) {
PyObject *self = PyMethod_GET_SELF(method);
if (likely(self)) {
PyObject *function = PyMethod_GET_FUNCTION(method);
res = __Pyx_PyObject_CallOneArg(function, self);
} else
res = __Pyx_PyObject_CallNoArg(method);
} else
#endif
res = __Pyx_PyObject_CallNoArg(method);
Py_DECREF(method);
}
if (unlikely(!res)) {
// surprisingly, CPython replaces the exception here...
__Pyx_Coroutine_AwaitableIterError(obj);
goto bad;
}
if (unlikely(!PyIter_Check(res))) {
PyErr_Format(PyExc_TypeError,
"__await__() returned non-iterator of type '%.100s'",
Py_TYPE(res)->tp_name);
Py_CLEAR(res);
} else {
int is_coroutine = 0;
#ifdef __Pyx_Coroutine_USED
is_coroutine |= __Pyx_Coroutine_Check(res);
#endif
#if PY_VERSION_HEX >= 0x030500B2 || defined(PyCoro_CheckExact)
is_coroutine |= PyCoro_CheckExact(res);
#endif
if (unlikely(is_coroutine)) {
/* __await__ must return an *iterator*, not
a coroutine or another awaitable (see PEP 492) */
PyErr_SetString(PyExc_TypeError,
"__await__() returned a coroutine");
Py_CLEAR(res);
}
}
return res;
slot_error:
PyErr_Format(Py