Spaces:
Runtime error
Runtime error
| //////////////////// 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; | |
| 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 | |
| { | |
| 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 | |
| { | |
| source_gen = PyObject_GetIter(source); | |
| if (unlikely(!source_gen)) | |
| return NULL; | |
| } | |
| // source_gen is now the iterator, make the first next() call | |
| retval = Py_TYPE(source_gen)->tp_iternext(source_gen); | |
| retval = PyIter_Next(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 = Py_TYPE(source_gen)->tp_iternext(source_gen); | |
| retval = PyIter_Next(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); | |
| // inlined "__pyx_PyAsyncGenASend" handling to avoid the series of generic calls | |
| } else if (__pyx_PyAsyncGenASend_CheckExact(source)) { | |
| retval = __Pyx_async_gen_asend_iternext(source); | |
| } 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) { | |
| if (__Pyx_Coroutine_Check(o)) { | |
| return __Pyx_NewRef(o); | |
| } | |
| return __Pyx__Coroutine_GetAwaitableIter(o); | |
| } | |
| static void __Pyx_Coroutine_AwaitableIterError(PyObject *source) { | |
| _PyErr_FormatFromCause( | |
| PyExc_TypeError, | |
| "'async for' received an invalid object " | |
| "from __anext__: %.100s", | |
| Py_TYPE(source)->tp_name); | |
| 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); | |
| // since Py2 does not have exception chaining, it's better to avoid shadowing exceptions there | |
| source++; | |
| } | |
| // adapted from genobject.c in Py3.5 | |
| static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *obj) { | |
| PyObject *res; | |
| __Pyx_PyAsyncMethodsStruct* am = __Pyx_PyType_AsAsync(obj); | |
| if (likely(am && am->am_await)) { | |
| res = (*am->am_await)(obj); | |
| } else | |
| if (PyCoro_CheckExact(obj)) { | |
| return __Pyx_NewRef(obj); | |
| } else | |
| 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 | |
| { | |
| 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))) { | |
| PyErr_Format(PyExc_TypeError, | |
| "__await__() returned non-iterator of type '%.100s'", | |
| Py_TYPE(res)->tp_name); | |
| Py_CLEAR(res); | |
| } else { | |
| int is_coroutine = 0; | |
| is_coroutine |= __Pyx_Coroutine_Check(res); | |
| is_coroutine |= PyCoro_CheckExact(res); | |
| 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(PyExc_TypeError, | |
| "object %.100s can't be used in 'await' expression", | |
| Py_TYPE(obj)->tp_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) { | |
| { | |
| 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; | |
| } | |
| // avoid C warning about 'unused function' | |
| if ((0)) (void) __Pyx_PyObject_CallMethod0(obj, PYIDENT("__aiter__")); | |
| PyErr_Format(PyExc_TypeError, "'async for' requires an object with __aiter__ method, got %.100s", | |
| Py_TYPE(obj)->tp_name); | |
| return NULL; | |
| } | |
| static CYTHON_INLINE PyObject *__Pyx_Coroutine_GetAsyncIter(PyObject *obj) { | |
| if (__Pyx_AsyncGen_CheckExact(obj)) { | |
| return __Pyx_NewRef(obj); | |
| } | |
| { | |
| __Pyx_PyAsyncMethodsStruct* am = __Pyx_PyType_AsAsync(obj); | |
| if (likely(am && am->am_aiter)) { | |
| return (*am->am_aiter)(obj); | |
| } | |
| } | |
| return __Pyx_Coroutine_GetAsyncIter_Generic(obj); | |
| } | |
| static PyObject *__Pyx__Coroutine_AsyncIterNext(PyObject *obj) { | |
| { | |
| 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)) | |
| PyErr_Format(PyExc_TypeError, "'async for' requires an object with __anext__ method, got %.100s", | |
| Py_TYPE(obj)->tp_name); | |
| return NULL; | |
| } | |
| static CYTHON_INLINE PyObject *__Pyx_Coroutine_AsyncIterNext(PyObject *obj) { | |
| if (__Pyx_AsyncGen_CheckExact(obj)) { | |
| return __Pyx_async_gen_anext(obj); | |
| } | |
| { | |
| __Pyx_PyAsyncMethodsStruct* am = __Pyx_PyType_AsAsync(obj); | |
| if (likely(am && am->am_anext)) { | |
| return (*am->am_anext)(obj); | |
| } | |
| } | |
| 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(CYTHON_UNUSED int in_async_gen) { | |
| PyObject *exc, *val, *tb, *cur_exc; | |
| __Pyx_PyThreadState_declare | |
| int is_async_stopiteration = 0; | |
| cur_exc = PyErr_Occurred(); | |
| if (likely(!__Pyx_PyErr_GivenExceptionMatches(cur_exc, PyExc_StopIteration))) { | |
| if (in_async_gen && unlikely(__Pyx_PyErr_GivenExceptionMatches(cur_exc, __Pyx_PyExc_StopAsyncIteration))) { | |
| is_async_stopiteration = 1; | |
| } else | |
| 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, | |
| is_async_stopiteration ? "async generator raised StopAsyncIteration" : | |
| in_async_gen ? "async generator raised StopIteration" : | |
| "generator raised StopIteration"); | |
| } | |
| //////////////////// CoroutineBase.proto //////////////////// | |
| //@substitute: naming | |
| typedef PyObject *(*__pyx_coroutine_body_t)(PyObject *, PyThreadState *, PyObject *); | |
| // See https://bugs.python.org/issue25612 | |
| // 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; | |
| typedef struct { | |
| 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 | |
| static int __Pyx_PyGen__FetchStopIterationValue(PyThreadState *tstate, PyObject **pvalue); /*proto*/ | |
| static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__Pyx_ExcInfoStruct *exc_state); /*proto*/ | |
| //////////////////// Coroutine.proto //////////////////// | |
| static PyTypeObject *__pyx_CoroutineType = 0; | |
| static PyTypeObject *__pyx_CoroutineAwaitType = 0; | |
| // __Pyx_Coroutine_Check(obj): see override for IterableCoroutine below | |
| static int __pyx_Coroutine_init(void); /*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 //////////////////// | |
| static PyTypeObject *__pyx_GeneratorType = 0; | |
| static PyObject *__Pyx_Generator_Next(PyObject *self); | |
| static int __pyx_Generator_init(void); /*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::PyObjectGetAttrStr | |
| //@requires: CommonStructures.c::FetchCommonType | |
| // 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(CYTHON_UNUSED PyThreadState *$local_tstate_cname, PyObject **pvalue) { | |
| PyObject *et, *ev, *tb; | |
| PyObject *value = NULL; | |
| __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; | |
| } | |
| else if (Py_TYPE(ev) == (PyTypeObject*)PyExc_StopIteration) { | |
| value = ((PyStopIterationObject *)ev)->value; | |
| Py_INCREF(value); | |
| Py_DECREF(ev); | |
| } | |
| // 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) { | |
| value = PyTuple_GET_ITEM(ev, 0); | |
| Py_INCREF(value); | |
| value = PySequence_ITEM(ev, 0); | |
| } 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); | |
| value = ((PyStopIterationObject *)ev)->value; | |
| Py_INCREF(value); | |
| Py_DECREF(ev); | |
| { | |
| 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; | |
| } | |
| } | |
| *pvalue = value; | |
| return 0; | |
| } | |
| static CYTHON_INLINE | |
| void __Pyx_Coroutine_ExceptionClear(__Pyx_ExcInfoStruct *exc_state) { | |
| 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); | |
| } | |
| static void __Pyx__Coroutine_AlreadyRunningError(CYTHON_UNUSED __pyx_CoroutineObject *gen) { | |
| const char *msg; | |
| if ((0)) { | |
| } else if (__Pyx_Coroutine_Check((PyObject*)gen)) { | |
| msg = "coroutine already executing"; | |
| } else if (__Pyx_AsyncGen_CheckExact((PyObject*)gen)) { | |
| msg = "async generator already executing"; | |
| } else { | |
| msg = "generator already executing"; | |
| } | |
| PyErr_SetString(PyExc_ValueError, msg); | |
| } | |
| static void __Pyx__Coroutine_NotStartedError(CYTHON_UNUSED PyObject *gen) { | |
| const char *msg; | |
| if ((0)) { | |
| } else if (__Pyx_Coroutine_Check(gen)) { | |
| msg = "can't send non-None value to a just-started coroutine"; | |
| } else if (__Pyx_AsyncGen_CheckExact(gen)) { | |
| msg = "can't send non-None value to a just-started async generator"; | |
| } else { | |
| msg = "can't send non-None value to a just-started generator"; | |
| } | |
| PyErr_SetString(PyExc_TypeError, msg); | |
| } | |
| static void __Pyx__Coroutine_AlreadyTerminatedError(CYTHON_UNUSED PyObject *gen, PyObject *value, CYTHON_UNUSED int closing) { | |
| 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 | |
| if (value) { | |
| // `gen` is an exhausted generator: | |
| // only set exception if called from send(). | |
| if (__Pyx_AsyncGen_CheckExact(gen)) | |
| PyErr_SetNone(__Pyx_PyExc_StopAsyncIteration); | |
| else | |
| 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); | |
| } | |
| __Pyx_PyThreadState_assign | |
| tstate = $local_tstate_cname; | |
| tstate = __Pyx_PyThreadState_Current; | |
| // 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_type) { | |
| // FIXME: what to do in PyPy? | |
| // Generators always return to their most recent caller, not | |
| // necessarily their creator. | |
| if (exc_state->exc_traceback) { | |
| PyTracebackObject *tb = (PyTracebackObject *) exc_state->exc_traceback; | |
| PyFrameObject *f = tb->tb_frame; | |
| assert(f->f_back == NULL); | |
| // 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); | |
| Py_XINCREF(tstate->frame); | |
| f->f_back = tstate->frame; | |
| } | |
| } | |
| // See https://bugs.python.org/issue25612 | |
| exc_state->previous_item = tstate->exc_info; | |
| tstate->exc_info = exc_state; | |
| 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); | |
| } | |
| self->is_running = 1; | |
| retval = self->body((PyObject *) self, tstate, value); | |
| self->is_running = 0; | |
| // 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); | |
| 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. | |
| PyObject *exc_tb = exc_state->exc_traceback; | |
| if (likely(exc_tb)) { | |
| // FIXME: what to do in PyPy? | |
| PyTracebackObject *tb = (PyTracebackObject *) exc_tb; | |
| PyFrameObject *f = tb->tb_frame; | |
| Py_CLEAR(f->f_back); | |
| } | |
| } | |
| static CYTHON_INLINE | |
| PyObject *__Pyx_Coroutine_MethodReturn(CYTHON_UNUSED PyObject* gen, PyObject *retval) { | |
| 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; | |
| if (__Pyx_AsyncGen_CheckExact(gen)) | |
| exc = __Pyx_PyExc_StopAsyncIteration; | |
| __Pyx_PyErr_SetNone(exc); | |
| } | |
| } | |
| return retval; | |
| } | |
| static CYTHON_INLINE | |
| PyObject *__Pyx_PyGen_Send(PyGenObject *gen, PyObject *arg) { | |
| return _PyGen_Send(gen, arg); | |
| 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 { | |
| _PyGen_SetStopIterationValue(result); | |
| } | |
| Py_CLEAR(result); | |
| } | |
| return result; | |
| } | |
| 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; | |
| if (__Pyx_Generator_CheckExact(yf)) { | |
| ret = __Pyx_Coroutine_Send(yf, value); | |
| } else | |
| if (__Pyx_Coroutine_Check(yf)) { | |
| ret = __Pyx_Coroutine_Send(yf, value); | |
| } else | |
| if (__pyx_PyAsyncGenASend_CheckExact(yf)) { | |
| ret = __Pyx_async_gen_asend_send(yf, value); | |
| } else | |
| // _PyGen_Send() is not exported before Py3.6 | |
| if (PyGen_CheckExact(yf)) { | |
| ret = __Pyx_PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value); | |
| } else | |
| // _PyGen_Send() is not exported before Py3.6 | |
| if (PyCoro_CheckExact(yf)) { | |
| ret = __Pyx_PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value); | |
| } else | |
| { | |
| if (value == Py_None) | |
| ret = Py_TYPE(yf)->tp_iternext(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; | |
| if (__Pyx_Generator_CheckExact(yf)) { | |
| retval = __Pyx_Coroutine_Close(yf); | |
| if (!retval) | |
| return -1; | |
| } else | |
| 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 | |
| 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 | |
| { | |
| PyObject *meth; | |
| gen->is_running = 1; | |
| meth = __Pyx_PyObject_GetAttrStr(yf, PYIDENT("close")); | |
| if (unlikely(!meth)) { | |
| if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { | |
| PyErr_WriteUnraisable(yf); | |
| } | |
| PyErr_Clear(); | |
| } else { | |
| retval = PyObject_CallFunction(meth, NULL); | |
| Py_DECREF(meth); | |
| if (!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; | |
| if (__Pyx_Generator_CheckExact(yf)) { | |
| ret = __Pyx_Generator_Next(yf); | |
| } else | |
| // _PyGen_Send() is not exported before Py3.6 | |
| if (PyGen_CheckExact(yf)) { | |
| ret = __Pyx_PyGen_Send((PyGenObject*)yf, NULL); | |
| } else | |
| if (__Pyx_Coroutine_Check(yf)) { | |
| ret = __Pyx_Coroutine_Send(yf, Py_None); | |
| } else | |
| ret = Py_TYPE(yf)->tp_iternext(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, CYTHON_UNUSED PyObject *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)) { | |
| } else if (__Pyx_Coroutine_Check(self)) { | |
| msg = "coroutine ignored GeneratorExit"; | |
| } else if (__Pyx_AsyncGen_CheckExact(self)) { | |
| msg = "async generator ignored GeneratorExit - might require Python 3.6+ finalisation (PEP 525)"; | |
| msg = "async generator ignored GeneratorExit"; | |
| } 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 | |
| || __Pyx_Generator_CheckExact(yf) | |
| || __Pyx_Coroutine_Check(yf) | |
| ) { | |
| ret = __Pyx__Coroutine_Throw(yf, typ, val, tb, args, close_on_genexit); | |
| } else if (__Pyx_CoroutineAwait_CheckExact(yf)) { | |
| ret = __Pyx__Coroutine_Throw(((__pyx_CoroutineAwaitObject*)yf)->coroutine, typ, val, tb, args, close_on_genexit); | |
| } else { | |
| PyObject *meth = __Pyx_PyObject_GetAttrStr(yf, PYIDENT("throw")); | |
| if (unlikely(!meth)) { | |
| Py_DECREF(yf); | |
| if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { | |
| gen->is_running = 0; | |
| return NULL; | |
| } | |
| PyErr_Clear(); | |
| __Pyx_Coroutine_Undelegate(gen); | |
| gen->is_running = 0; | |
| goto throw_here; | |
| } | |
| if (likely(args)) { | |
| ret = PyObject_CallObject(meth, args); | |
| } else { | |
| // "tb" or even "val" might be NULL, but that also correctly terminates the argument list | |
| ret = PyObject_CallFunctionObjArgs(meth, typ, val, tb, NULL); | |
| } | |
| 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 (!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) { | |
| Py_VISIT(exc_state->exc_type); | |
| Py_VISIT(exc_state->exc_value); | |
| Py_VISIT(exc_state->exc_traceback); | |
| 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); | |
| if (__Pyx_AsyncGen_CheckExact(self)) { | |
| Py_CLEAR(((__pyx_PyAsyncGenObject*)gen)->ag_finalizer); | |
| } | |
| 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 (PyObject_CallFinalizerFromDealloc(self)) | |
| Py_TYPE(gen)->tp_del(self); | |
| if (Py_REFCNT(self) > 0) | |
| { | |
| // resurrected. :( | |
| return; | |
| } | |
| PyObject_GC_UnTrack(self); | |
| } | |
| 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); | |
| } | |
| __Pyx_Coroutine_clear(self); | |
| PyObject_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; | |
| } | |
| // Temporarily resurrect the object. | |
| assert(self->ob_refcnt == 0); | |
| __Pyx_SET_REFCNT(self, 1); | |
| __Pyx_PyThreadState_assign | |
| // Save the current exception, if any. | |
| __Pyx_ErrFetch(&error_type, &error_value, &error_traceback); | |
| 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; | |
| } | |
| } | |
| if (unlikely(gen->resume_label == 0 && !error_value)) { | |
| // only warn about (async) coroutines | |
| if (!__Pyx_Generator_CheckExact(self)) | |
| { | |
| // untrack dead object as we are executing Python code (which might trigger GC) | |
| PyObject_GC_UnTrack(self); | |
| if (unlikely(PyErr_WarnFormat(PyExc_RuntimeWarning, 1, "coroutine '%.50S' was never awaited", gen->gi_qualname) < 0)) | |
| PyErr_WriteUnraisable(self); | |
| {PyObject *msg; | |
| char *cmsg; | |
| msg = NULL; | |
| cmsg = (char*) "coroutine was never awaited"; | |
| 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); | |
| } | |
| if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning, cmsg, 1) < 0)) | |
| PyErr_WriteUnraisable(self); | |
| Py_XDECREF(msg);} | |
| PyObject_GC_Track(self); | |
| } | |
| } 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); | |
| // Undo the temporary resurrection; can't use DECREF here, it would | |
| // cause a recursive call. | |
| assert(Py_REFCNT(self) > 0); | |
| if (--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); | |
| } | |
| 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; | |
| // 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. | |
| --Py_TYPE(self)->tp_frees; | |
| --Py_TYPE(self)->tp_allocs; | |
| } | |
| static PyObject * | |
| __Pyx_Coroutine_get_name(__pyx_CoroutineObject *self, CYTHON_UNUSED void *context) | |
| { | |
| PyObject *name = self->gi_name; | |
| // 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, CYTHON_UNUSED void *context) | |
| { | |
| PyObject *tmp; | |
| if (unlikely(value == NULL || !PyUnicode_Check(value))) | |
| if (unlikely(value == NULL || !PyString_Check(value))) | |
| { | |
| PyErr_SetString(PyExc_TypeError, | |
| "__name__ must be set to a string object"); | |
| return -1; | |
| } | |
| tmp = self->gi_name; | |
| Py_INCREF(value); | |
| self->gi_name = value; | |
| Py_XDECREF(tmp); | |
| return 0; | |
| } | |
| static PyObject * | |
| __Pyx_Coroutine_get_qualname(__pyx_CoroutineObject *self, CYTHON_UNUSED void *context) | |
| { | |
| PyObject *name = self->gi_qualname; | |
| // 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, CYTHON_UNUSED void *context) | |
| { | |
| PyObject *tmp; | |
| if (unlikely(value == NULL || !PyUnicode_Check(value))) | |
| if (unlikely(value == NULL || !PyString_Check(value))) | |
| { | |
| PyErr_SetString(PyExc_TypeError, | |
| "__qualname__ must be set to a string object"); | |
| return -1; | |
| } | |
| tmp = self->gi_qualname; | |
| Py_INCREF(value); | |
| self->gi_qualname = value; | |
| Py_XDECREF(tmp); | |
| return 0; | |
| } | |
| static PyObject * | |
| __Pyx_Coroutine_get_frame(__pyx_CoroutineObject *self, CYTHON_UNUSED void *context) | |
| { | |
| PyObject *frame = self->gi_frame; | |
| 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; | |
| gen->gi_exc_state.exc_type = NULL; | |
| gen->gi_exc_state.exc_value = NULL; | |
| gen->gi_exc_state.exc_traceback = NULL; | |
| gen->gi_exc_state.previous_item = NULL; | |
| 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); | |
| PyObject_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, CYTHON_UNUSED PyObject *arg) { | |
| return __Pyx_Coroutine_Close(self->coroutine); | |
| } | |
| static PyObject *__Pyx_CoroutineAwait_self(PyObject *self) { | |
| Py_INCREF(self); | |
| return self; | |
| } | |
| static PyObject *__Pyx_CoroutineAwait_no_new(CYTHON_UNUSED PyTypeObject *type, CYTHON_UNUSED PyObject *args, CYTHON_UNUSED PyObject *kwargs) { | |
| PyErr_SetString(PyExc_TypeError, "cannot instantiate type, use 'await coroutine' instead"); | |
| return NULL; | |
| } | |
| 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.")}, | |
| {0, 0, 0, 0} | |
| }; | |
| static PyTypeObject __pyx_CoroutineAwaitType_type = { | |
| PyVarObject_HEAD_INIT(0, 0) | |
| "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*/ | |
| __Pyx_CoroutineAwait_no_new, /*tp_new*/ | |
| 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*/ | |
| 0, /*tp_finalize*/ | |
| 0, /*tp_vectorcall*/ | |
| 0, /*tp_print*/ | |
| 0, /*tp_pypy_flags*/ | |
| }; | |
| 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; | |
| } | |
| static PyObject *__Pyx_Coroutine_await_method(PyObject *coroutine, CYTHON_UNUSED PyObject *arg) { | |
| return __Pyx__Coroutine_await(coroutine); | |
| } | |
| 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); | |
| } | |
| 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; | |
| } | |
| 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.")}, | |
| {"__await__", (PyCFunction) __Pyx_Coroutine_await_method, METH_NOARGS, | |
| (char*) PyDoc_STR("__await__() -> return an iterator to be used in await expression.")}, | |
| {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), PY_WRITE_RESTRICTED, 0}, | |
| {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} | |
| }; | |
| static __Pyx_PyAsyncMethodsStruct __pyx_Coroutine_as_async = { | |
| __Pyx_Coroutine_await, /*am_await*/ | |
| 0, /*am_aiter*/ | |
| 0, /*am_anext*/ | |
| 0, /*am_send*/ | |
| }; | |
| static PyTypeObject __pyx_CoroutineType_type = { | |
| PyVarObject_HEAD_INIT(0, 0) | |
| "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*/ | |
| &__pyx_Coroutine_as_async, /*tp_as_async (tp_reserved) - Py3 only! */ | |
| 0, /*tp_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_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ | |
| 0, /*tp_doc*/ | |
| (traverseproc) __Pyx_Coroutine_traverse, /*tp_traverse*/ | |
| 0, /*tp_clear*/ | |
| // in order to (mis-)use tp_reserved above, we must also implement tp_richcompare | |
| __Pyx_Coroutine_compare, /*tp_richcompare*/ | |
| 0, /*tp_richcompare*/ | |
| 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*/ | |
| 0, /*tp_del*/ | |
| __Pyx_Coroutine_del, /*tp_del*/ | |
| 0, /*tp_version_tag*/ | |
| __Pyx_Coroutine_del, /*tp_finalize*/ | |
| 0, /*tp_finalize*/ | |
| 0, /*tp_vectorcall*/ | |
| 0, /*tp_print*/ | |
| 0, /*tp_pypy_flags*/ | |
| }; | |
| static int __pyx_Coroutine_init(void) { | |
| // on Windows, C-API functions can't be used in slots statically | |
| __pyx_CoroutineType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict; | |
| __pyx_CoroutineType = __Pyx_FetchCommonType(&__pyx_CoroutineType_type); | |
| if (unlikely(!__pyx_CoroutineType)) | |
| return -1; | |
| if (unlikely(__pyx_IterableCoroutine_init() == -1)) | |
| return -1; | |
| __pyx_CoroutineAwaitType = __Pyx_FetchCommonType(&__pyx_CoroutineAwaitType_type); | |
| if (unlikely(!__pyx_CoroutineAwaitType)) | |
| return -1; | |
| return 0; | |
| } | |
| //////////////////// IterableCoroutine.proto //////////////////// | |
| static PyTypeObject *__pyx_IterableCoroutineType = 0; | |
| static int __pyx_IterableCoroutine_init(void);/*proto*/ | |
| //////////////////// IterableCoroutine //////////////////// | |
| //@requires: Coroutine | |
| //@requires: CommonStructures.c::FetchCommonType | |
| static PyTypeObject __pyx_IterableCoroutineType_type = { | |
| PyVarObject_HEAD_INIT(0, 0) | |
| "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*/ | |
| &__pyx_Coroutine_as_async, /*tp_as_async (tp_reserved) - Py3 only! */ | |
| 0, /*tp_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_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ | |
| 0, /*tp_doc*/ | |
| (traverseproc) __Pyx_Coroutine_traverse, /*tp_traverse*/ | |
| 0, /*tp_clear*/ | |
| // in order to (mis-)use tp_reserved above, we must also implement tp_richcompare | |
| __Pyx_Coroutine_compare, /*tp_richcompare*/ | |
| 0, /*tp_richcompare*/ | |
| 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*/ | |
| 0, /*tp_del*/ | |
| __Pyx_Coroutine_del, /*tp_del*/ | |
| 0, /*tp_version_tag*/ | |
| __Pyx_Coroutine_del, /*tp_finalize*/ | |
| 0, /*tp_vectorcall*/ | |
| 0, /*tp_print*/ | |
| 0, /*tp_pypy_flags*/ | |
| }; | |
| static int __pyx_IterableCoroutine_init(void) { | |
| __pyx_IterableCoroutineType_type.tp_getattro = __Pyx_PyObject_GenericGetAttrNoDict; | |
| __pyx_IterableCoroutineType = __Pyx_FetchCommonType(&__pyx_IterableCoroutineType_type); | |
| 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}, | |
| {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} | |
| }; | |
| static PyTypeObject __pyx_GeneratorType_type = { | |
| PyVarObject_HEAD_INIT(0, 0) | |
| "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_compare / 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*/ | |
| 0, /*tp_del*/ | |
| __Pyx_Coroutine_del, /*tp_del*/ | |
| 0, /*tp_version_tag*/ | |
| __Pyx_Coroutine_del, /*tp_finalize*/ | |
| 0, /*tp_finalize*/ | |
| 0, /*tp_vectorcall*/ | |
| 0, /*tp_print*/ | |
| 0, /*tp_pypy_flags*/ | |
| }; | |
| static int __pyx_Generator_init(void) { | |
| // 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); | |
| if (unlikely(!__pyx_GeneratorType)) { | |
| return -1; | |
| } | |
| return 0; | |
| } | |
| /////////////// ReturnWithStopIteration.proto /////////////// | |
| 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.3 <= x < 3.5b1 crash in yield-from when the StopIteration is not instantiated. | |
| // 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; | |
| __Pyx_PyThreadState_declare | |
| if ((PY_VERSION_HEX >= 0x03030000 && PY_VERSION_HEX < 0x030500B1) | |
| || 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; | |
| } | |
| __Pyx_PyThreadState_assign | |
| if (!$local_tstate_cname->exc_info->exc_type) | |
| if (!$local_tstate_cname->exc_type) | |
| { | |
| // no chaining needed => avoid the overhead in PyErr_SetObject() | |
| Py_INCREF(PyExc_StopIteration); | |
| __Pyx_ErrRestore(PyExc_StopIteration, exc, NULL); | |
| return; | |
| } | |
| args = PyTuple_Pack(1, value); | |
| if (unlikely(!args)) return; | |
| exc = PyObject_Call(PyExc_StopIteration, args, NULL); | |
| Py_DECREF(args); | |
| if (unlikely(!exc)) return; | |
| 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) { | |
| int result; | |
| PyObject *globals, *result_obj; | |
| globals = PyDict_New(); if (unlikely(!globals)) goto ignore; | |
| result = PyDict_SetItemString(globals, "_cython_coroutine_type", | |
| (PyObject*)__pyx_CoroutineType); | |
| Py_None); | |
| if (unlikely(result < 0)) goto ignore; | |
| result = PyDict_SetItemString(globals, "_cython_generator_type", | |
| (PyObject*)__pyx_GeneratorType); | |
| Py_None); | |
| 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; | |
| } | |
| // avoid "unused" warning | |
| py_code++; | |
| 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 | |
| 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; | |
| } | |
| static int __Pyx_patch_abc(void) { | |
| static int abc_patched = 0; | |
| if (CYTHON_REGISTER_ABCS && !abc_patched) { | |
| PyObject *module; | |
| module = PyImport_ImportModule((PY_MAJOR_VERSION >= 3) ? "collections.abc" : "collections"); | |
| if (!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(); | |
| } | |
| } | |
| // avoid "unused" warning for __Pyx_Coroutine_patch_module() | |
| if ((0)) __Pyx_Coroutine_patch_module(NULL, NULL); | |
| 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) { | |
| 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; | |
| // 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); | |
| } | |
| // avoid "unused" warning for __Pyx_patch_inspect() | |
| if ((0)) return __Pyx_patch_inspect(module); | |
| } | |
| 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; | |
| } | |
| // avoid "unused" warning for __Pyx_Coroutine_patch_module() | |
| if ((0)) return __Pyx_patch_inspect(__Pyx_Coroutine_patch_module(module, NULL)); | |
| 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) { | |
| 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; | |
| } | |
| // avoid "unused" warning for __Pyx_Coroutine_patch_module() | |
| if ((0)) return __Pyx_Coroutine_patch_module(module, NULL); | |
| return module; | |
| } | |
| //////////////////// StopAsyncIteration.proto //////////////////// | |
| static PyObject *__Pyx_PyExc_StopAsyncIteration; | |
| static int __pyx_StopAsyncIteration_init(void); /*proto*/ | |
| //////////////////// StopAsyncIteration //////////////////// | |
| 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*/ | |
| 0, /*tp_finalize*/ | |
| 0, /*tp_pypy_flags*/ | |
| }; | |
| static int __pyx_StopAsyncIteration_init(void) { | |
| __Pyx_PyExc_StopAsyncIteration = PyExc_StopAsyncIteration; | |
| 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 (builtins && unlikely(PyMapping_SetItemString(builtins, (char*) "StopAsyncIteration", __Pyx_PyExc_StopAsyncIteration) < 0)) | |
| return -1; | |
| return 0; | |
| } | |