2624 lines
96 KiB
C
2624 lines
96 KiB
C
//////////////////// GeneratorYieldFrom.proto ////////////////////
|
|
|
|
static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_CoroutineObject *gen, PyObject *source);
|
|
|
|
//////////////////// GeneratorYieldFrom ////////////////////
|
|
//@requires: Generator
|
|
|
|
#if CYTHON_USE_TYPE_SLOTS
|
|
static void __Pyx_PyIter_CheckErrorAndDecref(PyObject *source) {
|
|
__Pyx_TypeName source_type_name = __Pyx_PyType_GetName(Py_TYPE(source));
|
|
PyErr_Format(PyExc_TypeError,
|
|
"iter() returned non-iterator of type '" __Pyx_FMT_TYPENAME "'", source_type_name);
|
|
__Pyx_DECREF_TypeName(source_type_name);
|
|
Py_DECREF(source);
|
|
}
|
|
#endif
|
|
|
|
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))) {
|
|
__Pyx_PyIter_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
|
|
retval = __Pyx_PyObject_GetIterNextFunc(source_gen)(source_gen);
|
|
}
|
|
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 {
|
|
retval = __Pyx_PyObject_GetIterNextFunc(source_gen)(source_gen);
|
|
}
|
|
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::PyObjectGetMethod
|
|
//@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 && PY_VERSION_HEX < 0x030d0000 || defined(_PyErr_FormatFromCause)
|
|
__Pyx_TypeName source_type_name = __Pyx_PyType_GetName(Py_TYPE(source));
|
|
_PyErr_FormatFromCause(PyExc_TypeError,
|
|
"'async for' received an invalid object from __anext__: " __Pyx_FMT_TYPENAME, source_type_name);
|
|
__Pyx_DECREF_TypeName(source_type_name);
|
|
#elif PY_MAJOR_VERSION >= 3
|
|
PyObject *exc, *val, *val2, *tb;
|
|
__Pyx_TypeName source_type_name = __Pyx_PyType_GetName(Py_TYPE(source));
|
|
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__: " __Pyx_FMT_TYPENAME, source_type_name);
|
|
__Pyx_DECREF_TypeName(source_type_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
|
|
CYTHON_UNUSED_VAR(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 PY_VERSION_HEX >= 0x030C00A6
|
|
if (PyGen_CheckExact(obj) && (PyGen_GetCode((PyGenObject*)obj)->co_flags & CO_ITERABLE_COROUTINE)) {
|
|
#else
|
|
if (PyGen_CheckExact(obj) && ((PyGenObject*)obj)->gi_code && ((PyCodeObject *)((PyGenObject*)obj)->gi_code)->co_flags & CO_ITERABLE_COROUTINE) {
|
|
#endif
|
|
// Python generator marked with "@types.coroutine" decorator
|
|
return __Pyx_NewRef(obj);
|
|
} else
|
|
#endif
|
|
{
|
|
PyObject *method = NULL;
|
|
int is_method = __Pyx_PyObject_GetMethod(obj, PYIDENT("__await__"), &method);
|
|
if (likely(is_method)) {
|
|
res = __Pyx_PyObject_CallOneArg(method, obj);
|
|
} else if (likely(method)) {
|
|
res = __Pyx_PyObject_CallNoArg(method);
|
|
} else
|
|
goto slot_error;
|
|
Py_DECREF(method);
|
|
}
|
|
if (unlikely(!res)) {
|
|
// surprisingly, CPython replaces the exception here...
|
|
__Pyx_Coroutine_AwaitableIterError(obj);
|
|
goto bad;
|
|
}
|
|
if (unlikely(!PyIter_Check(res))) {
|
|
__Pyx_TypeName res_type_name = __Pyx_PyType_GetName(Py_TYPE(res));
|
|
PyErr_Format(PyExc_TypeError,
|
|
"__await__() returned non-iterator of type '" __Pyx_FMT_TYPENAME "'", res_type_name);
|
|
__Pyx_DECREF_TypeName(res_type_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:
|
|
{
|
|
__Pyx_TypeName obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj));
|
|
PyErr_Format(PyExc_TypeError,
|
|
"object " __Pyx_FMT_TYPENAME " can't be used in 'await' expression", obj_type_name);
|
|
__Pyx_DECREF_TypeName(obj_type_name);
|
|
}
|
|
bad:
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//////////////////// AsyncIter.proto ////////////////////
|
|
|
|
static CYTHON_INLINE PyObject *__Pyx_Coroutine_GetAsyncIter(PyObject *o); /*proto*/
|
|
static CYTHON_INLINE PyObject *__Pyx_Coroutine_AsyncIterNext(PyObject *o); /*proto*/
|
|
|
|
//////////////////// AsyncIter ////////////////////
|
|
//@requires: GetAwaitIter
|
|
//@requires: ObjectHandling.c::PyObjectCallMethod0
|
|
|
|
static PyObject *__Pyx_Coroutine_GetAsyncIter_Generic(PyObject *obj) {
|
|
__Pyx_TypeName obj_type_name;
|
|
#if PY_VERSION_HEX < 0x030500B1
|
|
{
|
|
PyObject *iter = __Pyx_PyObject_CallMethod0(obj, PYIDENT("__aiter__"));
|
|
if (likely(iter))
|
|
return iter;
|
|
// FIXME: for the sake of a nicely conforming exception message, assume any AttributeError meant '__aiter__'
|
|
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
|
|
return NULL;
|
|
}
|
|
#else
|
|
// avoid C warning about 'unused function'
|
|
(void)&__Pyx_PyObject_CallMethod0;
|
|
#endif
|
|
|
|
obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj));
|
|
PyErr_Format(PyExc_TypeError,
|
|
"'async for' requires an object with __aiter__ method, got " __Pyx_FMT_TYPENAME, obj_type_name);
|
|
__Pyx_DECREF_TypeName(obj_type_name);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
static CYTHON_INLINE PyObject *__Pyx_Coroutine_GetAsyncIter(PyObject *obj) {
|
|
#ifdef __Pyx_AsyncGen_USED
|
|
if (__Pyx_AsyncGen_CheckExact(obj)) {
|
|
return __Pyx_NewRef(obj);
|
|
}
|
|
#endif
|
|
#if CYTHON_USE_ASYNC_SLOTS
|
|
{
|
|
__Pyx_PyAsyncMethodsStruct* am = __Pyx_PyType_AsAsync(obj);
|
|
if (likely(am && am->am_aiter)) {
|
|
return (*am->am_aiter)(obj);
|
|
}
|
|
}
|
|
#endif
|
|
return __Pyx_Coroutine_GetAsyncIter_Generic(obj);
|
|
}
|
|
|
|
|
|
static PyObject *__Pyx__Coroutine_AsyncIterNext(PyObject *obj) {
|
|
#if PY_VERSION_HEX < 0x030500B1
|
|
{
|
|
PyObject *value = __Pyx_PyObject_CallMethod0(obj, PYIDENT("__anext__"));
|
|
if (likely(value))
|
|
return value;
|
|
}
|
|
// FIXME: for the sake of a nicely conforming exception message, assume any AttributeError meant '__anext__'
|
|
if (PyErr_ExceptionMatches(PyExc_AttributeError))
|
|
#endif
|
|
{
|
|
__Pyx_TypeName obj_type_name = __Pyx_PyType_GetName(Py_TYPE(obj));
|
|
PyErr_Format(PyExc_TypeError,
|
|
"'async for' requires an object with __anext__ method, got " __Pyx_FMT_TYPENAME, obj_type_name);
|
|
__Pyx_DECREF_TypeName(obj_type_name);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
static CYTHON_INLINE PyObject *__Pyx_Coroutine_AsyncIterNext(PyObject *obj) {
|
|
#ifdef __Pyx_AsyncGen_USED
|
|
if (__Pyx_AsyncGen_CheckExact(obj)) {
|
|
return __Pyx_async_gen_anext(obj);
|
|
}
|
|
#endif
|
|
#if CYTHON_USE_ASYNC_SLOTS
|
|
{
|
|
__Pyx_PyAsyncMethodsStruct* am = __Pyx_PyType_AsAsync(obj);
|
|
if (likely(am && am->am_anext)) {
|
|
return (*am->am_anext)(obj);
|
|
}
|
|
}
|
|
#endif
|
|
return __Pyx__Coroutine_AsyncIterNext(obj);
|
|
}
|
|
|
|
|
|
//////////////////// pep479.proto ////////////////////
|
|
|
|
static void __Pyx_Generator_Replace_StopIteration(int in_async_gen); /*proto*/
|
|
|
|
//////////////////// pep479 ////////////////////
|
|
//@requires: Exceptions.c::GetException
|
|
|
|
static void __Pyx_Generator_Replace_StopIteration(int in_async_gen) {
|
|
PyObject *exc, *val, *tb, *cur_exc;
|
|
__Pyx_PyThreadState_declare
|
|
#ifdef __Pyx_StopAsyncIteration_USED
|
|
int is_async_stopiteration = 0;
|
|
#endif
|
|
CYTHON_MAYBE_UNUSED_VAR(in_async_gen);
|
|
|
|
cur_exc = PyErr_Occurred();
|
|
if (likely(!__Pyx_PyErr_GivenExceptionMatches(cur_exc, PyExc_StopIteration))) {
|
|
#ifdef __Pyx_StopAsyncIteration_USED
|
|
if (in_async_gen && unlikely(__Pyx_PyErr_GivenExceptionMatches(cur_exc, __Pyx_PyExc_StopAsyncIteration))) {
|
|
is_async_stopiteration = 1;
|
|
} else
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
__Pyx_PyThreadState_assign
|
|
// Chain exceptions by moving Stop(Async)Iteration to exc_info before creating the RuntimeError.
|
|
// In Py2.x, no chaining happens, but the exception still stays visible in exc_info.
|
|
__Pyx_GetException(&exc, &val, &tb);
|
|
Py_XDECREF(exc);
|
|
Py_XDECREF(val);
|
|
Py_XDECREF(tb);
|
|
PyErr_SetString(PyExc_RuntimeError,
|
|
#ifdef __Pyx_StopAsyncIteration_USED
|
|
is_async_stopiteration ? "async generator raised StopAsyncIteration" :
|
|
in_async_gen ? "async generator raised StopIteration" :
|
|
#endif
|
|
"generator raised StopIteration");
|
|
}
|
|
|
|
|
|
//////////////////// CoroutineBase.proto ////////////////////
|
|
//@substitute: naming
|
|
|
|
struct __pyx_CoroutineObject;
|
|
typedef PyObject *(*__pyx_coroutine_body_t)(struct __pyx_CoroutineObject *, PyThreadState *, PyObject *);
|
|
|
|
#if CYTHON_USE_EXC_INFO_STACK
|
|
// See https://bugs.python.org/issue25612
|
|
#define __Pyx_ExcInfoStruct _PyErr_StackItem
|
|
#else
|
|
// Minimal replacement struct for Py<3.7, without the Py3.7 exception state stack.
|
|
typedef struct {
|
|
PyObject *exc_type;
|
|
PyObject *exc_value;
|
|
PyObject *exc_traceback;
|
|
} __Pyx_ExcInfoStruct;
|
|
#endif
|
|
|
|
typedef struct __pyx_CoroutineObject {
|
|
PyObject_HEAD
|
|
__pyx_coroutine_body_t body;
|
|
PyObject *closure;
|
|
__Pyx_ExcInfoStruct gi_exc_state;
|
|
PyObject *gi_weakreflist;
|
|
PyObject *classobj;
|
|
PyObject *yieldfrom;
|
|
PyObject *gi_name;
|
|
PyObject *gi_qualname;
|
|
PyObject *gi_modulename;
|
|
PyObject *gi_code;
|
|
PyObject *gi_frame;
|
|
int resume_label;
|
|
// using T_BOOL for property below requires char value
|
|
char is_running;
|
|
} __pyx_CoroutineObject;
|
|
|
|
static __pyx_CoroutineObject *__Pyx__Coroutine_New(
|
|
PyTypeObject *type, __pyx_coroutine_body_t body, PyObject *code, PyObject *closure,
|
|
PyObject *name, PyObject *qualname, PyObject *module_name); /*proto*/
|
|
|
|
static __pyx_CoroutineObject *__Pyx__Coroutine_NewInit(
|
|
__pyx_CoroutineObject *gen, __pyx_coroutine_body_t body, PyObject *code, PyObject *closure,
|
|
PyObject *name, PyObject *qualname, PyObject *module_name); /*proto*/
|
|
|
|
static CYTHON_INLINE void __Pyx_Coroutine_ExceptionClear(__Pyx_ExcInfoStruct *self);
|
|
static int __Pyx_Coroutine_clear(PyObject *self); /*proto*/
|
|
static PyObject *__Pyx_Coroutine_Send(PyObject *self, PyObject *value); /*proto*/
|
|
static PyObject *__Pyx_Coroutine_Close(PyObject *self); /*proto*/
|
|
static PyObject *__Pyx_Coroutine_Throw(PyObject *gen, PyObject *args); /*proto*/
|
|
|
|
// macros for exception state swapping instead of inline functions to make use of the local thread state context
|
|
#if CYTHON_USE_EXC_INFO_STACK
|
|
#define __Pyx_Coroutine_SwapException(self)
|
|
#define __Pyx_Coroutine_ResetAndClearException(self) __Pyx_Coroutine_ExceptionClear(&(self)->gi_exc_state)
|
|
#else
|
|
#define __Pyx_Coroutine_SwapException(self) { \
|
|
__Pyx_ExceptionSwap(&(self)->gi_exc_state.exc_type, &(self)->gi_exc_state.exc_value, &(self)->gi_exc_state.exc_traceback); \
|
|
__Pyx_Coroutine_ResetFrameBackpointer(&(self)->gi_exc_state); \
|
|
}
|
|
#define __Pyx_Coroutine_ResetAndClearException(self) { \
|
|
__Pyx_ExceptionReset((self)->gi_exc_state.exc_type, (self)->gi_exc_state.exc_value, (self)->gi_exc_state.exc_traceback); \
|
|
(self)->gi_exc_state.exc_type = (self)->gi_exc_state.exc_value = (self)->gi_exc_state.exc_traceback = NULL; \
|
|
}
|
|
#endif
|
|
|
|
#if CYTHON_FAST_THREAD_STATE
|
|
#define __Pyx_PyGen_FetchStopIterationValue(pvalue) \
|
|
__Pyx_PyGen__FetchStopIterationValue($local_tstate_cname, pvalue)
|
|
#else
|
|
#define __Pyx_PyGen_FetchStopIterationValue(pvalue) \
|
|
__Pyx_PyGen__FetchStopIterationValue(__Pyx_PyThreadState_Current, pvalue)
|
|
#endif
|
|
static int __Pyx_PyGen__FetchStopIterationValue(PyThreadState *tstate, PyObject **pvalue); /*proto*/
|
|
static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__Pyx_ExcInfoStruct *exc_state); /*proto*/
|
|
|
|
|
|
//////////////////// Coroutine.proto ////////////////////
|
|
|
|
#define __Pyx_Coroutine_USED
|
|
#define __Pyx_Coroutine_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_CoroutineType)
|
|
// __Pyx_Coroutine_Check(obj): see override for IterableCoroutine below
|
|
#define __Pyx_Coroutine_Check(obj) __Pyx_Coroutine_CheckExact(obj)
|
|
#define __Pyx_CoroutineAwait_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_CoroutineAwaitType)
|
|
|
|
#define __Pyx_Coroutine_New(body, code, closure, name, qualname, module_name) \
|
|
__Pyx__Coroutine_New(__pyx_CoroutineType, body, code, closure, name, qualname, module_name)
|
|
|
|
static int __pyx_Coroutine_init(PyObject *module); /*proto*/
|
|
static PyObject *__Pyx__Coroutine_await(PyObject *coroutine); /*proto*/
|
|
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
PyObject *coroutine;
|
|
} __pyx_CoroutineAwaitObject;
|
|
|
|
static PyObject *__Pyx_CoroutineAwait_Close(__pyx_CoroutineAwaitObject *self, PyObject *arg); /*proto*/
|
|
static PyObject *__Pyx_CoroutineAwait_Throw(__pyx_CoroutineAwaitObject *self, PyObject *args); /*proto*/
|
|
|
|
|
|
//////////////////// Generator.proto ////////////////////
|
|
|
|
#define __Pyx_Generator_USED
|
|
#define __Pyx_Generator_CheckExact(obj) __Pyx_IS_TYPE(obj, __pyx_GeneratorType)
|
|
|
|
#define __Pyx_Generator_New(body, code, closure, name, qualname, module_name) \
|
|
__Pyx__Coroutine_New(__pyx_GeneratorType, body, code, closure, name, qualname, module_name)
|
|
|
|
static PyObject *__Pyx_Generator_Next(PyObject *self);
|
|
static int __pyx_Generator_init(PyObject *module); /*proto*/
|
|
|
|
|
|
//////////////////// AsyncGen ////////////////////
|
|
//@requires: AsyncGen.c::AsyncGenerator
|
|
// -> empty, only delegates to separate file
|
|
|
|
|
|
//////////////////// CoroutineBase ////////////////////
|
|
//@substitute: naming
|
|
//@requires: Exceptions.c::PyErrFetchRestore
|
|
//@requires: Exceptions.c::PyThreadStateGet
|
|
//@requires: Exceptions.c::SwapException
|
|
//@requires: Exceptions.c::RaiseException
|
|
//@requires: Exceptions.c::SaveResetException
|
|
//@requires: ObjectHandling.c::PyObjectCallMethod1
|
|
//@requires: ObjectHandling.c::PyObjectCallNoArg
|
|
//@requires: ObjectHandling.c::PyObjectCallOneArg
|
|
//@requires: ObjectHandling.c::PyObjectFastCall
|
|
//@requires: ObjectHandling.c::PyObjectGetAttrStr
|
|
//@requires: ObjectHandling.c::PyObjectGetAttrStrNoError
|
|
//@requires: CommonStructures.c::FetchCommonType
|
|
//@requires: ModuleSetupCode.c::IncludeStructmemberH
|
|
|
|
#include <frameobject.h>
|
|
#if PY_VERSION_HEX >= 0x030b00a6
|
|
#ifndef Py_BUILD_CORE
|
|
#define Py_BUILD_CORE 1
|
|
#endif
|
|
#include "internal/pycore_frame.h"
|
|
#endif
|
|
|
|
#define __Pyx_Coroutine_Undelegate(gen) Py_CLEAR((gen)->yieldfrom)
|
|
|
|
// If StopIteration exception is set, fetches its 'value'
|
|
// attribute if any, otherwise sets pvalue to None.
|
|
//
|
|
// Returns 0 if no exception or StopIteration is set.
|
|
// If any other exception is set, returns -1 and leaves
|
|
// pvalue unchanged.
|
|
static int __Pyx_PyGen__FetchStopIterationValue(PyThreadState *$local_tstate_cname, PyObject **pvalue) {
|
|
PyObject *et, *ev, *tb;
|
|
PyObject *value = NULL;
|
|
CYTHON_UNUSED_VAR($local_tstate_cname);
|
|
|
|
__Pyx_ErrFetch(&et, &ev, &tb);
|
|
|
|
if (!et) {
|
|
Py_XDECREF(tb);
|
|
Py_XDECREF(ev);
|
|
Py_INCREF(Py_None);
|
|
*pvalue = Py_None;
|
|
return 0;
|
|
}
|
|
|
|
// most common case: plain StopIteration without or with separate argument
|
|
if (likely(et == PyExc_StopIteration)) {
|
|
if (!ev) {
|
|
Py_INCREF(Py_None);
|
|
value = Py_None;
|
|
}
|
|
#if PY_VERSION_HEX >= 0x030300A0
|
|
else if (likely(__Pyx_IS_TYPE(ev, (PyTypeObject*)PyExc_StopIteration))) {
|
|
value = ((PyStopIterationObject *)ev)->value;
|
|
Py_INCREF(value);
|
|
Py_DECREF(ev);
|
|
}
|
|
#endif
|
|
// PyErr_SetObject() and friends put the value directly into ev
|
|
else if (unlikely(PyTuple_Check(ev))) {
|
|
// if it's a tuple, it is interpreted as separate constructor arguments (surprise!)
|
|
if (PyTuple_GET_SIZE(ev) >= 1) {
|
|
#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
|
|
value = PyTuple_GET_ITEM(ev, 0);
|
|
Py_INCREF(value);
|
|
#else
|
|
value = PySequence_ITEM(ev, 0);
|
|
#endif
|
|
} else {
|
|
Py_INCREF(Py_None);
|
|
value = Py_None;
|
|
}
|
|
Py_DECREF(ev);
|
|
}
|
|
else if (!__Pyx_TypeCheck(ev, (PyTypeObject*)PyExc_StopIteration)) {
|
|
// 'steal' reference to ev
|
|
value = ev;
|
|
}
|
|
if (likely(value)) {
|
|
Py_XDECREF(tb);
|
|
Py_DECREF(et);
|
|
*pvalue = value;
|
|
return 0;
|
|
}
|
|
} else if (!__Pyx_PyErr_GivenExceptionMatches(et, PyExc_StopIteration)) {
|
|
__Pyx_ErrRestore(et, ev, tb);
|
|
return -1;
|
|
}
|
|
|
|
// otherwise: normalise and check what that gives us
|
|
PyErr_NormalizeException(&et, &ev, &tb);
|
|
if (unlikely(!PyObject_TypeCheck(ev, (PyTypeObject*)PyExc_StopIteration))) {
|
|
// looks like normalisation failed - raise the new exception
|
|
__Pyx_ErrRestore(et, ev, tb);
|
|
return -1;
|
|
}
|
|
Py_XDECREF(tb);
|
|
Py_DECREF(et);
|
|
#if PY_VERSION_HEX >= 0x030300A0
|
|
value = ((PyStopIterationObject *)ev)->value;
|
|
Py_INCREF(value);
|
|
Py_DECREF(ev);
|
|
#else
|
|
{
|
|
PyObject* args = __Pyx_PyObject_GetAttrStr(ev, PYIDENT("args"));
|
|
Py_DECREF(ev);
|
|
if (likely(args)) {
|
|
value = PySequence_GetItem(args, 0);
|
|
Py_DECREF(args);
|
|
}
|
|
if (unlikely(!value)) {
|
|
__Pyx_ErrRestore(NULL, NULL, NULL);
|
|
Py_INCREF(Py_None);
|
|
value = Py_None;
|
|
}
|
|
}
|
|
#endif
|
|
*pvalue = value;
|
|
return 0;
|
|
}
|
|
|
|
static CYTHON_INLINE
|
|
void __Pyx_Coroutine_ExceptionClear(__Pyx_ExcInfoStruct *exc_state) {
|
|
#if PY_VERSION_HEX >= 0x030B00a4
|
|
Py_CLEAR(exc_state->exc_value);
|
|
#else
|
|
PyObject *t, *v, *tb;
|
|
t = exc_state->exc_type;
|
|
v = exc_state->exc_value;
|
|
tb = exc_state->exc_traceback;
|
|
|
|
exc_state->exc_type = NULL;
|
|
exc_state->exc_value = NULL;
|
|
exc_state->exc_traceback = NULL;
|
|
|
|
Py_XDECREF(t);
|
|
Py_XDECREF(v);
|
|
Py_XDECREF(tb);
|
|
#endif
|
|
}
|
|
|
|
#define __Pyx_Coroutine_AlreadyRunningError(gen) (__Pyx__Coroutine_AlreadyRunningError(gen), (PyObject*)NULL)
|
|
static void __Pyx__Coroutine_AlreadyRunningError(__pyx_CoroutineObject *gen) {
|
|
const char *msg;
|
|
CYTHON_MAYBE_UNUSED_VAR(gen);
|
|
if ((0)) {
|
|
#ifdef __Pyx_Coroutine_USED
|
|
} else if (__Pyx_Coroutine_Check((PyObject*)gen)) {
|
|
msg = "coroutine already executing";
|
|
#endif
|
|
#ifdef __Pyx_AsyncGen_USED
|
|
} else if (__Pyx_AsyncGen_CheckExact((PyObject*)gen)) {
|
|
msg = "async generator already executing";
|
|
#endif
|
|
} else {
|
|
msg = "generator already executing";
|
|
}
|
|
PyErr_SetString(PyExc_ValueError, msg);
|
|
}
|
|
|
|
#define __Pyx_Coroutine_NotStartedError(gen) (__Pyx__Coroutine_NotStartedError(gen), (PyObject*)NULL)
|
|
static void __Pyx__Coroutine_NotStartedError(PyObject *gen) {
|
|
const char *msg;
|
|
CYTHON_MAYBE_UNUSED_VAR(gen);
|
|
if ((0)) {
|
|
#ifdef __Pyx_Coroutine_USED
|
|
} else if (__Pyx_Coroutine_Check(gen)) {
|
|
msg = "can't send non-None value to a just-started coroutine";
|
|
#endif
|
|
#ifdef __Pyx_AsyncGen_USED
|
|
} else if (__Pyx_AsyncGen_CheckExact(gen)) {
|
|
msg = "can't send non-None value to a just-started async generator";
|
|
#endif
|
|
} else {
|
|
msg = "can't send non-None value to a just-started generator";
|
|
}
|
|
PyErr_SetString(PyExc_TypeError, msg);
|
|
}
|
|
|
|
#define __Pyx_Coroutine_AlreadyTerminatedError(gen, value, closing) (__Pyx__Coroutine_AlreadyTerminatedError(gen, value, closing), (PyObject*)NULL)
|
|
static void __Pyx__Coroutine_AlreadyTerminatedError(PyObject *gen, PyObject *value, int closing) {
|
|
CYTHON_MAYBE_UNUSED_VAR(gen);
|
|
CYTHON_MAYBE_UNUSED_VAR(closing);
|
|
#ifdef __Pyx_Coroutine_USED
|
|
if (!closing && __Pyx_Coroutine_Check(gen)) {
|
|
// `self` is an exhausted coroutine: raise an error,
|
|
// except when called from gen_close(), which should
|
|
// always be a silent method.
|
|
PyErr_SetString(PyExc_RuntimeError, "cannot reuse already awaited coroutine");
|
|
} else
|
|
#endif
|
|
if (value) {
|
|
// `gen` is an exhausted generator:
|
|
// only set exception if called from send().
|
|
#ifdef __Pyx_AsyncGen_USED
|
|
if (__Pyx_AsyncGen_CheckExact(gen))
|
|
PyErr_SetNone(__Pyx_PyExc_StopAsyncIteration);
|
|
else
|
|
#endif
|
|
PyErr_SetNone(PyExc_StopIteration);
|
|
}
|
|
}
|
|
|
|
static
|
|
PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, int closing) {
|
|
__Pyx_PyThreadState_declare
|
|
PyThreadState *tstate;
|
|
__Pyx_ExcInfoStruct *exc_state;
|
|
PyObject *retval;
|
|
|
|
assert(!self->is_running);
|
|
|
|
if (unlikely(self->resume_label == 0)) {
|
|
if (unlikely(value && value != Py_None)) {
|
|
return __Pyx_Coroutine_NotStartedError((PyObject*)self);
|
|
}
|
|
}
|
|
|
|
if (unlikely(self->resume_label == -1)) {
|
|
return __Pyx_Coroutine_AlreadyTerminatedError((PyObject*)self, value, closing);
|
|
}
|
|
|
|
#if CYTHON_FAST_THREAD_STATE
|
|
__Pyx_PyThreadState_assign
|
|
tstate = $local_tstate_cname;
|
|
#else
|
|
tstate = __Pyx_PyThreadState_Current;
|
|
#endif
|
|
|
|
// Traceback/Frame rules pre-Py3.7:
|
|
// - on entry, save external exception state in self->gi_exc_state, restore it on exit
|
|
// - on exit, keep internally generated exceptions in self->gi_exc_state, clear everything else
|
|
// - on entry, set "f_back" pointer of internal exception traceback to (current) outer call frame
|
|
// - on exit, clear "f_back" of internal exception traceback
|
|
// - do not touch external frames and tracebacks
|
|
|
|
// Traceback/Frame rules for Py3.7+ (CYTHON_USE_EXC_INFO_STACK):
|
|
// - on entry, push internal exception state in self->gi_exc_state on the exception stack
|
|
// - on exit, keep internally generated exceptions in self->gi_exc_state, clear everything else
|
|
// - on entry, set "f_back" pointer of internal exception traceback to (current) outer call frame
|
|
// - on exit, clear "f_back" of internal exception traceback
|
|
// - do not touch external frames and tracebacks
|
|
|
|
exc_state = &self->gi_exc_state;
|
|
if (exc_state->exc_value) {
|
|
#if CYTHON_COMPILING_IN_PYPY
|
|
// FIXME: what to do in PyPy?
|
|
#else
|
|
// Generators always return to their most recent caller, not
|
|
// necessarily their creator.
|
|
PyObject *exc_tb;
|
|
#if PY_VERSION_HEX >= 0x030B00a4 && !CYTHON_COMPILING_IN_CPYTHON
|
|
// owned reference!
|
|
exc_tb = PyException_GetTraceback(exc_state->exc_value);
|
|
#elif PY_VERSION_HEX >= 0x030B00a4
|
|
exc_tb = ((PyBaseExceptionObject*) exc_state->exc_value)->traceback;
|
|
#else
|
|
exc_tb = exc_state->exc_traceback;
|
|
#endif
|
|
if (exc_tb) {
|
|
PyTracebackObject *tb = (PyTracebackObject *) exc_tb;
|
|
PyFrameObject *f = tb->tb_frame;
|
|
|
|
assert(f->f_back == NULL);
|
|
#if PY_VERSION_HEX >= 0x030B00A1
|
|
// PyThreadState_GetFrame returns NULL if there isn't a current frame
|
|
// which is a valid state so no need to check
|
|
f->f_back = PyThreadState_GetFrame(tstate);
|
|
#else
|
|
Py_XINCREF(tstate->frame);
|
|
f->f_back = tstate->frame;
|
|
#endif
|
|
#if PY_VERSION_HEX >= 0x030B00a4 && !CYTHON_COMPILING_IN_CPYTHON
|
|
Py_DECREF(exc_tb);
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if CYTHON_USE_EXC_INFO_STACK
|
|
// See https://bugs.python.org/issue25612
|
|
exc_state->previous_item = tstate->exc_info;
|
|
tstate->exc_info = exc_state;
|
|
#else
|
|
if (exc_state->exc_type) {
|
|
// We were in an except handler when we left,
|
|
// restore the exception state which was put aside.
|
|
__Pyx_ExceptionSwap(&exc_state->exc_type, &exc_state->exc_value, &exc_state->exc_traceback);
|
|
// self->exc_* now holds the exception state of the caller
|
|
} else {
|
|
// save away the exception state of the caller
|
|
__Pyx_Coroutine_ExceptionClear(exc_state);
|
|
__Pyx_ExceptionSave(&exc_state->exc_type, &exc_state->exc_value, &exc_state->exc_traceback);
|
|
}
|
|
#endif
|
|
|
|
self->is_running = 1;
|
|
retval = self->body(self, tstate, value);
|
|
self->is_running = 0;
|
|
|
|
#if CYTHON_USE_EXC_INFO_STACK
|
|
// See https://bugs.python.org/issue25612
|
|
exc_state = &self->gi_exc_state;
|
|
tstate->exc_info = exc_state->previous_item;
|
|
exc_state->previous_item = NULL;
|
|
// Cut off the exception frame chain so that we can reconnect it on re-entry above.
|
|
__Pyx_Coroutine_ResetFrameBackpointer(exc_state);
|
|
#endif
|
|
|
|
return retval;
|
|
}
|
|
|
|
static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__Pyx_ExcInfoStruct *exc_state) {
|
|
// Don't keep the reference to f_back any longer than necessary. It
|
|
// may keep a chain of frames alive or it could create a reference
|
|
// cycle.
|
|
#if CYTHON_COMPILING_IN_PYPY
|
|
// FIXME: what to do in PyPy?
|
|
CYTHON_UNUSED_VAR(exc_state);
|
|
#else
|
|
PyObject *exc_tb;
|
|
|
|
#if PY_VERSION_HEX >= 0x030B00a4
|
|
if (!exc_state->exc_value) return;
|
|
// owned reference!
|
|
exc_tb = PyException_GetTraceback(exc_state->exc_value);
|
|
#else
|
|
exc_tb = exc_state->exc_traceback;
|
|
#endif
|
|
|
|
if (likely(exc_tb)) {
|
|
PyTracebackObject *tb = (PyTracebackObject *) exc_tb;
|
|
PyFrameObject *f = tb->tb_frame;
|
|
Py_CLEAR(f->f_back);
|
|
#if PY_VERSION_HEX >= 0x030B00a4
|
|
Py_DECREF(exc_tb);
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static CYTHON_INLINE
|
|
PyObject *__Pyx_Coroutine_MethodReturn(PyObject* gen, PyObject *retval) {
|
|
CYTHON_MAYBE_UNUSED_VAR(gen);
|
|
if (unlikely(!retval)) {
|
|
__Pyx_PyThreadState_declare
|
|
__Pyx_PyThreadState_assign
|
|
if (!__Pyx_PyErr_Occurred()) {
|
|
// method call must not terminate with NULL without setting an exception
|
|
PyObject *exc = PyExc_StopIteration;
|
|
#ifdef __Pyx_AsyncGen_USED
|
|
if (__Pyx_AsyncGen_CheckExact(gen))
|
|
exc = __Pyx_PyExc_StopAsyncIteration;
|
|
#endif
|
|
__Pyx_PyErr_SetNone(exc);
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03030000 && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3)
|
|
static CYTHON_INLINE
|
|
PyObject *__Pyx_PyGen_Send(PyGenObject *gen, PyObject *arg) {
|
|
#if PY_VERSION_HEX <= 0x030A00A1
|
|
return _PyGen_Send(gen, arg);
|
|
#else
|
|
PyObject *result;
|
|
// PyIter_Send() asserts non-NULL arg
|
|
if (PyIter_Send((PyObject*)gen, arg ? arg : Py_None, &result) == PYGEN_RETURN) {
|
|
if (PyAsyncGen_CheckExact(gen)) {
|
|
assert(result == Py_None);
|
|
PyErr_SetNone(PyExc_StopAsyncIteration);
|
|
}
|
|
else if (result == Py_None) {
|
|
PyErr_SetNone(PyExc_StopIteration);
|
|
}
|
|
else {
|
|
#if PY_VERSION_HEX < 0x030d00A1
|
|
_PyGen_SetStopIterationValue(result);
|
|
#else
|
|
if (!PyTuple_Check(result) && !PyExceptionInstance_Check(result)) {
|
|
// delay instantiation if possible
|
|
PyErr_SetObject(PyExc_StopIteration, result);
|
|
} else {
|
|
PyObject *exc = __Pyx_PyObject_CallOneArg(PyExc_StopIteration, result);
|
|
if (likely(exc != NULL)) {
|
|
PyErr_SetObject(PyExc_StopIteration, exc);
|
|
Py_DECREF(exc);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
Py_DECREF(result);
|
|
result = NULL;
|
|
}
|
|
return result;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
static CYTHON_INLINE
|
|
PyObject *__Pyx_Coroutine_FinishDelegation(__pyx_CoroutineObject *gen) {
|
|
PyObject *ret;
|
|
PyObject *val = NULL;
|
|
__Pyx_Coroutine_Undelegate(gen);
|
|
__Pyx_PyGen__FetchStopIterationValue(__Pyx_PyThreadState_Current, &val);
|
|
// val == NULL on failure => pass on exception
|
|
ret = __Pyx_Coroutine_SendEx(gen, val, 0);
|
|
Py_XDECREF(val);
|
|
return ret;
|
|
}
|
|
|
|
static PyObject *__Pyx_Coroutine_Send(PyObject *self, PyObject *value) {
|
|
PyObject *retval;
|
|
__pyx_CoroutineObject *gen = (__pyx_CoroutineObject*) self;
|
|
PyObject *yf = gen->yieldfrom;
|
|
if (unlikely(gen->is_running))
|
|
return __Pyx_Coroutine_AlreadyRunningError(gen);
|
|
if (yf) {
|
|
PyObject *ret;
|
|
// FIXME: does this really need an INCREF() ?
|
|
//Py_INCREF(yf);
|
|
gen->is_running = 1;
|
|
#ifdef __Pyx_Generator_USED
|
|
if (__Pyx_Generator_CheckExact(yf)) {
|
|
ret = __Pyx_Coroutine_Send(yf, value);
|
|
} else
|
|
#endif
|
|
#ifdef __Pyx_Coroutine_USED
|
|
if (__Pyx_Coroutine_Check(yf)) {
|
|
ret = __Pyx_Coroutine_Send(yf, value);
|
|
} else
|
|
#endif
|
|
#ifdef __Pyx_AsyncGen_USED
|
|
if (__pyx_PyAsyncGenASend_CheckExact(yf)) {
|
|
ret = __Pyx_async_gen_asend_send(yf, value);
|
|
} else
|
|
#endif
|
|
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03030000 && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3)
|
|
// _PyGen_Send() is not exported before Py3.6
|
|
if (PyGen_CheckExact(yf)) {
|
|
ret = __Pyx_PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value);
|
|
} else
|
|
#endif
|
|
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03050000 && defined(PyCoro_CheckExact) && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3)
|
|
// _PyGen_Send() is not exported before Py3.6
|
|
if (PyCoro_CheckExact(yf)) {
|
|
ret = __Pyx_PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value);
|
|
} else
|
|
#endif
|
|
{
|
|
if (value == Py_None)
|
|
ret = __Pyx_PyObject_GetIterNextFunc(yf)(yf);
|
|
else
|
|
ret = __Pyx_PyObject_CallMethod1(yf, PYIDENT("send"), value);
|
|
}
|
|
gen->is_running = 0;
|
|
//Py_DECREF(yf);
|
|
if (likely(ret)) {
|
|
return ret;
|
|
}
|
|
retval = __Pyx_Coroutine_FinishDelegation(gen);
|
|
} else {
|
|
retval = __Pyx_Coroutine_SendEx(gen, value, 0);
|
|
}
|
|
return __Pyx_Coroutine_MethodReturn(self, retval);
|
|
}
|
|
|
|
// This helper function is used by gen_close and gen_throw to
|
|
// close a subiterator being delegated to by yield-from.
|
|
static int __Pyx_Coroutine_CloseIter(__pyx_CoroutineObject *gen, PyObject *yf) {
|
|
PyObject *retval = NULL;
|
|
int err = 0;
|
|
|
|
#ifdef __Pyx_Generator_USED
|
|
if (__Pyx_Generator_CheckExact(yf)) {
|
|
retval = __Pyx_Coroutine_Close(yf);
|
|
if (!retval)
|
|
return -1;
|
|
} else
|
|
#endif
|
|
#ifdef __Pyx_Coroutine_USED
|
|
if (__Pyx_Coroutine_Check(yf)) {
|
|
retval = __Pyx_Coroutine_Close(yf);
|
|
if (!retval)
|
|
return -1;
|
|
} else
|
|
if (__Pyx_CoroutineAwait_CheckExact(yf)) {
|
|
retval = __Pyx_CoroutineAwait_Close((__pyx_CoroutineAwaitObject*)yf, NULL);
|
|
if (!retval)
|
|
return -1;
|
|
} else
|
|
#endif
|
|
#ifdef __Pyx_AsyncGen_USED
|
|
if (__pyx_PyAsyncGenASend_CheckExact(yf)) {
|
|
retval = __Pyx_async_gen_asend_close(yf, NULL);
|
|
// cannot fail
|
|
} else
|
|
if (__pyx_PyAsyncGenAThrow_CheckExact(yf)) {
|
|
retval = __Pyx_async_gen_athrow_close(yf, NULL);
|
|
// cannot fail
|
|
} else
|
|
#endif
|
|
{
|
|
PyObject *meth;
|
|
gen->is_running = 1;
|
|
meth = __Pyx_PyObject_GetAttrStrNoError(yf, PYIDENT("close"));
|
|
if (unlikely(!meth)) {
|
|
if (unlikely(PyErr_Occurred())) {
|
|
PyErr_WriteUnraisable(yf);
|
|
}
|
|
} else {
|
|
retval = __Pyx_PyObject_CallNoArg(meth);
|
|
Py_DECREF(meth);
|
|
if (unlikely(!retval))
|
|
err = -1;
|
|
}
|
|
gen->is_running = 0;
|
|
}
|
|
Py_XDECREF(retval);
|
|
return err;
|
|
}
|
|
|
|
static PyObject *__Pyx_Generator_Next(PyObject *self) {
|
|
__pyx_CoroutineObject *gen = (__pyx_CoroutineObject*) self;
|
|
PyObject *yf = gen->yieldfrom;
|
|
if (unlikely(gen->is_running))
|
|
return __Pyx_Coroutine_AlreadyRunningError(gen);
|
|
if (yf) {
|
|
PyObject *ret;
|
|
// FIXME: does this really need an INCREF() ?
|
|
//Py_INCREF(yf);
|
|
// YieldFrom code ensures that yf is an iterator
|
|
gen->is_running = 1;
|
|
#ifdef __Pyx_Generator_USED
|
|
if (__Pyx_Generator_CheckExact(yf)) {
|
|
ret = __Pyx_Generator_Next(yf);
|
|
} else
|
|
#endif
|
|
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03030000 && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3)
|
|
// _PyGen_Send() is not exported before Py3.6
|
|
if (PyGen_CheckExact(yf)) {
|
|
ret = __Pyx_PyGen_Send((PyGenObject*)yf, NULL);
|
|
} else
|
|
#endif
|
|
#ifdef __Pyx_Coroutine_USED
|
|
if (__Pyx_Coroutine_Check(yf)) {
|
|
ret = __Pyx_Coroutine_Send(yf, Py_None);
|
|
} else
|
|
#endif
|
|
ret = __Pyx_PyObject_GetIterNextFunc(yf)(yf);
|
|
gen->is_running = 0;
|
|
//Py_DECREF(yf);
|
|
if (likely(ret)) {
|
|
return ret;
|
|
}
|
|
return __Pyx_Coroutine_FinishDelegation(gen);
|
|
}
|
|
return __Pyx_Coroutine_SendEx(gen, Py_None, 0);
|
|
}
|
|
|
|
static PyObject *__Pyx_Coroutine_Close_Method(PyObject *self, PyObject *arg) {
|
|
CYTHON_UNUSED_VAR(arg);
|
|
return __Pyx_Coroutine_Close(self);
|
|
}
|
|
|
|
static PyObject *__Pyx_Coroutine_Close(PyObject *self) {
|
|
__pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self;
|
|
PyObject *retval, *raised_exception;
|
|
PyObject *yf = gen->yieldfrom;
|
|
int err = 0;
|
|
|
|
if (unlikely(gen->is_running))
|
|
return __Pyx_Coroutine_AlreadyRunningError(gen);
|
|
|
|
if (yf) {
|
|
Py_INCREF(yf);
|
|
err = __Pyx_Coroutine_CloseIter(gen, yf);
|
|
__Pyx_Coroutine_Undelegate(gen);
|
|
Py_DECREF(yf);
|
|
}
|
|
if (err == 0)
|
|
PyErr_SetNone(PyExc_GeneratorExit);
|
|
retval = __Pyx_Coroutine_SendEx(gen, NULL, 1);
|
|
if (unlikely(retval)) {
|
|
const char *msg;
|
|
Py_DECREF(retval);
|
|
if ((0)) {
|
|
#ifdef __Pyx_Coroutine_USED
|
|
} else if (__Pyx_Coroutine_Check(self)) {
|
|
msg = "coroutine ignored GeneratorExit";
|
|
#endif
|
|
#ifdef __Pyx_AsyncGen_USED
|
|
} else if (__Pyx_AsyncGen_CheckExact(self)) {
|
|
#if PY_VERSION_HEX < 0x03060000
|
|
msg = "async generator ignored GeneratorExit - might require Python 3.6+ finalisation (PEP 525)";
|
|
#else
|
|
msg = "async generator ignored GeneratorExit";
|
|
#endif
|
|
#endif
|
|
} else {
|
|
msg = "generator ignored GeneratorExit";
|
|
}
|
|
PyErr_SetString(PyExc_RuntimeError, msg);
|
|
return NULL;
|
|
}
|
|
raised_exception = PyErr_Occurred();
|
|
if (likely(!raised_exception || __Pyx_PyErr_GivenExceptionMatches2(raised_exception, PyExc_GeneratorExit, PyExc_StopIteration))) {
|
|
// ignore these errors
|
|
if (raised_exception) PyErr_Clear();
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *__Pyx__Coroutine_Throw(PyObject *self, PyObject *typ, PyObject *val, PyObject *tb,
|
|
PyObject *args, int close_on_genexit) {
|
|
__pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self;
|
|
PyObject *yf = gen->yieldfrom;
|
|
|
|
if (unlikely(gen->is_running))
|
|
return __Pyx_Coroutine_AlreadyRunningError(gen);
|
|
|
|
if (yf) {
|
|
PyObject *ret;
|
|
Py_INCREF(yf);
|
|
if (__Pyx_PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit) && close_on_genexit) {
|
|
// Asynchronous generators *should not* be closed right away.
|
|
// We have to allow some awaits to work it through, hence the
|
|
// `close_on_genexit` parameter here.
|
|
int err = __Pyx_Coroutine_CloseIter(gen, yf);
|
|
Py_DECREF(yf);
|
|
__Pyx_Coroutine_Undelegate(gen);
|
|
if (err < 0)
|
|
return __Pyx_Coroutine_MethodReturn(self, __Pyx_Coroutine_SendEx(gen, NULL, 0));
|
|
goto throw_here;
|
|
}
|
|
gen->is_running = 1;
|
|
if (0
|
|
#ifdef __Pyx_Generator_USED
|
|
|| __Pyx_Generator_CheckExact(yf)
|
|
#endif
|
|
#ifdef __Pyx_Coroutine_USED
|
|
|| __Pyx_Coroutine_Check(yf)
|
|
#endif
|
|
) {
|
|
ret = __Pyx__Coroutine_Throw(yf, typ, val, tb, args, close_on_genexit);
|
|
#ifdef __Pyx_Coroutine_USED
|
|
} else if (__Pyx_CoroutineAwait_CheckExact(yf)) {
|
|
ret = __Pyx__Coroutine_Throw(((__pyx_CoroutineAwaitObject*)yf)->coroutine, typ, val, tb, args, close_on_genexit);
|
|
#endif
|
|
} else {
|
|
PyObject *meth = __Pyx_PyObject_GetAttrStrNoError(yf, PYIDENT("throw"));
|
|
if (unlikely(!meth)) {
|
|
Py_DECREF(yf);
|
|
if (unlikely(PyErr_Occurred())) {
|
|
gen->is_running = 0;
|
|
return NULL;
|
|
}
|
|
__Pyx_Coroutine_Undelegate(gen);
|
|
gen->is_running = 0;
|
|
goto throw_here;
|
|
}
|
|
if (likely(args)) {
|
|
ret = __Pyx_PyObject_Call(meth, args, NULL);
|
|
} else {
|
|
// "tb" or even "val" might be NULL, but that also correctly terminates the argument list
|
|
PyObject *cargs[4] = {NULL, typ, val, tb};
|
|
ret = __Pyx_PyObject_FastCall(meth, cargs+1, 3 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET);
|
|
}
|
|
Py_DECREF(meth);
|
|
}
|
|
gen->is_running = 0;
|
|
Py_DECREF(yf);
|
|
if (!ret) {
|
|
ret = __Pyx_Coroutine_FinishDelegation(gen);
|
|
}
|
|
return __Pyx_Coroutine_MethodReturn(self, ret);
|
|
}
|
|
throw_here:
|
|
__Pyx_Raise(typ, val, tb, NULL);
|
|
return __Pyx_Coroutine_MethodReturn(self, __Pyx_Coroutine_SendEx(gen, NULL, 0));
|
|
}
|
|
|
|
static PyObject *__Pyx_Coroutine_Throw(PyObject *self, PyObject *args) {
|
|
PyObject *typ;
|
|
PyObject *val = NULL;
|
|
PyObject *tb = NULL;
|
|
|
|
if (unlikely(!PyArg_UnpackTuple(args, (char *)"throw", 1, 3, &typ, &val, &tb)))
|
|
return NULL;
|
|
|
|
return __Pyx__Coroutine_Throw(self, typ, val, tb, args, 1);
|
|
}
|
|
|
|
static CYTHON_INLINE int __Pyx_Coroutine_traverse_excstate(__Pyx_ExcInfoStruct *exc_state, visitproc visit, void *arg) {
|
|
#if PY_VERSION_HEX >= 0x030B00a4
|
|
Py_VISIT(exc_state->exc_value);
|
|
#else
|
|
Py_VISIT(exc_state->exc_type);
|
|
Py_VISIT(exc_state->exc_value);
|
|
Py_VISIT(exc_state->exc_traceback);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static int __Pyx_Coroutine_traverse(__pyx_CoroutineObject *gen, visitproc visit, void *arg) {
|
|
Py_VISIT(gen->closure);
|
|
Py_VISIT(gen->classobj);
|
|
Py_VISIT(gen->yieldfrom);
|
|
return __Pyx_Coroutine_traverse_excstate(&gen->gi_exc_state, visit, arg);
|
|
}
|
|
|
|
static int __Pyx_Coroutine_clear(PyObject *self) {
|
|
__pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self;
|
|
|
|
Py_CLEAR(gen->closure);
|
|
Py_CLEAR(gen->classobj);
|
|
Py_CLEAR(gen->yieldfrom);
|
|
__Pyx_Coroutine_ExceptionClear(&gen->gi_exc_state);
|
|
#ifdef __Pyx_AsyncGen_USED
|
|
if (__Pyx_AsyncGen_CheckExact(self)) {
|
|
Py_CLEAR(((__pyx_PyAsyncGenObject*)gen)->ag_finalizer);
|
|
}
|
|
#endif
|
|
Py_CLEAR(gen->gi_code);
|
|
Py_CLEAR(gen->gi_frame);
|
|
Py_CLEAR(gen->gi_name);
|
|
Py_CLEAR(gen->gi_qualname);
|
|
Py_CLEAR(gen->gi_modulename);
|
|
return 0;
|
|
}
|
|
|
|
static void __Pyx_Coroutine_dealloc(PyObject *self) {
|
|
__pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self;
|
|
|
|
PyObject_GC_UnTrack(gen);
|
|
if (gen->gi_weakreflist != NULL)
|
|
PyObject_ClearWeakRefs(self);
|
|
|
|
if (gen->resume_label >= 0) {
|
|
// Generator is paused or unstarted, so we need to close
|
|
PyObject_GC_Track(self);
|
|
#if PY_VERSION_HEX >= 0x030400a1 && CYTHON_USE_TP_FINALIZE
|
|
if (unlikely(PyObject_CallFinalizerFromDealloc(self)))
|
|
#else
|
|
Py_TYPE(gen)->tp_del(self);
|
|
if (unlikely(Py_REFCNT(self) > 0))
|
|
#endif
|
|
{
|
|
// resurrected. :(
|
|
return;
|
|
}
|
|
PyObject_GC_UnTrack(self);
|
|
}
|
|
|
|
#ifdef __Pyx_AsyncGen_USED
|
|
if (__Pyx_AsyncGen_CheckExact(self)) {
|
|
/* We have to handle this case for asynchronous generators
|
|
right here, because this code has to be between UNTRACK
|
|
and GC_Del. */
|
|
Py_CLEAR(((__pyx_PyAsyncGenObject*)self)->ag_finalizer);
|
|
}
|
|
#endif
|
|
__Pyx_Coroutine_clear(self);
|
|
__Pyx_PyHeapTypeObject_GC_Del(gen);
|
|
}
|
|
|
|
static void __Pyx_Coroutine_del(PyObject *self) {
|
|
PyObject *error_type, *error_value, *error_traceback;
|
|
__pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self;
|
|
__Pyx_PyThreadState_declare
|
|
|
|
if (gen->resume_label < 0) {
|
|
// already terminated => nothing to clean up
|
|
return;
|
|
}
|
|
|
|
#if !CYTHON_USE_TP_FINALIZE
|
|
// Temporarily resurrect the object.
|
|
assert(self->ob_refcnt == 0);
|
|
__Pyx_SET_REFCNT(self, 1);
|
|
#endif
|
|
|
|
__Pyx_PyThreadState_assign
|
|
|
|
// Save the current exception, if any.
|
|
__Pyx_ErrFetch(&error_type, &error_value, &error_traceback);
|
|
|
|
#ifdef __Pyx_AsyncGen_USED
|
|
if (__Pyx_AsyncGen_CheckExact(self)) {
|
|
__pyx_PyAsyncGenObject *agen = (__pyx_PyAsyncGenObject*)self;
|
|
PyObject *finalizer = agen->ag_finalizer;
|
|
if (finalizer && !agen->ag_closed) {
|
|
PyObject *res = __Pyx_PyObject_CallOneArg(finalizer, self);
|
|
if (unlikely(!res)) {
|
|
PyErr_WriteUnraisable(self);
|
|
} else {
|
|
Py_DECREF(res);
|
|
}
|
|
// Restore the saved exception.
|
|
__Pyx_ErrRestore(error_type, error_value, error_traceback);
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (unlikely(gen->resume_label == 0 && !error_value)) {
|
|
#ifdef __Pyx_Coroutine_USED
|
|
#ifdef __Pyx_Generator_USED
|
|
// only warn about (async) coroutines
|
|
if (!__Pyx_Generator_CheckExact(self))
|
|
#endif
|
|
{
|
|
// untrack dead object as we are executing Python code (which might trigger GC)
|
|
PyObject_GC_UnTrack(self);
|
|
#if PY_MAJOR_VERSION >= 3 /* PY_VERSION_HEX >= 0x03030000*/ || defined(PyErr_WarnFormat)
|
|
if (unlikely(PyErr_WarnFormat(PyExc_RuntimeWarning, 1, "coroutine '%.50S' was never awaited", gen->gi_qualname) < 0))
|
|
PyErr_WriteUnraisable(self);
|
|
#else
|
|
{PyObject *msg;
|
|
char *cmsg;
|
|
#if CYTHON_COMPILING_IN_PYPY
|
|
msg = NULL;
|
|
cmsg = (char*) "coroutine was never awaited";
|
|
#else
|
|
char *cname;
|
|
PyObject *qualname;
|
|
qualname = gen->gi_qualname;
|
|
cname = PyString_AS_STRING(qualname);
|
|
msg = PyString_FromFormat("coroutine '%.50s' was never awaited", cname);
|
|
|
|
if (unlikely(!msg)) {
|
|
PyErr_Clear();
|
|
cmsg = (char*) "coroutine was never awaited";
|
|
} else {
|
|
cmsg = PyString_AS_STRING(msg);
|
|
}
|
|
#endif
|
|
if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning, cmsg, 1) < 0))
|
|
PyErr_WriteUnraisable(self);
|
|
Py_XDECREF(msg);}
|
|
#endif
|
|
PyObject_GC_Track(self);
|
|
}
|
|
#endif /*__Pyx_Coroutine_USED*/
|
|
} else {
|
|
PyObject *res = __Pyx_Coroutine_Close(self);
|
|
if (unlikely(!res)) {
|
|
if (PyErr_Occurred())
|
|
PyErr_WriteUnraisable(self);
|
|
} else {
|
|
Py_DECREF(res);
|
|
}
|
|
}
|
|
|
|
// Restore the saved exception.
|
|
__Pyx_ErrRestore(error_type, error_value, error_traceback);
|
|
|
|
#if !CYTHON_USE_TP_FINALIZE
|
|
// Undo the temporary resurrection; can't use DECREF here, it would
|
|
// cause a recursive call.
|
|
assert(Py_REFCNT(self) > 0);
|
|
if (likely(--self->ob_refcnt == 0)) {
|
|
// this is the normal path out
|
|
return;
|
|
}
|
|
|
|
// close() resurrected it! Make it look like the original Py_DECREF
|
|
// never happened.
|
|
{
|
|
Py_ssize_t refcnt = Py_REFCNT(self);
|
|
_Py_NewReference(self);
|
|
__Pyx_SET_REFCNT(self, refcnt);
|
|
}
|
|
#if CYTHON_COMPILING_IN_CPYTHON
|
|
assert(PyType_IS_GC(Py_TYPE(self)) &&
|
|
_Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
|
|
|
|
// If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
|
|
// we need to undo that.
|
|
_Py_DEC_REFTOTAL;
|
|
#endif
|
|
// If Py_TRACE_REFS, _Py_NewReference re-added self to the object
|
|
// chain, so no more to do there.
|
|
// If COUNT_ALLOCS, the original decref bumped tp_frees, and
|
|
// _Py_NewReference bumped tp_allocs: both of those need to be
|
|
// undone.
|
|
#ifdef COUNT_ALLOCS
|
|
--Py_TYPE(self)->tp_frees;
|
|
--Py_TYPE(self)->tp_allocs;
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
static PyObject *
|
|
__Pyx_Coroutine_get_name(__pyx_CoroutineObject *self, void *context)
|
|
{
|
|
PyObject *name = self->gi_name;
|
|
CYTHON_UNUSED_VAR(context);
|
|
// avoid NULL pointer dereference during garbage collection
|
|
if (unlikely(!name)) name = Py_None;
|
|
Py_INCREF(name);
|
|
return name;
|
|
}
|
|
|
|
static int
|
|
__Pyx_Coroutine_set_name(__pyx_CoroutineObject *self, PyObject *value, void *context)
|
|
{
|
|
CYTHON_UNUSED_VAR(context);
|
|
#if PY_MAJOR_VERSION >= 3
|
|
if (unlikely(value == NULL || !PyUnicode_Check(value)))
|
|
#else
|
|
if (unlikely(value == NULL || !PyString_Check(value)))
|
|
#endif
|
|
{
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"__name__ must be set to a string object");
|
|
return -1;
|
|
}
|
|
Py_INCREF(value);
|
|
__Pyx_Py_XDECREF_SET(self->gi_name, value);
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
__Pyx_Coroutine_get_qualname(__pyx_CoroutineObject *self, void *context)
|
|
{
|
|
PyObject *name = self->gi_qualname;
|
|
CYTHON_UNUSED_VAR(context);
|
|
// avoid NULL pointer dereference during garbage collection
|
|
if (unlikely(!name)) name = Py_None;
|
|
Py_INCREF(name);
|
|
return name;
|
|
}
|
|
|
|
static int
|
|
__Pyx_Coroutine_set_qualname(__pyx_CoroutineObject *self, PyObject *value, void *context)
|
|
{
|
|
CYTHON_UNUSED_VAR(context);
|
|
#if PY_MAJOR_VERSION >= 3
|
|
if (unlikely(value == NULL || !PyUnicode_Check(value)))
|
|
#else
|
|
if (unlikely(value == NULL || !PyString_Check(value)))
|
|
#endif
|
|
{
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"__qualname__ must be set to a string object");
|
|
return -1;
|
|
}
|
|
Py_INCREF(value);
|
|
__Pyx_Py_XDECREF_SET(self->gi_qualname, value);
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *
|
|
__Pyx_Coroutine_get_frame(__pyx_CoroutineObject *self, void *context)
|
|
{
|
|
PyObject *frame = self->gi_frame;
|
|
CYTHON_UNUSED_VAR(context);
|
|
if (!frame) {
|
|
if (unlikely(!self->gi_code)) {
|
|
// Avoid doing something stupid, e.g. during garbage collection.
|
|
Py_RETURN_NONE;
|
|
}
|
|
frame = (PyObject *) PyFrame_New(
|
|
PyThreadState_Get(), /*PyThreadState *tstate,*/
|
|
(PyCodeObject*) self->gi_code, /*PyCodeObject *code,*/
|
|
$moddict_cname, /*PyObject *globals,*/
|
|
0 /*PyObject *locals*/
|
|
);
|
|
if (unlikely(!frame))
|
|
return NULL;
|
|
// keep the frame cached once it's created
|
|
self->gi_frame = frame;
|
|
}
|
|
Py_INCREF(frame);
|
|
return frame;
|
|
}
|
|
|
|
static __pyx_CoroutineObject *__Pyx__Coroutine_New(
|
|
PyTypeObject* type, __pyx_coroutine_body_t body, PyObject *code, PyObject *closure,
|
|
PyObject *name, PyObject *qualname, PyObject *module_name) {
|
|
__pyx_CoroutineObject *gen = PyObject_GC_New(__pyx_CoroutineObject, type);
|
|
if (unlikely(!gen))
|
|
return NULL;
|
|
return __Pyx__Coroutine_NewInit(gen, body, code, closure, name, qualname, module_name);
|
|
}
|
|
|
|
static __pyx_CoroutineObject *__Pyx__Coroutine_NewInit(
|
|
__pyx_CoroutineObject *gen, __pyx_coroutine_body_t body, PyObject *code, PyObject *closure,
|
|
PyObject *name, PyObject *qualname, PyObject *module_name) {
|
|
gen->body = body;
|
|
gen->closure = closure;
|
|
Py_XINCREF(closure);
|
|
gen->is_running = 0;
|
|
gen->resume_label = 0;
|
|
gen->classobj = NULL;
|
|
gen->yieldfrom = NULL;
|
|
#if PY_VERSION_HEX >= 0x030B00a4
|
|
gen->gi_exc_state.exc_value = NULL;
|
|
#else
|
|
gen->gi_exc_state.exc_type = NULL;
|
|
gen->gi_exc_state.exc_value = NULL;
|
|
gen->gi_exc_state.exc_traceback = NULL;
|
|
#endif
|
|
#if CYTHON_USE_EXC_INFO_STACK
|
|
gen->gi_exc_state.previous_item = NULL;
|
|
#endif
|
|
gen->gi_weakreflist = NULL;
|
|
Py_XINCREF(qualname);
|
|
gen->gi_qualname = qualname;
|
|
Py_XINCREF(name);
|
|
gen->gi_name = name;
|
|
Py_XINCREF(module_name);
|
|
gen->gi_modulename = module_name;
|
|
Py_XINCREF(code);
|
|
gen->gi_code = code;
|
|
gen->gi_frame = NULL;
|
|
|
|
PyObject_GC_Track(gen);
|
|
return gen;
|
|
}
|
|
|
|
|
|
//////////////////// Coroutine ////////////////////
|
|
//@requires: CoroutineBase
|
|
//@requires: PatchGeneratorABC
|
|
//@requires: ObjectHandling.c::PyObject_GenericGetAttrNoDict
|
|
|
|
static void __Pyx_CoroutineAwait_dealloc(PyObject *self) {
|
|
PyObject_GC_UnTrack(self);
|
|
Py_CLEAR(((__pyx_CoroutineAwaitObject*)self)->coroutine);
|
|
__Pyx_PyHeapTypeObject_GC_Del(self);
|
|
}
|
|
|
|
static int __Pyx_CoroutineAwait_traverse(__pyx_CoroutineAwaitObject *self, visitproc visit, void *arg) {
|
|
Py_VISIT(self->coroutine);
|
|
return 0;
|
|
}
|
|
|
|
static int __Pyx_CoroutineAwait_clear(__pyx_CoroutineAwaitObject *self) {
|
|
Py_CLEAR(self->coroutine);
|
|
return 0;
|
|
}
|
|
|
|
static PyObject *__Pyx_CoroutineAwait_Next(__pyx_CoroutineAwaitObject *self) {
|
|
return __Pyx_Generator_Next(self->coroutine);
|
|
}
|
|
|
|
static PyObject *__Pyx_CoroutineAwait_Send(__pyx_CoroutineAwaitObject *self, PyObject *value) {
|
|
return __Pyx_Coroutine_Send(self->coroutine, value);
|
|
}
|
|
|
|
static PyObject *__Pyx_CoroutineAwait_Throw(__pyx_CoroutineAwaitObject *self, PyObject *args) {
|
|
return __Pyx_Coroutine_Throw(self->coroutine, args);
|
|
}
|
|
|
|
static PyObject *__Pyx_CoroutineAwait_Close(__pyx_CoroutineAwaitObject *self, PyObject *arg) {
|
|
CYTHON_UNUSED_VAR(arg);
|
|
return __Pyx_Coroutine_Close(self->coroutine);
|
|
}
|
|
|
|
static PyObject *__Pyx_CoroutineAwait_self(PyObject *self) {
|
|
Py_INCREF(self);
|
|
return self;
|
|
}
|
|
|
|
#if !CYTHON_COMPILING_IN_PYPY
|
|
static PyObject *__Pyx_CoroutineAwait_no_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) {
|
|
CYTHON_UNUSED_VAR(type);
|
|
CYTHON_UNUSED_VAR(args);
|
|
CYTHON_UNUSED_VAR(kwargs);
|
|
PyErr_SetString(PyExc_TypeError, "cannot instantiate type, use 'await coroutine' instead");
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
// In earlier versions of Python an object with no __dict__ and not __slots__ is assumed
|
|
// to be pickleable by default. Coroutine-wrappers have significant state so shouldn't be.
|
|
// Therefore provide a default implementation.
|
|
// Something similar applies to heaptypes (i.e. with type_specs) with protocols 0 and 1
|
|
// even in more recent versions.
|
|
// We are applying this to all Python versions (hence the commented out version guard)
|
|
// to make the behaviour explicit.
|
|
// #if PY_VERSION_HEX < 0x03060000 || CYTHON_USE_TYPE_SPECS
|
|
static PyObject *__Pyx_CoroutineAwait_reduce_ex(__pyx_CoroutineAwaitObject *self, PyObject *arg) {
|
|
CYTHON_UNUSED_VAR(arg);
|
|
PyErr_Format(PyExc_TypeError, "cannot pickle '%.200s' object",
|
|
Py_TYPE(self)->tp_name);
|
|
return NULL;
|
|
}
|
|
// #endif
|
|
|
|
static PyMethodDef __pyx_CoroutineAwait_methods[] = {
|
|
{"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.")},
|
|
// only needed with type-specs or version<3.6, but included in all versions for clarity
|
|
// #if PY_VERSION_HEX < 0x03060000 || CYTHON_USE_TYPE_SPECS
|
|
{"__reduce_ex__", (PyCFunction) __Pyx_CoroutineAwait_reduce_ex, METH_O, 0},
|
|
{"__reduce__", (PyCFunction) __Pyx_CoroutineAwait_reduce_ex, METH_NOARGS, 0},
|
|
// #endif
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
#if CYTHON_USE_TYPE_SPECS
|
|
static PyType_Slot __pyx_CoroutineAwaitType_slots[] = {
|
|
{Py_tp_dealloc, (void *)__Pyx_CoroutineAwait_dealloc},
|
|
{Py_tp_traverse, (void *)__Pyx_CoroutineAwait_traverse},
|
|
{Py_tp_clear, (void *)__Pyx_CoroutineAwait_clear},
|
|
#if !CYTHON_COMPILING_IN_PYPY
|
|
{Py_tp_new, (void *)__Pyx_CoroutineAwait_no_new},
|
|
#endif
|
|
{Py_tp_methods, (void *)__pyx_CoroutineAwait_methods},
|
|
{Py_tp_iter, (void *)__Pyx_CoroutineAwait_self},
|
|
{Py_tp_iternext, (void *)__Pyx_CoroutineAwait_Next},
|
|
{0, 0},
|
|
};
|
|
|
|
static PyType_Spec __pyx_CoroutineAwaitType_spec = {
|
|
__PYX_TYPE_MODULE_PREFIX "coroutine_wrapper",
|
|
sizeof(__pyx_CoroutineAwaitObject),
|
|
0,
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
|
|
__pyx_CoroutineAwaitType_slots
|
|
};
|
|
#else /* CYTHON_USE_TYPE_SPECS */
|
|
|
|
static PyTypeObject __pyx_CoroutineAwaitType_type = {
|
|
PyVarObject_HEAD_INIT(0, 0)
|
|
__PYX_TYPE_MODULE_PREFIX "coroutine_wrapper", /*tp_name*/
|
|
sizeof(__pyx_CoroutineAwaitObject), /*tp_basicsize*/
|
|
0, /*tp_itemsize*/
|
|
(destructor) __Pyx_CoroutineAwait_dealloc,/*tp_dealloc*/
|
|
0, /*tp_print*/
|
|
0, /*tp_getattr*/
|
|
0, /*tp_setattr*/
|
|
0, /*tp_as_async resp. tp_compare*/
|
|
0, /*tp_repr*/
|
|
0, /*tp_as_number*/
|
|
0, /*tp_as_sequence*/
|
|
0, /*tp_as_mapping*/
|
|
0, /*tp_hash*/
|
|
0, /*tp_call*/
|
|
0, /*tp_str*/
|
|
0, /*tp_getattro*/
|
|
0, /*tp_setattro*/
|
|
0, /*tp_as_buffer*/
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
|
|
PyDoc_STR("A wrapper object implementing __await__ for coroutines."), /*tp_doc*/
|
|
(traverseproc) __Pyx_CoroutineAwait_traverse, /*tp_traverse*/
|
|
(inquiry) __Pyx_CoroutineAwait_clear, /*tp_clear*/
|
|
0, /*tp_richcompare*/
|
|
0, /*tp_weaklistoffset*/
|
|
__Pyx_CoroutineAwait_self, /*tp_iter*/
|
|
(iternextfunc) __Pyx_CoroutineAwait_Next, /*tp_iternext*/
|
|
__pyx_CoroutineAwait_methods, /*tp_methods*/
|
|
0 , /*tp_members*/
|
|
0 , /*tp_getset*/
|
|
0, /*tp_base*/
|
|
0, /*tp_dict*/
|
|
0, /*tp_descr_get*/
|
|
0, /*tp_descr_set*/
|
|
0, /*tp_dictoffset*/
|
|
0, /*tp_init*/
|
|
0, /*tp_alloc*/
|
|
#if !CYTHON_COMPILING_IN_PYPY
|
|
__Pyx_CoroutineAwait_no_new, /*tp_new*/
|
|
#else
|
|
0, /*tp_new*/
|
|
#endif
|
|
0, /*tp_free*/
|
|
0, /*tp_is_gc*/
|
|
0, /*tp_bases*/
|
|
0, /*tp_mro*/
|
|
0, /*tp_cache*/
|
|
0, /*tp_subclasses*/
|
|
0, /*tp_weaklist*/
|
|
0, /*tp_del*/
|
|
0, /*tp_version_tag*/
|
|
#if PY_VERSION_HEX >= 0x030400a1
|
|
0, /*tp_finalize*/
|
|
#endif
|
|
#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
|
|
0, /*tp_vectorcall*/
|
|
#endif
|
|
#if __PYX_NEED_TP_PRINT_SLOT
|
|
0, /*tp_print*/
|
|
#endif
|
|
#if PY_VERSION_HEX >= 0x030C0000
|
|
0, /*tp_watched*/
|
|
#endif
|
|
#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
|
|
0, /*tp_pypy_flags*/
|
|
#endif
|
|
};
|
|
#endif /* CYTHON_USE_TYPE_SPECS */
|
|
|
|
#if PY_VERSION_HEX < 0x030500B1 || defined(__Pyx_IterableCoroutine_USED) || CYTHON_USE_ASYNC_SLOTS
|
|
static CYTHON_INLINE PyObject *__Pyx__Coroutine_await(PyObject *coroutine) {
|
|
__pyx_CoroutineAwaitObject *await = PyObject_GC_New(__pyx_CoroutineAwaitObject, __pyx_CoroutineAwaitType);
|
|
if (unlikely(!await)) return NULL;
|
|
Py_INCREF(coroutine);
|
|
await->coroutine = coroutine;
|
|
PyObject_GC_Track(await);
|
|
return (PyObject*)await;
|
|
}
|
|
#endif
|
|
|
|
#if PY_VERSION_HEX < 0x030500B1
|
|
static PyObject *__Pyx_Coroutine_await_method(PyObject *coroutine, PyObject *arg) {
|
|
CYTHON_UNUSED_VAR(arg);
|
|
return __Pyx__Coroutine_await(coroutine);
|
|
}
|
|
#endif
|
|
|
|
#if defined(__Pyx_IterableCoroutine_USED) || CYTHON_USE_ASYNC_SLOTS
|
|
static PyObject *__Pyx_Coroutine_await(PyObject *coroutine) {
|
|
if (unlikely(!coroutine || !__Pyx_Coroutine_Check(coroutine))) {
|
|
PyErr_SetString(PyExc_TypeError, "invalid input, expected coroutine");
|
|
return NULL;
|
|
}
|
|
return __Pyx__Coroutine_await(coroutine);
|
|
}
|
|
#endif
|
|
|
|
#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3 && PY_VERSION_HEX < 0x030500B1
|
|
static PyObject *__Pyx_Coroutine_compare(PyObject *obj, PyObject *other, int op) {
|
|
PyObject* result;
|
|
switch (op) {
|
|
case Py_EQ: result = (other == obj) ? Py_True : Py_False; break;
|
|
case Py_NE: result = (other != obj) ? Py_True : Py_False; break;
|
|
default:
|
|
result = Py_NotImplemented;
|
|
}
|
|
Py_INCREF(result);
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
static PyMethodDef __pyx_Coroutine_methods[] = {
|
|
{"send", (PyCFunction) __Pyx_Coroutine_Send, METH_O,
|
|
(char*) PyDoc_STR("send(arg) -> send 'arg' into coroutine,\nreturn next iterated value or raise StopIteration.")},
|
|
{"throw", (PyCFunction) __Pyx_Coroutine_Throw, METH_VARARGS,
|
|
(char*) PyDoc_STR("throw(typ[,val[,tb]]) -> raise exception in coroutine,\nreturn next iterated value or raise StopIteration.")},
|
|
{"close", (PyCFunction) __Pyx_Coroutine_Close_Method, METH_NOARGS,
|
|
(char*) PyDoc_STR("close() -> raise GeneratorExit inside coroutine.")},
|
|
#if PY_VERSION_HEX < 0x030500B1
|
|
{"__await__", (PyCFunction) __Pyx_Coroutine_await_method, METH_NOARGS,
|
|
(char*) PyDoc_STR("__await__() -> return an iterator to be used in await expression.")},
|
|
#endif
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
static PyMemberDef __pyx_Coroutine_memberlist[] = {
|
|
{(char *) "cr_running", T_BOOL, offsetof(__pyx_CoroutineObject, is_running), READONLY, NULL},
|
|
{(char*) "cr_await", T_OBJECT, offsetof(__pyx_CoroutineObject, yieldfrom), READONLY,
|
|
(char*) PyDoc_STR("object being awaited, or None")},
|
|
{(char*) "cr_code", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_code), READONLY, NULL},
|
|
{(char *) "__module__", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_modulename), 0, 0},
|
|
#if CYTHON_USE_TYPE_SPECS
|
|
{(char *) "__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CoroutineObject, gi_weakreflist), READONLY, 0},
|
|
#endif
|
|
{0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static PyGetSetDef __pyx_Coroutine_getsets[] = {
|
|
{(char *) "__name__", (getter)__Pyx_Coroutine_get_name, (setter)__Pyx_Coroutine_set_name,
|
|
(char*) PyDoc_STR("name of the coroutine"), 0},
|
|
{(char *) "__qualname__", (getter)__Pyx_Coroutine_get_qualname, (setter)__Pyx_Coroutine_set_qualname,
|
|
(char*) PyDoc_STR("qualified name of the coroutine"), 0},
|
|
{(char *) "cr_frame", (getter)__Pyx_Coroutine_get_frame, NULL,
|
|
(char*) PyDoc_STR("Frame of the coroutine"), 0},
|
|
{0, 0, 0, 0, 0}
|
|
};
|
|
|
|
#if CYTHON_USE_TYPE_SPECS
|
|
static PyType_Slot __pyx_CoroutineType_slots[] = {
|
|
{Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc},
|
|
{Py_am_await, (void *)&__Pyx_Coroutine_await},
|
|
{Py_tp_traverse, (void *)__Pyx_Coroutine_traverse},
|
|
{Py_tp_methods, (void *)__pyx_Coroutine_methods},
|
|
{Py_tp_members, (void *)__pyx_Coroutine_memberlist},
|
|
{Py_tp_getset, (void *)__pyx_Coroutine_getsets},
|
|
{Py_tp_getattro, (void *) __Pyx_PyObject_GenericGetAttrNoDict},
|
|
#if CYTHON_USE_TP_FINALIZE
|
|
{Py_tp_finalize, (void *)__Pyx_Coroutine_del},
|
|
#endif
|
|
{0, 0},
|
|
};
|
|
|
|
static PyType_Spec __pyx_CoroutineType_spec = {
|
|
__PYX_TYPE_MODULE_PREFIX "coroutine",
|
|
sizeof(__pyx_CoroutineObject),
|
|
0,
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
|
|
__pyx_CoroutineType_slots
|
|
};
|
|
#else /* CYTHON_USE_TYPE_SPECS */
|
|
|
|
#if CYTHON_USE_ASYNC_SLOTS
|
|
static __Pyx_PyAsyncMethodsStruct __pyx_Coroutine_as_async = {
|
|
__Pyx_Coroutine_await, /*am_await*/
|
|
0, /*am_aiter*/
|
|
0, /*am_anext*/
|
|
#if PY_VERSION_HEX >= 0x030A00A3
|
|
0, /*am_send*/
|
|
#endif
|
|
};
|
|
#endif
|
|
|
|
static PyTypeObject __pyx_CoroutineType_type = {
|
|
PyVarObject_HEAD_INIT(0, 0)
|
|
__PYX_TYPE_MODULE_PREFIX "coroutine", /*tp_name*/
|
|
sizeof(__pyx_CoroutineObject), /*tp_basicsize*/
|
|
0, /*tp_itemsize*/
|
|
(destructor) __Pyx_Coroutine_dealloc,/*tp_dealloc*/
|
|
0, /*tp_print*/
|
|
0, /*tp_getattr*/
|
|
0, /*tp_setattr*/
|
|
#if CYTHON_USE_ASYNC_SLOTS
|
|
&__pyx_Coroutine_as_async, /*tp_as_async (tp_reserved) - Py3 only! */
|
|
#else
|
|
0, /*tp_reserved*/
|
|
#endif
|
|
0, /*tp_repr*/
|
|
0, /*tp_as_number*/
|
|
0, /*tp_as_sequence*/
|
|
0, /*tp_as_mapping*/
|
|
0, /*tp_hash*/
|
|
0, /*tp_call*/
|
|
0, /*tp_str*/
|
|
0, /*tp_getattro*/
|
|
0, /*tp_setattro*/
|
|
0, /*tp_as_buffer*/
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
|
|
0, /*tp_doc*/
|
|
(traverseproc) __Pyx_Coroutine_traverse, /*tp_traverse*/
|
|
0, /*tp_clear*/
|
|
#if CYTHON_USE_ASYNC_SLOTS && CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3 && PY_VERSION_HEX < 0x030500B1
|
|
// in order to (mis-)use tp_reserved above, we must also implement tp_richcompare
|
|
__Pyx_Coroutine_compare, /*tp_richcompare*/
|
|
#else
|
|
0, /*tp_richcompare*/
|
|
#endif
|
|
offsetof(__pyx_CoroutineObject, gi_weakreflist), /*tp_weaklistoffset*/
|
|
// no tp_iter() as iterator is only available through __await__()
|
|
0, /*tp_iter*/
|
|
0, /*tp_iternext*/
|
|
__pyx_Coroutine_methods, /*tp_methods*/
|
|
__pyx_Coroutine_memberlist, /*tp_members*/
|
|
__pyx_Coroutine_getsets, /*tp_getset*/
|
|
0, /*tp_base*/
|
|
0, /*tp_dict*/
|
|
0, /*tp_descr_get*/
|
|
0, /*tp_descr_set*/
|
|
0, /*tp_dictoffset*/
|
|
0, /*tp_init*/
|
|
0, /*tp_alloc*/
|
|
0, /*tp_new*/
|
|
0, /*tp_free*/
|
|
0, /*tp_is_gc*/
|
|
0, /*tp_bases*/
|
|
0, /*tp_mro*/
|
|
0, /*tp_cache*/
|
|
0, /*tp_subclasses*/
|
|
0, /*tp_weaklist*/
|
|
#if CYTHON_USE_TP_FINALIZE
|
|
0, /*tp_del*/
|
|
#else
|
|
__Pyx_Coroutine_del, /*tp_del*/
|
|
#endif
|
|
0, /*tp_version_tag*/
|
|
#if CYTHON_USE_TP_FINALIZE
|
|
__Pyx_Coroutine_del, /*tp_finalize*/
|
|
#elif PY_VERSION_HEX >= 0x030400a1
|
|
0, /*tp_finalize*/
|
|
#endif
|
|
#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
|
|
0, /*tp_vectorcall*/
|
|
#endif
|
|
#if __PYX_NEED_TP_PRINT_SLOT
|
|
0, /*tp_print*/
|
|
#endif
|
|
#if PY_VERSION_HEX >= 0x030C0000
|
|
0, /*tp_watched*/
|
|
#endif
|
|
#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
|
|
0, /*tp_pypy_flags*/
|
|
#endif
|
|
};
|
|
#endif /* CYTHON_USE_TYPE_SPECS */
|
|
|
|
static int __pyx_Coroutine_init(PyObject *module) {
|
|
CYTHON_MAYBE_UNUSED_VAR(module);
|
|
// on Windows, C-API functions can't be used in slots statically
|
|
#if CYTHON_USE_TYPE_SPECS
|
|
__pyx_CoroutineType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_CoroutineType_spec, NULL);
|
|
#else
|
|
__pyx_CoroutineType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict;
|
|
__pyx_CoroutineType = __Pyx_FetchCommonType(&__pyx_CoroutineType_type);
|
|
#endif
|
|
if (unlikely(!__pyx_CoroutineType))
|
|
return -1;
|
|
|
|
#ifdef __Pyx_IterableCoroutine_USED
|
|
if (unlikely(__pyx_IterableCoroutine_init(module) == -1))
|
|
return -1;
|
|
#endif
|
|
|
|
#if CYTHON_USE_TYPE_SPECS
|
|
__pyx_CoroutineAwaitType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_CoroutineAwaitType_spec, NULL);
|
|
#else
|
|
__pyx_CoroutineAwaitType = __Pyx_FetchCommonType(&__pyx_CoroutineAwaitType_type);
|
|
#endif
|
|
if (unlikely(!__pyx_CoroutineAwaitType))
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
//////////////////// IterableCoroutine.proto ////////////////////
|
|
|
|
#define __Pyx_IterableCoroutine_USED
|
|
|
|
#undef __Pyx_Coroutine_Check
|
|
#define __Pyx_Coroutine_Check(obj) (__Pyx_Coroutine_CheckExact(obj) || __Pyx_IS_TYPE(obj, __pyx_IterableCoroutineType))
|
|
|
|
#define __Pyx_IterableCoroutine_New(body, code, closure, name, qualname, module_name) \
|
|
__Pyx__Coroutine_New(__pyx_IterableCoroutineType, body, code, closure, name, qualname, module_name)
|
|
|
|
static int __pyx_IterableCoroutine_init(PyObject *module);/*proto*/
|
|
|
|
|
|
//////////////////// IterableCoroutine ////////////////////
|
|
//@requires: Coroutine
|
|
//@requires: CommonStructures.c::FetchCommonType
|
|
|
|
#if CYTHON_USE_TYPE_SPECS
|
|
static PyType_Slot __pyx_IterableCoroutineType_slots[] = {
|
|
{Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc},
|
|
{Py_am_await, (void *)&__Pyx_Coroutine_await},
|
|
{Py_tp_traverse, (void *)__Pyx_Coroutine_traverse},
|
|
{Py_tp_iter, (void *)__Pyx_Coroutine_await},
|
|
{Py_tp_iternext, (void *)__Pyx_Generator_Next},
|
|
{Py_tp_methods, (void *)__pyx_Coroutine_methods},
|
|
{Py_tp_members, (void *)__pyx_Coroutine_memberlist},
|
|
{Py_tp_getset, (void *)__pyx_Coroutine_getsets},
|
|
{Py_tp_getattro, (void *) __Pyx_PyObject_GenericGetAttrNoDict},
|
|
#if CYTHON_USE_TP_FINALIZE
|
|
{Py_tp_finalize, (void *)__Pyx_Coroutine_del},
|
|
#endif
|
|
{0, 0},
|
|
};
|
|
|
|
static PyType_Spec __pyx_IterableCoroutineType_spec = {
|
|
__PYX_TYPE_MODULE_PREFIX "iterable_coroutine",
|
|
sizeof(__pyx_CoroutineObject),
|
|
0,
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
|
|
__pyx_IterableCoroutineType_slots
|
|
};
|
|
#else /* CYTHON_USE_TYPE_SPECS */
|
|
|
|
static PyTypeObject __pyx_IterableCoroutineType_type = {
|
|
PyVarObject_HEAD_INIT(0, 0)
|
|
__PYX_TYPE_MODULE_PREFIX "iterable_coroutine", /*tp_name*/
|
|
sizeof(__pyx_CoroutineObject), /*tp_basicsize*/
|
|
0, /*tp_itemsize*/
|
|
(destructor) __Pyx_Coroutine_dealloc,/*tp_dealloc*/
|
|
0, /*tp_print*/
|
|
0, /*tp_getattr*/
|
|
0, /*tp_setattr*/
|
|
#if CYTHON_USE_ASYNC_SLOTS
|
|
&__pyx_Coroutine_as_async, /*tp_as_async (tp_reserved) - Py3 only! */
|
|
#else
|
|
0, /*tp_reserved*/
|
|
#endif
|
|
0, /*tp_repr*/
|
|
0, /*tp_as_number*/
|
|
0, /*tp_as_sequence*/
|
|
0, /*tp_as_mapping*/
|
|
0, /*tp_hash*/
|
|
0, /*tp_call*/
|
|
0, /*tp_str*/
|
|
0, /*tp_getattro*/
|
|
0, /*tp_setattro*/
|
|
0, /*tp_as_buffer*/
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
|
|
0, /*tp_doc*/
|
|
(traverseproc) __Pyx_Coroutine_traverse, /*tp_traverse*/
|
|
0, /*tp_clear*/
|
|
#if CYTHON_USE_ASYNC_SLOTS && CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3 && PY_VERSION_HEX < 0x030500B1
|
|
// in order to (mis-)use tp_reserved above, we must also implement tp_richcompare
|
|
__Pyx_Coroutine_compare, /*tp_richcompare*/
|
|
#else
|
|
0, /*tp_richcompare*/
|
|
#endif
|
|
offsetof(__pyx_CoroutineObject, gi_weakreflist), /*tp_weaklistoffset*/
|
|
// enable iteration for legacy support of asyncio yield-from protocol
|
|
__Pyx_Coroutine_await, /*tp_iter*/
|
|
(iternextfunc) __Pyx_Generator_Next, /*tp_iternext*/
|
|
__pyx_Coroutine_methods, /*tp_methods*/
|
|
__pyx_Coroutine_memberlist, /*tp_members*/
|
|
__pyx_Coroutine_getsets, /*tp_getset*/
|
|
0, /*tp_base*/
|
|
0, /*tp_dict*/
|
|
0, /*tp_descr_get*/
|
|
0, /*tp_descr_set*/
|
|
0, /*tp_dictoffset*/
|
|
0, /*tp_init*/
|
|
0, /*tp_alloc*/
|
|
0, /*tp_new*/
|
|
0, /*tp_free*/
|
|
0, /*tp_is_gc*/
|
|
0, /*tp_bases*/
|
|
0, /*tp_mro*/
|
|
0, /*tp_cache*/
|
|
0, /*tp_subclasses*/
|
|
0, /*tp_weaklist*/
|
|
#if PY_VERSION_HEX >= 0x030400a1
|
|
0, /*tp_del*/
|
|
#else
|
|
__Pyx_Coroutine_del, /*tp_del*/
|
|
#endif
|
|
0, /*tp_version_tag*/
|
|
#if PY_VERSION_HEX >= 0x030400a1 && !CYTHON_COMPILING_IN_PYPY
|
|
__Pyx_Coroutine_del, /*tp_finalize*/
|
|
#endif
|
|
#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
|
|
0, /*tp_vectorcall*/
|
|
#endif
|
|
#if __PYX_NEED_TP_PRINT_SLOT
|
|
0, /*tp_print*/
|
|
#endif
|
|
#if PY_VERSION_HEX >= 0x030C0000
|
|
0, /*tp_watched*/
|
|
#endif
|
|
#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
|
|
0, /*tp_pypy_flags*/
|
|
#endif
|
|
};
|
|
#endif /* CYTHON_USE_TYPE_SPECS */
|
|
|
|
|
|
static int __pyx_IterableCoroutine_init(PyObject *module) {
|
|
#if CYTHON_USE_TYPE_SPECS
|
|
__pyx_IterableCoroutineType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_IterableCoroutineType_spec, NULL);
|
|
#else
|
|
CYTHON_UNUSED_VAR(module);
|
|
__pyx_IterableCoroutineType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict;
|
|
__pyx_IterableCoroutineType = __Pyx_FetchCommonType(&__pyx_IterableCoroutineType_type);
|
|
#endif
|
|
if (unlikely(!__pyx_IterableCoroutineType))
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
//////////////////// Generator ////////////////////
|
|
//@requires: CoroutineBase
|
|
//@requires: PatchGeneratorABC
|
|
//@requires: ObjectHandling.c::PyObject_GenericGetAttrNoDict
|
|
|
|
static PyMethodDef __pyx_Generator_methods[] = {
|
|
{"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_Method, METH_NOARGS,
|
|
(char*) PyDoc_STR("close() -> raise GeneratorExit inside generator.")},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
static PyMemberDef __pyx_Generator_memberlist[] = {
|
|
{(char *) "gi_running", T_BOOL, offsetof(__pyx_CoroutineObject, is_running), READONLY, NULL},
|
|
{(char*) "gi_yieldfrom", T_OBJECT, offsetof(__pyx_CoroutineObject, yieldfrom), READONLY,
|
|
(char*) PyDoc_STR("object being iterated by 'yield from', or None")},
|
|
{(char*) "gi_code", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_code), READONLY, NULL},
|
|
{(char *) "__module__", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_modulename), 0, 0},
|
|
#if CYTHON_USE_TYPE_SPECS
|
|
{(char *) "__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CoroutineObject, gi_weakreflist), READONLY, 0},
|
|
#endif
|
|
{0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static PyGetSetDef __pyx_Generator_getsets[] = {
|
|
{(char *) "__name__", (getter)__Pyx_Coroutine_get_name, (setter)__Pyx_Coroutine_set_name,
|
|
(char*) PyDoc_STR("name of the generator"), 0},
|
|
{(char *) "__qualname__", (getter)__Pyx_Coroutine_get_qualname, (setter)__Pyx_Coroutine_set_qualname,
|
|
(char*) PyDoc_STR("qualified name of the generator"), 0},
|
|
{(char *) "gi_frame", (getter)__Pyx_Coroutine_get_frame, NULL,
|
|
(char*) PyDoc_STR("Frame of the generator"), 0},
|
|
{0, 0, 0, 0, 0}
|
|
};
|
|
|
|
#if CYTHON_USE_TYPE_SPECS
|
|
static PyType_Slot __pyx_GeneratorType_slots[] = {
|
|
{Py_tp_dealloc, (void *)__Pyx_Coroutine_dealloc},
|
|
{Py_tp_traverse, (void *)__Pyx_Coroutine_traverse},
|
|
{Py_tp_iter, (void *)PyObject_SelfIter},
|
|
{Py_tp_iternext, (void *)__Pyx_Generator_Next},
|
|
{Py_tp_methods, (void *)__pyx_Generator_methods},
|
|
{Py_tp_members, (void *)__pyx_Generator_memberlist},
|
|
{Py_tp_getset, (void *)__pyx_Generator_getsets},
|
|
{Py_tp_getattro, (void *) __Pyx_PyObject_GenericGetAttrNoDict},
|
|
#if CYTHON_USE_TP_FINALIZE
|
|
{Py_tp_finalize, (void *)__Pyx_Coroutine_del},
|
|
#endif
|
|
{0, 0},
|
|
};
|
|
|
|
static PyType_Spec __pyx_GeneratorType_spec = {
|
|
__PYX_TYPE_MODULE_PREFIX "generator",
|
|
sizeof(__pyx_CoroutineObject),
|
|
0,
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
|
|
__pyx_GeneratorType_slots
|
|
};
|
|
#else /* CYTHON_USE_TYPE_SPECS */
|
|
|
|
static PyTypeObject __pyx_GeneratorType_type = {
|
|
PyVarObject_HEAD_INIT(0, 0)
|
|
__PYX_TYPE_MODULE_PREFIX "generator", /*tp_name*/
|
|
sizeof(__pyx_CoroutineObject), /*tp_basicsize*/
|
|
0, /*tp_itemsize*/
|
|
(destructor) __Pyx_Coroutine_dealloc,/*tp_dealloc*/
|
|
0, /*tp_print*/
|
|
0, /*tp_getattr*/
|
|
0, /*tp_setattr*/
|
|
0, /*tp_as_async*/
|
|
0, /*tp_repr*/
|
|
0, /*tp_as_number*/
|
|
0, /*tp_as_sequence*/
|
|
0, /*tp_as_mapping*/
|
|
0, /*tp_hash*/
|
|
0, /*tp_call*/
|
|
0, /*tp_str*/
|
|
0, /*tp_getattro*/
|
|
0, /*tp_setattro*/
|
|
0, /*tp_as_buffer*/
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
|
|
0, /*tp_doc*/
|
|
(traverseproc) __Pyx_Coroutine_traverse, /*tp_traverse*/
|
|
0, /*tp_clear*/
|
|
0, /*tp_richcompare*/
|
|
offsetof(__pyx_CoroutineObject, gi_weakreflist), /*tp_weaklistoffset*/
|
|
0, /*tp_iter*/
|
|
(iternextfunc) __Pyx_Generator_Next, /*tp_iternext*/
|
|
__pyx_Generator_methods, /*tp_methods*/
|
|
__pyx_Generator_memberlist, /*tp_members*/
|
|
__pyx_Generator_getsets, /*tp_getset*/
|
|
0, /*tp_base*/
|
|
0, /*tp_dict*/
|
|
0, /*tp_descr_get*/
|
|
0, /*tp_descr_set*/
|
|
0, /*tp_dictoffset*/
|
|
0, /*tp_init*/
|
|
0, /*tp_alloc*/
|
|
0, /*tp_new*/
|
|
0, /*tp_free*/
|
|
0, /*tp_is_gc*/
|
|
0, /*tp_bases*/
|
|
0, /*tp_mro*/
|
|
0, /*tp_cache*/
|
|
0, /*tp_subclasses*/
|
|
0, /*tp_weaklist*/
|
|
#if CYTHON_USE_TP_FINALIZE
|
|
0, /*tp_del*/
|
|
#else
|
|
__Pyx_Coroutine_del, /*tp_del*/
|
|
#endif
|
|
0, /*tp_version_tag*/
|
|
#if CYTHON_USE_TP_FINALIZE
|
|
__Pyx_Coroutine_del, /*tp_finalize*/
|
|
#elif PY_VERSION_HEX >= 0x030400a1
|
|
0, /*tp_finalize*/
|
|
#endif
|
|
#if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)
|
|
0, /*tp_vectorcall*/
|
|
#endif
|
|
#if __PYX_NEED_TP_PRINT_SLOT
|
|
0, /*tp_print*/
|
|
#endif
|
|
#if PY_VERSION_HEX >= 0x030C0000
|
|
0, /*tp_watched*/
|
|
#endif
|
|
#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
|
|
0, /*tp_pypy_flags*/
|
|
#endif
|
|
};
|
|
#endif /* CYTHON_USE_TYPE_SPECS */
|
|
|
|
static int __pyx_Generator_init(PyObject *module) {
|
|
#if CYTHON_USE_TYPE_SPECS
|
|
__pyx_GeneratorType = __Pyx_FetchCommonTypeFromSpec(module, &__pyx_GeneratorType_spec, NULL);
|
|
#else
|
|
CYTHON_UNUSED_VAR(module);
|
|
// on Windows, C-API functions can't be used in slots statically
|
|
__pyx_GeneratorType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict;
|
|
__pyx_GeneratorType_type.tp_iter = PyObject_SelfIter;
|
|
__pyx_GeneratorType = __Pyx_FetchCommonType(&__pyx_GeneratorType_type);
|
|
#endif
|
|
if (unlikely(!__pyx_GeneratorType)) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/////////////// ReturnWithStopIteration.proto ///////////////
|
|
|
|
#define __Pyx_ReturnWithStopIteration(value) \
|
|
if (value == Py_None) PyErr_SetNone(PyExc_StopIteration); else __Pyx__ReturnWithStopIteration(value)
|
|
static void __Pyx__ReturnWithStopIteration(PyObject* value); /*proto*/
|
|
|
|
/////////////// ReturnWithStopIteration ///////////////
|
|
//@requires: Exceptions.c::PyErrFetchRestore
|
|
//@requires: Exceptions.c::PyThreadStateGet
|
|
//@substitute: naming
|
|
|
|
// 1) Instantiating an exception just to pass back a value is costly.
|
|
// 2) CPython 3.12 cannot separate exception type and value
|
|
// 3) Passing a tuple as value into PyErr_SetObject() passes its items on as arguments.
|
|
// 4) Passing an exception as value will interpret it as an exception on unpacking and raise it (or unpack its value).
|
|
// 5) If there is currently an exception being handled, we need to chain it.
|
|
|
|
static void __Pyx__ReturnWithStopIteration(PyObject* value) {
|
|
PyObject *exc, *args;
|
|
#if CYTHON_COMPILING_IN_CPYTHON
|
|
__Pyx_PyThreadState_declare
|
|
if (PY_VERSION_HEX >= 0x030C00A6
|
|
|| unlikely(PyTuple_Check(value) || PyExceptionInstance_Check(value))) {
|
|
args = PyTuple_New(1);
|
|
if (unlikely(!args)) return;
|
|
Py_INCREF(value);
|
|
PyTuple_SET_ITEM(args, 0, value);
|
|
exc = PyType_Type.tp_call(PyExc_StopIteration, args, NULL);
|
|
Py_DECREF(args);
|
|
if (!exc) return;
|
|
} else {
|
|
// it's safe to avoid instantiating the exception
|
|
Py_INCREF(value);
|
|
exc = value;
|
|
}
|
|
#if CYTHON_FAST_THREAD_STATE
|
|
__Pyx_PyThreadState_assign
|
|
#if CYTHON_USE_EXC_INFO_STACK
|
|
if (!$local_tstate_cname->exc_info->exc_value)
|
|
#else
|
|
if (!$local_tstate_cname->exc_type)
|
|
#endif
|
|
{
|
|
// no chaining needed => avoid the overhead in PyErr_SetObject()
|
|
Py_INCREF(PyExc_StopIteration);
|
|
__Pyx_ErrRestore(PyExc_StopIteration, exc, NULL);
|
|
return;
|
|
}
|
|
#endif
|
|
#else
|
|
args = PyTuple_Pack(1, value);
|
|
if (unlikely(!args)) return;
|
|
exc = PyObject_Call(PyExc_StopIteration, args, NULL);
|
|
Py_DECREF(args);
|
|
if (unlikely(!exc)) return;
|
|
#endif
|
|
PyErr_SetObject(PyExc_StopIteration, exc);
|
|
Py_DECREF(exc);
|
|
}
|
|
|
|
|
|
//////////////////// PatchModuleWithCoroutine.proto ////////////////////
|
|
|
|
static PyObject* __Pyx_Coroutine_patch_module(PyObject* module, const char* py_code); /*proto*/
|
|
|
|
//////////////////// PatchModuleWithCoroutine ////////////////////
|
|
//@substitute: naming
|
|
|
|
static PyObject* __Pyx_Coroutine_patch_module(PyObject* module, const char* py_code) {
|
|
#if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED)
|
|
int result;
|
|
PyObject *globals, *result_obj;
|
|
globals = PyDict_New(); if (unlikely(!globals)) goto ignore;
|
|
result = PyDict_SetItemString(globals, "_cython_coroutine_type",
|
|
#ifdef __Pyx_Coroutine_USED
|
|
(PyObject*)__pyx_CoroutineType);
|
|
#else
|
|
Py_None);
|
|
#endif
|
|
if (unlikely(result < 0)) goto ignore;
|
|
result = PyDict_SetItemString(globals, "_cython_generator_type",
|
|
#ifdef __Pyx_Generator_USED
|
|
(PyObject*)__pyx_GeneratorType);
|
|
#else
|
|
Py_None);
|
|
#endif
|
|
if (unlikely(result < 0)) goto ignore;
|
|
if (unlikely(PyDict_SetItemString(globals, "_module", module) < 0)) goto ignore;
|
|
if (unlikely(PyDict_SetItemString(globals, "__builtins__", $builtins_cname) < 0)) goto ignore;
|
|
result_obj = PyRun_String(py_code, Py_file_input, globals, globals);
|
|
if (unlikely(!result_obj)) goto ignore;
|
|
Py_DECREF(result_obj);
|
|
Py_DECREF(globals);
|
|
return module;
|
|
|
|
ignore:
|
|
Py_XDECREF(globals);
|
|
PyErr_WriteUnraisable(module);
|
|
if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning, "Cython module failed to patch module with custom type", 1) < 0)) {
|
|
Py_DECREF(module);
|
|
module = NULL;
|
|
}
|
|
#else
|
|
// avoid "unused" warning
|
|
py_code++;
|
|
#endif
|
|
return module;
|
|
}
|
|
|
|
|
|
//////////////////// PatchGeneratorABC.proto ////////////////////
|
|
|
|
// register with Generator/Coroutine ABCs in 'collections.abc'
|
|
// see https://bugs.python.org/issue24018
|
|
static int __Pyx_patch_abc(void); /*proto*/
|
|
|
|
//////////////////// PatchGeneratorABC ////////////////////
|
|
//@requires: PatchModuleWithCoroutine
|
|
|
|
#ifndef CYTHON_REGISTER_ABCS
|
|
#define CYTHON_REGISTER_ABCS 1
|
|
#endif
|
|
|
|
#if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED)
|
|
static PyObject* __Pyx_patch_abc_module(PyObject *module); /*proto*/
|
|
static PyObject* __Pyx_patch_abc_module(PyObject *module) {
|
|
module = __Pyx_Coroutine_patch_module(
|
|
module, CSTRING("""\
|
|
if _cython_generator_type is not None:
|
|
try: Generator = _module.Generator
|
|
except AttributeError: pass
|
|
else: Generator.register(_cython_generator_type)
|
|
if _cython_coroutine_type is not None:
|
|
try: Coroutine = _module.Coroutine
|
|
except AttributeError: pass
|
|
else: Coroutine.register(_cython_coroutine_type)
|
|
""")
|
|
);
|
|
return module;
|
|
}
|
|
#endif
|
|
|
|
static int __Pyx_patch_abc(void) {
|
|
#if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED)
|
|
static int abc_patched = 0;
|
|
if (CYTHON_REGISTER_ABCS && !abc_patched) {
|
|
PyObject *module;
|
|
module = PyImport_ImportModule((PY_MAJOR_VERSION >= 3) ? "collections.abc" : "collections");
|
|
if (unlikely(!module)) {
|
|
PyErr_WriteUnraisable(NULL);
|
|
if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning,
|
|
((PY_MAJOR_VERSION >= 3) ?
|
|
"Cython module failed to register with collections.abc module" :
|
|
"Cython module failed to register with collections module"), 1) < 0)) {
|
|
return -1;
|
|
}
|
|
} else {
|
|
module = __Pyx_patch_abc_module(module);
|
|
abc_patched = 1;
|
|
if (unlikely(!module))
|
|
return -1;
|
|
Py_DECREF(module);
|
|
}
|
|
// also register with "backports_abc" module if available, just in case
|
|
module = PyImport_ImportModule("backports_abc");
|
|
if (module) {
|
|
module = __Pyx_patch_abc_module(module);
|
|
Py_XDECREF(module);
|
|
}
|
|
if (!module) {
|
|
PyErr_Clear();
|
|
}
|
|
}
|
|
#else
|
|
// avoid "unused" warning for __Pyx_Coroutine_patch_module()
|
|
if ((0)) __Pyx_Coroutine_patch_module(NULL, NULL);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
|
|
//////////////////// PatchAsyncIO.proto ////////////////////
|
|
|
|
// run after importing "asyncio" to patch Cython generator support into it
|
|
static PyObject* __Pyx_patch_asyncio(PyObject* module); /*proto*/
|
|
|
|
//////////////////// PatchAsyncIO ////////////////////
|
|
//@requires: ImportExport.c::Import
|
|
//@requires: PatchModuleWithCoroutine
|
|
//@requires: PatchInspect
|
|
|
|
static PyObject* __Pyx_patch_asyncio(PyObject* module) {
|
|
#if PY_VERSION_HEX < 0x030500B2 && \
|
|
(defined(__Pyx_Coroutine_USED) || defined(__Pyx_Generator_USED)) && \
|
|
(!defined(CYTHON_PATCH_ASYNCIO) || CYTHON_PATCH_ASYNCIO)
|
|
PyObject *patch_module = NULL;
|
|
static int asyncio_patched = 0;
|
|
if (unlikely((!asyncio_patched) && module)) {
|
|
PyObject *package;
|
|
package = __Pyx_Import(PYIDENT("asyncio.coroutines"), NULL, 0);
|
|
if (package) {
|
|
patch_module = __Pyx_Coroutine_patch_module(
|
|
PyObject_GetAttrString(package, "coroutines"), CSTRING("""\
|
|
try:
|
|
coro_types = _module._COROUTINE_TYPES
|
|
except AttributeError: pass
|
|
else:
|
|
if _cython_coroutine_type is not None and _cython_coroutine_type not in coro_types:
|
|
coro_types = tuple(coro_types) + (_cython_coroutine_type,)
|
|
if _cython_generator_type is not None and _cython_generator_type not in coro_types:
|
|
coro_types = tuple(coro_types) + (_cython_generator_type,)
|
|
_module._COROUTINE_TYPES = coro_types
|
|
""")
|
|
);
|
|
} else {
|
|
PyErr_Clear();
|
|
// Always enable fallback: even if we compile against 3.4.2, we might be running on 3.4.1 at some point.
|
|
//#if PY_VERSION_HEX < 0x03040200
|
|
// Py3.4.1 used to have asyncio.tasks instead of asyncio.coroutines
|
|
package = __Pyx_Import(PYIDENT("asyncio.tasks"), NULL, 0);
|
|
if (unlikely(!package)) goto asyncio_done;
|
|
patch_module = __Pyx_Coroutine_patch_module(
|
|
PyObject_GetAttrString(package, "tasks"), CSTRING("""\
|
|
if hasattr(_module, 'iscoroutine'):
|
|
old_types = getattr(_module.iscoroutine, '_cython_coroutine_types', None)
|
|
if old_types is None or not isinstance(old_types, set):
|
|
old_types = set()
|
|
def cy_wrap(orig_func, type=type, cython_coroutine_types=old_types):
|
|
def cy_iscoroutine(obj): return type(obj) in cython_coroutine_types or orig_func(obj)
|
|
cy_iscoroutine._cython_coroutine_types = cython_coroutine_types
|
|
return cy_iscoroutine
|
|
_module.iscoroutine = cy_wrap(_module.iscoroutine)
|
|
if _cython_coroutine_type is not None:
|
|
old_types.add(_cython_coroutine_type)
|
|
if _cython_generator_type is not None:
|
|
old_types.add(_cython_generator_type)
|
|
""")
|
|
);
|
|
//#endif
|
|
// Py < 0x03040200
|
|
}
|
|
Py_DECREF(package);
|
|
if (unlikely(!patch_module)) goto ignore;
|
|
//#if PY_VERSION_HEX < 0x03040200
|
|
asyncio_done:
|
|
PyErr_Clear();
|
|
//#endif
|
|
asyncio_patched = 1;
|
|
#ifdef __Pyx_Generator_USED
|
|
// now patch inspect.isgenerator() by looking up the imported module in the patched asyncio module
|
|
{
|
|
PyObject *inspect_module;
|
|
if (patch_module) {
|
|
inspect_module = PyObject_GetAttr(patch_module, PYIDENT("inspect"));
|
|
Py_DECREF(patch_module);
|
|
} else {
|
|
inspect_module = __Pyx_Import(PYIDENT("inspect"), NULL, 0);
|
|
}
|
|
if (unlikely(!inspect_module)) goto ignore;
|
|
inspect_module = __Pyx_patch_inspect(inspect_module);
|
|
if (unlikely(!inspect_module)) {
|
|
Py_DECREF(module);
|
|
module = NULL;
|
|
}
|
|
Py_XDECREF(inspect_module);
|
|
}
|
|
#else
|
|
// avoid "unused" warning for __Pyx_patch_inspect()
|
|
if ((0)) return __Pyx_patch_inspect(module);
|
|
#endif
|
|
}
|
|
return module;
|
|
ignore:
|
|
PyErr_WriteUnraisable(module);
|
|
if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning, "Cython module failed to patch asyncio package with custom generator type", 1) < 0)) {
|
|
Py_DECREF(module);
|
|
module = NULL;
|
|
}
|
|
#else
|
|
// avoid "unused" warning for __Pyx_Coroutine_patch_module()
|
|
if ((0)) return __Pyx_patch_inspect(__Pyx_Coroutine_patch_module(module, NULL));
|
|
#endif
|
|
return module;
|
|
}
|
|
|
|
|
|
//////////////////// PatchInspect.proto ////////////////////
|
|
|
|
// run after importing "inspect" to patch Cython generator support into it
|
|
static PyObject* __Pyx_patch_inspect(PyObject* module); /*proto*/
|
|
|
|
//////////////////// PatchInspect ////////////////////
|
|
//@requires: PatchModuleWithCoroutine
|
|
|
|
static PyObject* __Pyx_patch_inspect(PyObject* module) {
|
|
#if defined(__Pyx_Generator_USED) && (!defined(CYTHON_PATCH_INSPECT) || CYTHON_PATCH_INSPECT)
|
|
static int inspect_patched = 0;
|
|
if (unlikely((!inspect_patched) && module)) {
|
|
module = __Pyx_Coroutine_patch_module(
|
|
module, CSTRING("""\
|
|
old_types = getattr(_module.isgenerator, '_cython_generator_types', None)
|
|
if old_types is None or not isinstance(old_types, set):
|
|
old_types = set()
|
|
def cy_wrap(orig_func, type=type, cython_generator_types=old_types):
|
|
def cy_isgenerator(obj): return type(obj) in cython_generator_types or orig_func(obj)
|
|
cy_isgenerator._cython_generator_types = cython_generator_types
|
|
return cy_isgenerator
|
|
_module.isgenerator = cy_wrap(_module.isgenerator)
|
|
old_types.add(_cython_generator_type)
|
|
""")
|
|
);
|
|
inspect_patched = 1;
|
|
}
|
|
#else
|
|
// avoid "unused" warning for __Pyx_Coroutine_patch_module()
|
|
if ((0)) return __Pyx_Coroutine_patch_module(module, NULL);
|
|
#endif
|
|
return module;
|
|
}
|
|
|
|
|
|
//////////////////// StopAsyncIteration.proto ////////////////////
|
|
|
|
#define __Pyx_StopAsyncIteration_USED
|
|
static PyObject *__Pyx_PyExc_StopAsyncIteration;
|
|
static int __pyx_StopAsyncIteration_init(PyObject *module); /*proto*/
|
|
|
|
//////////////////// StopAsyncIteration ////////////////////
|
|
|
|
#if PY_VERSION_HEX < 0x030500B1
|
|
#if CYTHON_USE_TYPE_SPECS
|
|
#error Using async coroutines with type specs requires Python 3.5 or later.
|
|
#else
|
|
|
|
static PyTypeObject __Pyx__PyExc_StopAsyncIteration_type = {
|
|
PyVarObject_HEAD_INIT(0, 0)
|
|
"StopAsyncIteration", /*tp_name*/
|
|
sizeof(PyBaseExceptionObject), /*tp_basicsize*/
|
|
0, /*tp_itemsize*/
|
|
0, /*tp_dealloc*/
|
|
0, /*tp_print*/
|
|
0, /*tp_getattr*/
|
|
0, /*tp_setattr*/
|
|
0, /*tp_compare / reserved*/
|
|
0, /*tp_repr*/
|
|
0, /*tp_as_number*/
|
|
0, /*tp_as_sequence*/
|
|
0, /*tp_as_mapping*/
|
|
0, /*tp_hash*/
|
|
0, /*tp_call*/
|
|
0, /*tp_str*/
|
|
0, /*tp_getattro*/
|
|
0, /*tp_setattro*/
|
|
0, /*tp_as_buffer*/
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
|
|
PyDoc_STR("Signal the end from iterator.__anext__()."), /*tp_doc*/
|
|
0, /*tp_traverse*/
|
|
0, /*tp_clear*/
|
|
0, /*tp_richcompare*/
|
|
0, /*tp_weaklistoffset*/
|
|
0, /*tp_iter*/
|
|
0, /*tp_iternext*/
|
|
0, /*tp_methods*/
|
|
0, /*tp_members*/
|
|
0, /*tp_getset*/
|
|
0, /*tp_base*/
|
|
0, /*tp_dict*/
|
|
0, /*tp_descr_get*/
|
|
0, /*tp_descr_set*/
|
|
0, /*tp_dictoffset*/
|
|
0, /*tp_init*/
|
|
0, /*tp_alloc*/
|
|
0, /*tp_new*/
|
|
0, /*tp_free*/
|
|
0, /*tp_is_gc*/
|
|
0, /*tp_bases*/
|
|
0, /*tp_mro*/
|
|
0, /*tp_cache*/
|
|
0, /*tp_subclasses*/
|
|
0, /*tp_weaklist*/
|
|
0, /*tp_del*/
|
|
0, /*tp_version_tag*/
|
|
#if PY_VERSION_HEX >= 0x030400a1
|
|
0, /*tp_finalize*/
|
|
#endif
|
|
#if CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM+0 >= 0x06000000
|
|
0, /*tp_pypy_flags*/
|
|
#endif
|
|
};
|
|
#endif
|
|
#endif
|
|
|
|
static int __pyx_StopAsyncIteration_init(PyObject *module) {
|
|
CYTHON_UNUSED_VAR(module);
|
|
#if PY_VERSION_HEX >= 0x030500B1
|
|
__Pyx_PyExc_StopAsyncIteration = PyExc_StopAsyncIteration;
|
|
#else
|
|
PyObject *builtins = PyEval_GetBuiltins();
|
|
if (likely(builtins)) {
|
|
PyObject *exc = PyMapping_GetItemString(builtins, (char*) "StopAsyncIteration");
|
|
if (exc) {
|
|
__Pyx_PyExc_StopAsyncIteration = exc;
|
|
return 0;
|
|
}
|
|
}
|
|
PyErr_Clear();
|
|
|
|
__Pyx__PyExc_StopAsyncIteration_type.tp_traverse = ((PyTypeObject*)PyExc_BaseException)->tp_traverse;
|
|
__Pyx__PyExc_StopAsyncIteration_type.tp_clear = ((PyTypeObject*)PyExc_BaseException)->tp_clear;
|
|
__Pyx__PyExc_StopAsyncIteration_type.tp_dictoffset = ((PyTypeObject*)PyExc_BaseException)->tp_dictoffset;
|
|
__Pyx__PyExc_StopAsyncIteration_type.tp_base = (PyTypeObject*)PyExc_Exception;
|
|
|
|
__Pyx_PyExc_StopAsyncIteration = (PyObject*) __Pyx_FetchCommonType(&__Pyx__PyExc_StopAsyncIteration_type);
|
|
if (unlikely(!__Pyx_PyExc_StopAsyncIteration))
|
|
return -1;
|
|
if (likely(builtins) && unlikely(PyMapping_SetItemString(builtins, (char*) "StopAsyncIteration", __Pyx_PyExc_StopAsyncIteration) < 0))
|
|
return -1;
|
|
#endif
|
|
return 0;
|
|
}
|