Coroutine.c 58.6 KB
Newer Older
1
//////////////////// GeneratorYieldFrom.proto ////////////////////
2

3
static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_CoroutineObject *gen, PyObject *source);
4

5
//////////////////// GeneratorYieldFrom ////////////////////
6 7
//@requires: Generator

8
static CYTHON_INLINE PyObject* __Pyx_Generator_Yield_From(__pyx_CoroutineObject *gen, PyObject *source) {
9 10
    PyObject *source_gen, *retval;
    source_gen = PyObject_GetIter(source);
11 12 13 14 15 16 17 18 19 20 21
    if (unlikely(!source_gen)) {
        #ifdef __Pyx_Coroutine_USED
        #if CYTHON_COMPILING_IN_CPYTHON
        // avoid exception instantiation if possible
        if (PyErr_Occurred() == PyExc_TypeError
        #else
        if (PyErr_ExceptionMatches(PyExc_TypeError)
        #endif
                && __Pyx_Coroutine_CheckExact(source)) {
            PyErr_Clear();
            // TODO: this should only happen for types.coroutine()ed generators, but we can't determine that here
Stefan Behnel's avatar
Stefan Behnel committed
22
            source_gen = __Pyx_Coroutine_await(source);
23 24
        } else
        #endif
25
        return NULL;
26
    }
27
    // source_gen is now the iterator, make the first next() call
28 29 30 31 32 33 34 35 36
    retval = Py_TYPE(source_gen)->tp_iternext(source_gen);
    if (likely(retval)) {
        gen->yieldfrom = source_gen;
        return retval;
    }
    Py_DECREF(source_gen);
    return NULL;
}

37

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
//////////////////// CoroutineYieldFrom.proto ////////////////////

static CYTHON_INLINE PyObject* __Pyx_Coroutine_Yield_From(__pyx_CoroutineObject *gen, PyObject *source);

//////////////////// CoroutineYieldFrom ////////////////////
//@requires: Coroutine
//@requires: GetAwaitIter

static CYTHON_INLINE PyObject* __Pyx_Coroutine_Yield_From(__pyx_CoroutineObject *gen, PyObject *source) {
    PyObject *retval;
    if (__Pyx_Coroutine_CheckExact(source)) {
        retval = __Pyx_Generator_Next(source);
        if (retval) {
            Py_INCREF(source);
            gen->yieldfrom = source;
            return retval;
        }
    } else {
        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_CheckExact(source_gen)) {
            retval = __Pyx_Generator_Next(source_gen);
        } else {
            retval = Py_TYPE(source_gen)->tp_iternext(source_gen);
        }
        if (retval) {
            gen->yieldfrom = source_gen;
            return retval;
        }
        Py_DECREF(source_gen);
    }
    return NULL;
}


//////////////////// GetAwaitIter.proto ////////////////////

static CYTHON_INLINE PyObject *__Pyx_Coroutine_GetAwaitableIter(PyObject *o); /*proto*/
static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *o); /*proto*/

//////////////////// GetAwaitIter ////////////////////
//@requires: Coroutine
//@requires: ObjectHandling.c::PyObjectGetAttrStr
//@requires: ObjectHandling.c::PyObjectCallNoArg
//@requires: ObjectHandling.c::PyObjectCallOneArg

static CYTHON_INLINE PyObject *__Pyx_Coroutine_GetAwaitableIter(PyObject *o) {
#ifdef __Pyx_Coroutine_USED
    if (__Pyx_Coroutine_CheckExact(o)) {
        Py_INCREF(o);
        return o;
    }
#endif
    return __Pyx__Coroutine_GetAwaitableIter(o);
}

96 97
// adapted from genobject.c in Py3.5
static PyObject *__Pyx__Coroutine_GetAwaitableIter(PyObject *obj) {
98
    PyObject *res;
99 100
#if PY_MAJOR_VERSION >= 3
    __Pyx_PyAsyncMethodsStruct* am = __Pyx_PyType_AsAsync(obj);
101 102
    if (likely(am && am->am_await)) {
        res = (*am->am_await)(obj);
103 104 105 106
    } else
#endif
    {
#if PY_VERSION_HEX >= 0x030500B1
107 108 109 110 111 112 113
    #if CYTHON_COMPILING_IN_CPYTHON
        if (PyGen_CheckCoroutineExact(obj)) {
            // Python generator marked with "@types.coroutine" decorator
            Py_INCREF(obj);
            return obj;
        }
    #endif
114
        // no slot => no method
115
        goto slot_error;
116
#else
117 118 119 120 121 122 123 124 125 126
        PyObject *method = __Pyx_PyObject_GetAttrStr(obj, PYIDENT("__await__"));
        if (unlikely(!method)) goto slot_error;
        #if CYTHON_COMPILING_IN_CPYTHON
        if (likely(PyMethod_Check(method))) {
            PyObject *self = PyMethod_GET_SELF(method);
            if (likely(self)) {
                PyObject *function = PyMethod_GET_FUNCTION(method);
                res = __Pyx_PyObject_CallOneArg(function, self);
            } else
                res = __Pyx_PyObject_CallNoArg(method);
127
        } else
128
        #endif
129
            res = __Pyx_PyObject_CallNoArg(method);
130
        Py_DECREF(method);
131
#endif
132
    }
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
    if (unlikely(!res)) goto bad;
    if (!PyIter_Check(res)) {
        PyErr_Format(PyExc_TypeError,
                     "__await__() returned non-iterator of type '%.100s'",
                     Py_TYPE(res)->tp_name);
        Py_CLEAR(res);
    } else {
        int is_coroutine = 0;
        #ifdef __Pyx_Coroutine_USED
        is_coroutine |= __Pyx_Coroutine_CheckExact(res);
        #endif
        #if PY_VERSION_HEX >= 0x030500B1
        is_coroutine |= PyGen_CheckCoroutineExact(res);
        #endif
        if (unlikely(is_coroutine)) {
            /* __await__ must return an *iterator*, not
               a coroutine or another awaitable (see PEP 492) */
            PyErr_SetString(PyExc_TypeError,
                            "__await__() returned a coroutine");
            Py_CLEAR(res);
        }
    }
    return res;
slot_error:
    PyErr_Format(PyExc_TypeError,
                 "object %.100s can't be used in 'await' expression",
159
                 Py_TYPE(obj)->tp_name);
160 161 162 163 164
bad:
    return NULL;
}


165 166 167 168 169 170 171 172 173 174
//////////////////// 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 CYTHON_INLINE PyObject *__Pyx_Coroutine_GetAsyncIter(PyObject *obj) {
175 176
#if PY_MAJOR_VERSION >= 3
    __Pyx_PyAsyncMethodsStruct* am = __Pyx_PyType_AsAsync(obj);
177 178 179
    if (likely(am && am->am_aiter)) {
        return (*am->am_aiter)(obj);
    }
180 181 182 183 184 185 186 187 188 189
#endif
#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;
    }
190 191 192 193 194 195 196 197
#endif

    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_AsyncIterNext(PyObject *obj) {
198 199
#if PY_MAJOR_VERSION >= 3
    __Pyx_PyAsyncMethodsStruct* am = __Pyx_PyType_AsAsync(obj);
200 201
    if (likely(am && am->am_anext)) {
        return (*am->am_anext)(obj);
202 203 204 205 206 207 208 209
    }
#endif
#if PY_VERSION_HEX < 0x030500B1
    {
        PyObject *value = __Pyx_PyObject_CallMethod0(obj, PYIDENT("__anext__"));
        if (likely(value))
            return value;
    }
210
    // FIXME: for the sake of a nicely conforming exception message, assume any AttributeError meant '__anext__'
211
    if (PyErr_ExceptionMatches(PyExc_AttributeError))
212 213 214 215 216 217 218
#endif
        PyErr_Format(PyExc_TypeError, "'async for' requires an object with __anext__ method, got %.100s",
                     Py_TYPE(obj)->tp_name);
    return NULL;
}


219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
//////////////////// pep479.proto ////////////////////

static void __Pyx_Generator_Replace_StopIteration(void); /*proto*/

//////////////////// pep479 ////////////////////
//@requires: Exceptions.c::GetException

static void __Pyx_Generator_Replace_StopIteration(void) {
    PyObject *exc, *val, *tb;
    // Chain exceptions by moving StopIteration 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, "generator raised StopIteration");
}


238
//////////////////// CoroutineBase.proto ////////////////////
239

240
typedef PyObject *(*__pyx_coroutine_body_t)(PyObject *, PyObject *);
241 242 243

typedef struct {
    PyObject_HEAD
244
    __pyx_coroutine_body_t body;
245 246 247 248 249 250
    PyObject *closure;
    PyObject *exc_type;
    PyObject *exc_value;
    PyObject *exc_traceback;
    PyObject *gi_weakreflist;
    PyObject *classobj;
251
    PyObject *yieldfrom;
252 253
    PyObject *gi_name;
    PyObject *gi_qualname;
254
    int resume_label;
255 256
    // using T_BOOL for property below requires char value
    char is_running;
257
} __pyx_CoroutineObject;
258

259 260 261
static __pyx_CoroutineObject *__Pyx__Coroutine_New(PyTypeObject *type, __pyx_coroutine_body_t body,
                                                   PyObject *closure, PyObject *name, PyObject *qualname); /*proto*/
static int __Pyx_Coroutine_clear(PyObject *self); /*proto*/
262

263
#if 1 || PY_VERSION_HEX < 0x030300B0
Stefan Behnel's avatar
Stefan Behnel committed
264
static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue); /*proto*/
265 266 267 268
#else
#define __Pyx_PyGen_FetchStopIterationValue(pvalue) PyGen_FetchStopIterationValue(pvalue)
#endif

269 270 271 272 273 274 275 276 277 278

//////////////////// Coroutine.proto ////////////////////

#define __Pyx_Coroutine_USED
static PyTypeObject *__pyx_CoroutineType = 0;
#define __Pyx_Coroutine_CheckExact(obj) (Py_TYPE(obj) == __pyx_CoroutineType)

#define __Pyx_Coroutine_New(body, closure, name, qualname)  \
    __Pyx__Coroutine_New(__pyx_CoroutineType, body, closure, name, qualname)

Stefan Behnel's avatar
Stefan Behnel committed
279 280
static int __pyx_Coroutine_init(void); /*proto*/
static PyObject *__Pyx_Coroutine_await(PyObject *coroutine); /*proto*/
281 282 283 284 285 286 287 288 289 290 291


//////////////////// Generator.proto ////////////////////

#define __Pyx_Generator_USED
static PyTypeObject *__pyx_GeneratorType = 0;
#define __Pyx_Generator_CheckExact(obj) (Py_TYPE(obj) == __pyx_GeneratorType)

#define __Pyx_Generator_New(body, closure, name, qualname)  \
    __Pyx__Coroutine_New(__pyx_GeneratorType, body, closure, name, qualname)

Stefan Behnel's avatar
Stefan Behnel committed
292
static int __pyx_Generator_init(void); /*proto*/
293 294 295


//////////////////// CoroutineBase ////////////////////
296 297 298
//@requires: Exceptions.c::PyErrFetchRestore
//@requires: Exceptions.c::SwapException
//@requires: Exceptions.c::RaiseException
299
//@requires: ObjectHandling.c::PyObjectCallMethod1
300
//@requires: ObjectHandling.c::PyObjectGetAttrStr
301
//@requires: CommonTypes.c::FetchCommonType
302

303 304
#include <structmember.h>
#include <frameobject.h>
305

306
static PyObject *__Pyx_Generator_Next(PyObject *self);
307 308 309 310 311
static PyObject *__Pyx_Coroutine_Send(PyObject *self, PyObject *value);
static PyObject *__Pyx_Coroutine_Close(PyObject *self);
static PyObject *__Pyx_Coroutine_Throw(PyObject *gen, PyObject *args);

#define __Pyx_Coroutine_Undelegate(gen) Py_CLEAR((gen)->yieldfrom)
312 313 314 315 316 317 318 319 320 321 322

//   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.
#if 1 || PY_VERSION_HEX < 0x030300B0
static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) {
    PyObject *et, *ev, *tb;
    PyObject *value = NULL;
323
    int result;
324 325 326 327 328 329 330 331 332 333 334 335 336

    __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)) {
337
        int error = 0;
338 339 340 341 342 343 344 345 346 347 348
#if PY_VERSION_HEX >= 0x030300A0
        if (ev && Py_TYPE(ev) == (PyTypeObject*)PyExc_StopIteration) {
            value = ((PyStopIterationObject *)ev)->value;
            Py_INCREF(value);
            Py_DECREF(ev);
            Py_XDECREF(tb);
            Py_DECREF(et);
            *pvalue = value;
            return 0;
        }
#endif
349
        if (!ev || !(error = PyObject_IsInstance(ev, PyExc_StopIteration))) {
350 351 352 353
            // PyErr_SetObject() and friends put the value directly into ev
            if (!ev) {
                Py_INCREF(Py_None);
                ev = Py_None;
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
            } else if (PyTuple_Check(ev)) {
                // however, if it's a tuple, it is interpreted as separate constructor arguments (surprise!)
                if (PyTuple_GET_SIZE(ev) >= 1) {
                    PyObject *value;
#if CYTHON_COMPILING_IN_CPYTHON
                    value = PySequence_ITEM(ev, 0);
#else
                    value = PyTuple_GET_ITEM(ev, 0);
                    Py_INCREF(value);
#endif
                    Py_DECREF(ev);
                    ev = value;
                } else {
                    Py_INCREF(Py_None);
                    Py_DECREF(ev);
                    ev = Py_None;
                }
371 372 373 374 375 376
            }
            Py_XDECREF(tb);
            Py_DECREF(et);
            *pvalue = ev;
            return 0;
        }
377 378 379 380
        if (unlikely(error == -1)) {
            // error during isinstance() check
            return -1;
        }
381 382 383
    } else if (!PyErr_GivenExceptionMatches(et, PyExc_StopIteration)) {
        __Pyx_ErrRestore(et, ev, tb);
        return -1;
384
    }
385

386 387
    // otherwise: normalise and check what that gives us
    PyErr_NormalizeException(&et, &ev, &tb);
388 389
    result = PyObject_IsInstance(ev, PyExc_StopIteration);
    if (unlikely(!result)) {
390 391 392 393 394 395
        // looks like normalisation failed - raise the new exception
        __Pyx_ErrRestore(et, ev, tb);
        return -1;
    }
    Py_XDECREF(tb);
    Py_DECREF(et);
396 397 398 399 400
    if (unlikely(result == -1)) {
        // error during isinstance() check
        Py_DECREF(ev);
        return -1;
    }
401 402 403 404 405 406
#if PY_VERSION_HEX >= 0x030300A0
    value = ((PyStopIterationObject *)ev)->value;
    Py_INCREF(value);
    Py_DECREF(ev);
#else
    {
407
        PyObject* args = __Pyx_PyObject_GetAttrStr(ev, PYIDENT("args"));
408 409
        Py_DECREF(ev);
        if (likely(args)) {
410
            value = PySequence_GetItem(args, 0);
411 412 413 414 415 416 417 418 419 420 421 422 423 424
            Py_DECREF(args);
        }
        if (unlikely(!value)) {
            __Pyx_ErrRestore(NULL, NULL, NULL);
            Py_INCREF(Py_None);
            value = Py_None;
        }
    }
#endif
    *pvalue = value;
    return 0;
}
#endif

425
static CYTHON_INLINE
426
void __Pyx_Coroutine_ExceptionClear(__pyx_CoroutineObject *self) {
427 428 429
    PyObject *exc_type = self->exc_type;
    PyObject *exc_value = self->exc_value;
    PyObject *exc_traceback = self->exc_traceback;
430 431 432 433

    self->exc_type = NULL;
    self->exc_value = NULL;
    self->exc_traceback = NULL;
434 435 436 437

    Py_XDECREF(exc_type);
    Py_XDECREF(exc_value);
    Py_XDECREF(exc_traceback);
438 439 440
}

static CYTHON_INLINE
441
int __Pyx_Coroutine_CheckRunning(__pyx_CoroutineObject *gen) {
442
    if (unlikely(gen->is_running)) {
443 444
        PyErr_SetString(PyExc_ValueError,
                        "generator already executing");
445
        return 1;
446
    }
447 448 449 450
    return 0;
}

static CYTHON_INLINE
451
PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value) {
452 453 454
    PyObject *retval;

    assert(!self->is_running);
455

456 457
    if (unlikely(self->resume_label == 0)) {
        if (unlikely(value && value != Py_None)) {
458 459 460 461 462 463 464
            PyErr_SetString(PyExc_TypeError,
                            "can't send non-None value to a "
                            "just-started generator");
            return NULL;
        }
    }

465
    if (unlikely(self->resume_label == -1)) {
466 467 468 469 470
        PyErr_SetNone(PyExc_StopIteration);
        return NULL;
    }


471
    if (value) {
472 473 474
#if CYTHON_COMPILING_IN_PYPY
        // FIXME: what to do in PyPy?
#else
475 476
        // Generators always return to their most recent caller, not
        // necessarily their creator.
477 478 479 480 481 482 483 484 485
        if (self->exc_traceback) {
            PyThreadState *tstate = PyThreadState_GET();
            PyTracebackObject *tb = (PyTracebackObject *) self->exc_traceback;
            PyFrameObject *f = tb->tb_frame;

            Py_XINCREF(tstate->frame);
            assert(f->f_back == NULL);
            f->f_back = tstate->frame;
        }
486
#endif
487 488 489
        __Pyx_ExceptionSwap(&self->exc_type, &self->exc_value,
                            &self->exc_traceback);
    } else {
490
        __Pyx_Coroutine_ExceptionClear(self);
491
    }
492 493 494 495 496

    self->is_running = 1;
    retval = self->body((PyObject *) self, value);
    self->is_running = 0;

497 498 499
    if (retval) {
        __Pyx_ExceptionSwap(&self->exc_type, &self->exc_value,
                            &self->exc_traceback);
500 501 502
#if CYTHON_COMPILING_IN_PYPY
        // FIXME: what to do in PyPy?
#else
503 504 505
        // 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.
506 507 508 509 510
        if (self->exc_traceback) {
            PyTracebackObject *tb = (PyTracebackObject *) self->exc_traceback;
            PyFrameObject *f = tb->tb_frame;
            Py_CLEAR(f->f_back);
        }
511
#endif
512
    } else {
513
        __Pyx_Coroutine_ExceptionClear(self);
514
    }
515 516 517 518

    return retval;
}

519
static CYTHON_INLINE
520
PyObject *__Pyx_Coroutine_MethodReturn(PyObject *retval) {
521 522 523 524 525 526 527
    if (unlikely(!retval && !PyErr_Occurred())) {
        // method call must not terminate with NULL without setting an exception
        PyErr_SetNone(PyExc_StopIteration);
    }
    return retval;
}

528
static CYTHON_INLINE
529
PyObject *__Pyx_Coroutine_FinishDelegation(__pyx_CoroutineObject *gen) {
530 531
    PyObject *ret;
    PyObject *val = NULL;
532
    __Pyx_Coroutine_Undelegate(gen);
533 534
    __Pyx_PyGen_FetchStopIterationValue(&val);
    // val == NULL on failure => pass on exception
535
    ret = __Pyx_Coroutine_SendEx(gen, val);
536 537
    Py_XDECREF(val);
    return ret;
538 539
}

540
static PyObject *__Pyx_Coroutine_Send(PyObject *self, PyObject *value) {
541
    PyObject *retval;
542
    __pyx_CoroutineObject *gen = (__pyx_CoroutineObject*) self;
543
    PyObject *yf = gen->yieldfrom;
544
    if (unlikely(__Pyx_Coroutine_CheckRunning(gen)))
545 546 547 548 549 550
        return NULL;
    if (yf) {
        PyObject *ret;
        // FIXME: does this really need an INCREF() ?
        //Py_INCREF(yf);
        gen->is_running = 1;
551
        #ifdef __Pyx_Generator_USED
552
        if (__Pyx_Generator_CheckExact(yf)) {
553 554 555 556 557 558 559 560 561
            ret = __Pyx_Coroutine_Send(yf, value);
        } else
        #endif
        #ifdef __Pyx_Coroutine_USED
        if (__Pyx_Coroutine_CheckExact(yf)) {
            ret = __Pyx_Coroutine_Send(yf, value);
        } else
        #endif
        {
562
            if (value == Py_None)
563
                ret = PyIter_Next(yf);  // FIXME!
564
            else
565
                ret = __Pyx_PyObject_CallMethod1(yf, PYIDENT("send"), value);
566 567 568 569 570 571
        }
        gen->is_running = 0;
        //Py_DECREF(yf);
        if (likely(ret)) {
            return ret;
        }
572
        retval = __Pyx_Coroutine_FinishDelegation(gen);
573
    } else {
574
        retval = __Pyx_Coroutine_SendEx(gen, value);
575
    }
576
    return __Pyx_Coroutine_MethodReturn(retval);
577 578 579 580
}

//   This helper function is used by gen_close and gen_throw to
//   close a subiterator being delegated to by yield-from.
581
static int __Pyx_Coroutine_CloseIter(__pyx_CoroutineObject *gen, PyObject *yf) {
582 583 584
    PyObject *retval = NULL;
    int err = 0;

585
    #ifdef __Pyx_Generator_USED
586
    if (__Pyx_Generator_CheckExact(yf)) {
587
        retval = __Pyx_Coroutine_Close(yf);
588 589
        if (!retval)
            return -1;
590 591 592 593 594 595 596 597 598 599
    } else
    #endif
    #ifdef __Pyx_Coroutine_USED
    if (__Pyx_Coroutine_CheckExact(yf)) {
        retval = __Pyx_Coroutine_Close(yf);
        if (!retval)
            return -1;
    } else
    #endif
    {
600 601
        PyObject *meth;
        gen->is_running = 1;
602
        meth = __Pyx_PyObject_GetAttrStr(yf, PYIDENT("close"));
603 604 605 606 607 608
        if (unlikely(!meth)) {
            if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
                PyErr_WriteUnraisable(yf);
            }
            PyErr_Clear();
        } else {
609
            retval = PyObject_CallFunction(meth, NULL);
610 611 612 613 614 615 616 617 618 619
            Py_DECREF(meth);
            if (!retval)
                err = -1;
        }
        gen->is_running = 0;
    }
    Py_XDECREF(retval);
    return err;
}

620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
static PyObject *__Pyx_Generator_Next(PyObject *self) {
    __pyx_CoroutineObject *gen = (__pyx_CoroutineObject*) self;
    PyObject *yf = gen->yieldfrom;
    if (unlikely(__Pyx_Coroutine_CheckRunning(gen)))
        return NULL;
    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;
        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);
}

642 643
static PyObject *__Pyx_Coroutine_Close(PyObject *self) {
    __pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self;
644 645 646 647
    PyObject *retval, *raised_exception;
    PyObject *yf = gen->yieldfrom;
    int err = 0;

648
    if (unlikely(__Pyx_Coroutine_CheckRunning(gen)))
649 650 651 652
        return NULL;

    if (yf) {
        Py_INCREF(yf);
653 654
        err = __Pyx_Coroutine_CloseIter(gen, yf);
        __Pyx_Coroutine_Undelegate(gen);
655 656 657 658
        Py_DECREF(yf);
    }
    if (err == 0)
        PyErr_SetNone(PyExc_GeneratorExit);
659
    retval = __Pyx_Coroutine_SendEx(gen, NULL);
660 661 662 663 664 665
    if (retval) {
        Py_DECREF(retval);
        PyErr_SetString(PyExc_RuntimeError,
                        "generator ignored GeneratorExit");
        return NULL;
    }
666 667 668 669 670 671
    raised_exception = PyErr_Occurred();
    if (!raised_exception
        || raised_exception == PyExc_StopIteration
        || raised_exception == PyExc_GeneratorExit
        || PyErr_GivenExceptionMatches(raised_exception, PyExc_GeneratorExit)
        || PyErr_GivenExceptionMatches(raised_exception, PyExc_StopIteration))
672
    {
673 674
        // ignore these errors
        if (raised_exception) PyErr_Clear();
675 676 677 678 679 680
        Py_INCREF(Py_None);
        return Py_None;
    }
    return NULL;
}

681 682
static PyObject *__Pyx_Coroutine_Throw(PyObject *self, PyObject *args) {
    __pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self;
683 684 685
    PyObject *typ;
    PyObject *tb = NULL;
    PyObject *val = NULL;
686
    PyObject *yf = gen->yieldfrom;
687 688 689

    if (!PyArg_UnpackTuple(args, (char *)"throw", 1, 3, &typ, &val, &tb))
        return NULL;
690

691
    if (unlikely(__Pyx_Coroutine_CheckRunning(gen)))
692 693 694 695 696 697
        return NULL;

    if (yf) {
        PyObject *ret;
        Py_INCREF(yf);
        if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit)) {
698
            int err = __Pyx_Coroutine_CloseIter(gen, yf);
699
            Py_DECREF(yf);
700
            __Pyx_Coroutine_Undelegate(gen);
701
            if (err < 0)
702
                return __Pyx_Coroutine_MethodReturn(__Pyx_Coroutine_SendEx(gen, NULL));
703 704 705
            goto throw_here;
        }
        gen->is_running = 1;
706
        #ifdef __Pyx_Generator_USED
707
        if (__Pyx_Generator_CheckExact(yf)) {
708 709 710 711 712 713 714 715 716
            ret = __Pyx_Coroutine_Throw(yf, args);
        } else
        #endif
        #ifdef __Pyx_Coroutine_USED
        if (__Pyx_Coroutine_CheckExact(yf)) {
            ret = __Pyx_Coroutine_Throw(yf, args);
        } else
        #endif
        {
717
            PyObject *meth = __Pyx_PyObject_GetAttrStr(yf, PYIDENT("throw"));
718 719 720 721 722 723 724
            if (unlikely(!meth)) {
                Py_DECREF(yf);
                if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
                    gen->is_running = 0;
                    return NULL;
                }
                PyErr_Clear();
725
                __Pyx_Coroutine_Undelegate(gen);
726 727 728 729 730 731 732 733 734
                gen->is_running = 0;
                goto throw_here;
            }
            ret = PyObject_CallObject(meth, args);
            Py_DECREF(meth);
        }
        gen->is_running = 0;
        Py_DECREF(yf);
        if (!ret) {
735
            ret = __Pyx_Coroutine_FinishDelegation(gen);
736
        }
737
        return __Pyx_Coroutine_MethodReturn(ret);
738 739
    }
throw_here:
740
    __Pyx_Raise(typ, val, tb, NULL);
741
    return __Pyx_Coroutine_MethodReturn(__Pyx_Coroutine_SendEx(gen, NULL));
742 743
}

744 745
static int __Pyx_Coroutine_traverse(PyObject *self, visitproc visit, void *arg) {
    __pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self;
746 747 748

    Py_VISIT(gen->closure);
    Py_VISIT(gen->classobj);
749
    Py_VISIT(gen->yieldfrom);
750 751 752 753 754 755
    Py_VISIT(gen->exc_type);
    Py_VISIT(gen->exc_value);
    Py_VISIT(gen->exc_traceback);
    return 0;
}

756 757
static int __Pyx_Coroutine_clear(PyObject *self) {
    __pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self;
758 759 760 761 762 763 764

    Py_CLEAR(gen->closure);
    Py_CLEAR(gen->classobj);
    Py_CLEAR(gen->yieldfrom);
    Py_CLEAR(gen->exc_type);
    Py_CLEAR(gen->exc_value);
    Py_CLEAR(gen->exc_traceback);
765 766
    Py_CLEAR(gen->gi_name);
    Py_CLEAR(gen->gi_qualname);
767 768 769
    return 0;
}

770 771
static void __Pyx_Coroutine_dealloc(PyObject *self) {
    __pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self;
772

773 774 775 776 777
    PyObject_GC_UnTrack(gen);
    if (gen->gi_weakreflist != NULL)
        PyObject_ClearWeakRefs(self);

    if (gen->resume_label > 0) {
778
        // Generator is paused, so we need to close
779 780 781 782
        PyObject_GC_Track(self);
#if PY_VERSION_HEX >= 0x030400a1
        if (PyObject_CallFinalizerFromDealloc(self))
#else
783 784
        Py_TYPE(gen)->tp_del(self);
        if (self->ob_refcnt > 0)
785
#endif
786 787 788 789
        {
            // resurrected.  :(
            return;
        }
790
        PyObject_GC_UnTrack(self);
791 792
    }

793
    __Pyx_Coroutine_clear(self);
794 795 796
    PyObject_GC_Del(gen);
}

797
static void __Pyx_Coroutine_del(PyObject *self) {
798 799
    PyObject *res;
    PyObject *error_type, *error_value, *error_traceback;
800
    __pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self;
801 802 803 804

    if (gen->resume_label <= 0)
        return ;

805
#if PY_VERSION_HEX < 0x030400a1
806
    // Temporarily resurrect the object.
807 808
    assert(self->ob_refcnt == 0);
    self->ob_refcnt = 1;
809
#endif
810

811
    // Save the current exception, if any.
812 813
    __Pyx_ErrFetch(&error_type, &error_value, &error_traceback);

814
    res = __Pyx_Coroutine_Close(self);
815 816 817 818 819 820

    if (res == NULL)
        PyErr_WriteUnraisable(self);
    else
        Py_DECREF(res);

821
    // Restore the saved exception.
822 823
    __Pyx_ErrRestore(error_type, error_value, error_traceback);

824
#if PY_VERSION_HEX < 0x030400a1
825 826
    // Undo the temporary resurrection; can't use DECREF here, it would
    // cause a recursive call.
827
    assert(self->ob_refcnt > 0);
828 829 830 831
    if (--self->ob_refcnt == 0) {
        // this is the normal path out
        return;
    }
832

833 834
    // close() resurrected it!  Make it look like the original Py_DECREF
    // never happened.
835 836 837 838 839
    {
        Py_ssize_t refcnt = self->ob_refcnt;
        _Py_NewReference(self);
        self->ob_refcnt = refcnt;
    }
840
#if CYTHON_COMPILING_IN_CPYTHON
841 842 843
    assert(PyType_IS_GC(self->ob_type) &&
           _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);

844 845
    // If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
    // we need to undo that.
846
    _Py_DEC_REFTOTAL;
847
#endif
848 849 850 851 852
    // 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.
853
#ifdef COUNT_ALLOCS
854 855
    --Py_TYPE(self)->tp_frees;
    --Py_TYPE(self)->tp_allocs;
856
#endif
857
#endif
858
}
859

860
static PyObject *
861
__Pyx_Coroutine_get_name(__pyx_CoroutineObject *self)
862 863 864 865 866 867
{
    Py_INCREF(self->gi_name);
    return self->gi_name;
}

static int
868
__Pyx_Coroutine_set_name(__pyx_CoroutineObject *self, PyObject *value)
869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
{
    PyObject *tmp;

#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;
    }
    tmp = self->gi_name;
    Py_INCREF(value);
    self->gi_name = value;
    Py_XDECREF(tmp);
    return 0;
}

static PyObject *
889
__Pyx_Coroutine_get_qualname(__pyx_CoroutineObject *self)
890 891 892 893 894 895
{
    Py_INCREF(self->gi_qualname);
    return self->gi_qualname;
}

static int
896
__Pyx_Coroutine_set_qualname(__pyx_CoroutineObject *self, PyObject *value)
897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915
{
    PyObject *tmp;

#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;
    }
    tmp = self->gi_qualname;
    Py_INCREF(value);
    self->gi_qualname = value;
    Py_XDECREF(tmp);
    return 0;
}

916 917
static PyGetSetDef __pyx_Coroutine_getsets[] = {
    {(char *) "__name__", (getter)__Pyx_Coroutine_get_name, (setter)__Pyx_Coroutine_set_name,
Stefan Behnel's avatar
Stefan Behnel committed
918
     (char*) PyDoc_STR("name of the generator"), 0},
919
    {(char *) "__qualname__", (getter)__Pyx_Coroutine_get_qualname, (setter)__Pyx_Coroutine_set_qualname,
Stefan Behnel's avatar
Stefan Behnel committed
920
     (char*) PyDoc_STR("qualified name of the generator"), 0},
921 922 923
    {0, 0, 0, 0, 0}
};

924 925
static PyMemberDef __pyx_Coroutine_memberlist[] = {
    {(char *) "gi_running", T_BOOL, offsetof(__pyx_CoroutineObject, is_running), READONLY, NULL},
926
    {0, 0, 0, 0, 0}
927 928
};

929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960
static __pyx_CoroutineObject *__Pyx__Coroutine_New(PyTypeObject* type, __pyx_coroutine_body_t body,
                                                   PyObject *closure, PyObject *name, PyObject *qualname) {
    __pyx_CoroutineObject *gen = PyObject_GC_New(__pyx_CoroutineObject, type);

    if (gen == NULL)
        return NULL;

    gen->body = body;
    gen->closure = closure;
    Py_XINCREF(closure);
    gen->is_running = 0;
    gen->resume_label = 0;
    gen->classobj = NULL;
    gen->yieldfrom = NULL;
    gen->exc_type = NULL;
    gen->exc_value = NULL;
    gen->exc_traceback = NULL;
    gen->gi_weakreflist = NULL;
    Py_XINCREF(qualname);
    gen->gi_qualname = qualname;
    Py_XINCREF(name);
    gen->gi_name = name;

    PyObject_GC_Track(gen);
    return gen;
}


//////////////////// Coroutine ////////////////////
//@requires: CoroutineBase
//@requires: PatchGeneratorABC

961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
static void __Pyx_Coroutine_check_and_dealloc(PyObject *self) {
    __pyx_CoroutineObject *gen = (__pyx_CoroutineObject *) self;

    if (gen->resume_label == 0 && !PyErr_Occurred()) {
#if PY_VERSION_HEX >= 0x03030000 || defined(PyErr_WarnFormat)
        PyErr_WarnFormat(PyExc_RuntimeWarning, 1, "coroutine '%.50S' was never awaited", gen->gi_qualname);
#else
        PyObject *msg, *qualname;
        char *cname, *cmsg;
        #if PY_MAJOR_VERSION >= 3
        qualname = PyUnicode_AsUTF8String(gen->gi_qualname);
        if (likely(qualname)) {
            cname = PyBytes_AS_STRING(qualname);
        } else {
            PyErr_Clear();
            cname = (char*) "?";
        }
        msg = PyBytes_FromFormat(
        #else
        qualname = gen->gi_qualname;
        cname = PyString_AS_STRING(qualname);
        msg = PyString_FromFormat(
        #endif
            "coroutine '%.50s' was never awaited", cname);

        #if PY_MAJOR_VERSION >= 3
        Py_XDECREF(qualname);
        #endif

        if (unlikely(!msg)) {
            PyErr_Clear();
            cmsg = (char*) "coroutine was never awaited";
        } else {
            #if PY_MAJOR_VERSION >= 3
            cmsg = PyBytes_AS_STRING(msg);
            #else
            cmsg = PyString_AS_STRING(msg);
            #endif
        }
        if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning, cmsg, 1) < 0))
            PyErr_WriteUnraisable(self);
        Py_XDECREF(msg);
#endif
    }

    __Pyx_Coroutine_dealloc(self);
}

1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
#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

Stefan Behnel's avatar
Stefan Behnel committed
1023
static PyObject *__Pyx_Coroutine_await(PyObject *self) {
1024 1025 1026 1027
    Py_INCREF(self);
    return self;
}

1028 1029 1030 1031 1032
static PyMethodDef __pyx_Coroutine_methods[] = {
    {"send", (PyCFunction) __Pyx_Coroutine_Send, METH_O, 0},
    {"throw", (PyCFunction) __Pyx_Coroutine_Throw, METH_VARARGS, 0},
    {"close", (PyCFunction) __Pyx_Coroutine_Close, METH_NOARGS, 0},
#if PY_VERSION_HEX < 0x030500B1
Stefan Behnel's avatar
Stefan Behnel committed
1033
    {"__await__", (PyCFunction) __Pyx_Coroutine_await, METH_NOARGS, 0},
1034 1035 1036 1037
#endif
    {0, 0, 0, 0}
};

1038 1039
#if PY_MAJOR_VERSION >= 3
static __Pyx_PyAsyncMethodsStruct __pyx_Coroutine_as_async = {
Stefan Behnel's avatar
Stefan Behnel committed
1040
    __Pyx_Coroutine_await, /*am_await*/
1041 1042
    0, /*am_aiter*/
    0, /*am_anext*/
1043
};
1044 1045
#endif

1046
static PyTypeObject __pyx_CoroutineType_type = {
1047
    PyVarObject_HEAD_INIT(0, 0)
1048 1049
    "coroutine",                        /*tp_name*/
    sizeof(__pyx_CoroutineObject),      /*tp_basicsize*/
1050
    0,                                  /*tp_itemsize*/
1051
    (destructor) __Pyx_Coroutine_check_and_dealloc,/*tp_dealloc*/
1052 1053 1054
    0,                                  /*tp_print*/
    0,                                  /*tp_getattr*/
    0,                                  /*tp_setattr*/
1055 1056
#if PY_MAJOR_VERSION >= 3
    &__pyx_Coroutine_as_async,          /*tp_as_async (tp_reserved)*/
1057
#else
1058
    0,                                  /*tp_reserved*/
1059
#endif
1060
    0,                                  /*tp_repr*/
1061 1062 1063 1064 1065 1066
    0,                                  /*tp_as_number*/
    0,                                  /*tp_as_sequence*/
    0,                                  /*tp_as_mapping*/
    0,                                  /*tp_hash*/
    0,                                  /*tp_call*/
    0,                                  /*tp_str*/
Stefan Behnel's avatar
Stefan Behnel committed
1067
    0,                                  /*tp_getattro*/
1068 1069
    0,                                  /*tp_setattro*/
    0,                                  /*tp_as_buffer*/
1070
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/
1071
    0,                                  /*tp_doc*/
1072
    (traverseproc) __Pyx_Coroutine_traverse,   /*tp_traverse*/
1073
    0,                                  /*tp_clear*/
1074 1075 1076 1077
#if 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
1078
    0,                                  /*tp_richcompare*/
1079
#endif
1080
    offsetof(__pyx_CoroutineObject, gi_weakreflist), /*tp_weaklistoffset*/
1081
// no tp_iter() as iterator is only available through __await__()
Stefan Behnel's avatar
Stefan Behnel committed
1082
    0,                                  /*tp_iter*/
1083
    (iternextfunc) __Pyx_Generator_Next, /*tp_iternext*/
1084 1085 1086
    __pyx_Coroutine_methods,            /*tp_methods*/
    __pyx_Coroutine_memberlist,         /*tp_members*/
    __pyx_Coroutine_getsets,            /*tp_getset*/
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
    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*/
1102 1103 1104
#if PY_VERSION_HEX >= 0x030400a1
    0,                                  /*tp_del*/
#else
1105
    __Pyx_Coroutine_del,                /*tp_del*/
1106
#endif
1107
    0,                                  /*tp_version_tag*/
1108
#if PY_VERSION_HEX >= 0x030400a1
1109
    __Pyx_Coroutine_del,                /*tp_finalize*/
1110
#endif
1111 1112
};

1113
static int __pyx_Coroutine_init(void) {
1114 1115
    // on Windows, C-API functions can't be used in slots statically
    __pyx_CoroutineType_type.tp_getattro = PyObject_GenericGetAttr;
1116

1117
    __pyx_CoroutineType = __Pyx_FetchCommonType(&__pyx_CoroutineType_type);
1118
    if (unlikely(!__pyx_CoroutineType)) {
1119
        return -1;
1120
    }
1121 1122
    return 0;
}
1123

1124 1125 1126 1127
//////////////////// Generator ////////////////////
//@requires: CoroutineBase
//@requires: PatchGeneratorABC

1128 1129 1130 1131 1132 1133 1134
static PyMethodDef __pyx_Generator_methods[] = {
    {"send", (PyCFunction) __Pyx_Coroutine_Send, METH_O, 0},
    {"throw", (PyCFunction) __Pyx_Coroutine_Throw, METH_VARARGS, 0},
    {"close", (PyCFunction) __Pyx_Coroutine_Close, METH_NOARGS, 0},
    {0, 0, 0, 0}
};

1135 1136 1137 1138 1139 1140 1141 1142 1143
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*/
1144
    0,                                  /*tp_compare / tp_as_async*/
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
    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*/
1163
    __pyx_Generator_methods,            /*tp_methods*/
1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191
    __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
    __Pyx_Coroutine_del,                /*tp_finalize*/
#endif
};

1192
static int __pyx_Generator_init(void) {
1193
    // on Windows, C-API functions can't be used in slots statically
Stefan Behnel's avatar
Stefan Behnel committed
1194 1195
    __pyx_GeneratorType_type.tp_getattro = PyObject_GenericGetAttr;
    __pyx_GeneratorType_type.tp_iter = PyObject_SelfIter;
1196 1197

    __pyx_GeneratorType = __Pyx_FetchCommonType(&__pyx_GeneratorType_type);
1198
    if (unlikely(!__pyx_GeneratorType)) {
1199 1200 1201
        return -1;
    }
    return 0;
1202
}
1203 1204


1205 1206
/////////////// ReturnWithStopIteration.proto ///////////////

1207 1208
#define __Pyx_ReturnWithStopIteration(value)  \
    if (value == Py_None) PyErr_SetNone(PyExc_StopIteration); else __Pyx__ReturnWithStopIteration(value)
1209 1210 1211
static void __Pyx__ReturnWithStopIteration(PyObject* value); /*proto*/

/////////////// ReturnWithStopIteration ///////////////
1212 1213 1214 1215 1216 1217 1218
//@requires: Exceptions.c::PyErrFetchRestore
//@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) If there is currently an exception being handled, we need to chain it.
1219 1220 1221

static void __Pyx__ReturnWithStopIteration(PyObject* value) {
    PyObject *exc, *args;
1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
#if CYTHON_COMPILING_IN_CPYTHON
    if ((PY_VERSION_HEX >= 0x03030000 && PY_VERSION_HEX < 0x030500B1) || PyTuple_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 (!PyThreadState_GET()->exc_type) {
        // no chaining needed => avoid the overhead in PyErr_SetObject()
        Py_INCREF(PyExc_StopIteration);
        __Pyx_ErrRestore(PyExc_StopIteration, exc, NULL);
        return;
    }
#else
    args = PyTuple_Pack(1, value);
    if (unlikely(!args)) return;
1245 1246
    exc = PyObject_Call(PyExc_StopIteration, args, NULL);
    Py_DECREF(args);
1247
    if (unlikely(!exc)) return;
1248
#endif
1249 1250 1251
    PyErr_SetObject(PyExc_StopIteration, exc);
    Py_DECREF(exc);
}
1252 1253


1254
//////////////////// PatchModuleWithCoroutine.proto ////////////////////
1255

1256
static PyObject* __Pyx_Coroutine_patch_module(PyObject* module, const char* py_code); /*proto*/
1257

1258
//////////////////// PatchModuleWithCoroutine ////////////////////
1259 1260
//@substitute: naming

1261 1262
static PyObject* __Pyx_Coroutine_patch_module(PyObject* module, const char* py_code) {
#if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED)
1263 1264
    PyObject *globals, *result_obj;
    globals = PyDict_New();  if (unlikely(!globals)) goto ignore;
1265 1266 1267 1268
    #ifdef __Pyx_Coroutine_USED
    if (unlikely(PyDict_SetItemString(globals, "_cython_coroutine_type", (PyObject*)__pyx_CoroutineType) < 0)) goto ignore;
    #endif
    #ifdef __Pyx_Generator_USED
1269
    if (unlikely(PyDict_SetItemString(globals, "_cython_generator_type", (PyObject*)__pyx_GeneratorType) < 0)) goto ignore;
1270
    #endif
1271
    if (unlikely(PyDict_SetItemString(globals, "_module", module) < 0)) goto ignore;
1272
    if (unlikely(PyDict_SetItemString(globals, "__builtins__", $builtins_cname) < 0)) goto ignore;
1273 1274 1275 1276 1277 1278 1279 1280
    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);
1281
    PyErr_WriteUnraisable(module);
1282 1283 1284 1285
    if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning, "Cython module failed to patch module with custom type", 1) < 0)) {
        Py_DECREF(module);
        module = NULL;
    }
1286 1287 1288 1289
#else
    // avoid "unused" warning
    py_code++;
#endif
1290 1291
    return module;
}
1292

1293

1294 1295 1296 1297 1298 1299 1300
//////////////////// PatchGeneratorABC.proto ////////////////////

// patch 'collections.abc' if it lacks generator support
// see https://bugs.python.org/issue24018
static int __Pyx_patch_abc(void); /*proto*/

//////////////////// PatchGeneratorABC ////////////////////
1301
//@requires: PatchModuleWithCoroutine
1302 1303

static int __Pyx_patch_abc(void) {
1304 1305
#if (defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED)) && \
        (!defined(CYTHON_PATCH_ABC) || CYTHON_PATCH_ABC)
1306 1307 1308
    static int abc_patched = 0;
    if (!abc_patched) {
        PyObject *module;
1309
        module = PyImport_ImportModule((PY_VERSION_HEX >= 0x03030000) ? "collections.abc" : "collections");
1310
        if (!module) {
1311
            PyErr_WriteUnraisable(NULL);
1312 1313
            if (unlikely(PyErr_WarnEx(PyExc_RuntimeWarning,
                    ((PY_VERSION_HEX >= 0x03030000) ?
1314 1315
                        "Cython module failed to patch collections.abc module" :
                        "Cython module failed to patch collections module"), 1) < 0)) {
1316 1317 1318
                return -1;
            }
        } else {
1319 1320
            module = __Pyx_Coroutine_patch_module(
                module,
1321
#ifdef __Pyx_Generator_USED
1322
                CSTRING("""\
1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
def mk_gen():
    from abc import abstractmethod

    required_methods = (
        '__iter__', '__next__' if hasattr(iter(()), '__next__') else 'next',
         'send', 'throw', 'close')

    class Generator(_module.Iterator):
        __slots__ = ()

        if '__next__' in required_methods:
            def __next__(self):
                return self.send(None)
        else:
            def next(self):
                return self.send(None)

        @abstractmethod
        def send(self, value):
            raise StopIteration

1344
        @abstractmethod
1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378
        def throw(self, typ, val=None, tb=None):
            if val is None:
                if tb is None:
                    raise typ
                val = typ()
            if tb is not None:
                val = val.with_traceback(tb)
            raise val

        def close(self):
            try:
                self.throw(GeneratorExit)
            except (GeneratorExit, StopIteration):
                pass
            else:
                raise RuntimeError('generator ignored GeneratorExit')

        @classmethod
        def __subclasshook__(cls, C):
            if cls is Generator:
                mro = C.__mro__
                for method in required_methods:
                    for base in mro:
                        if method in base.__dict__:
                            break
                    else:
                        return NotImplemented
                return True
            return NotImplemented

    generator = type((lambda: (yield))())
    Generator.register(generator)
    return Generator

1379 1380 1381 1382 1383
try:
    Generator = _module.Generator
except AttributeError:
    Generator = _module.Generator = mk_gen()
Generator.register(_cython_generator_type)
1384
""")
1385 1386
#endif
#ifdef __Pyx_Coroutine_USED
1387
                CSTRING("""\
1388
def mk_awaitable():
1389
    from abc import abstractmethod, ABCMeta
1390 1391
""")
#if PY_MAJOR_VERSION >= 3
1392
                CSTRING("""\
1393
    class Awaitable(metaclass=ABCMeta):
1394
""")
1395
#else
1396
                CSTRING("""\
1397
    class Awaitable(object):
1398 1399
        __metaclass__ = ABCMeta
""")
1400
#endif
1401
                CSTRING("""\
1402 1403
        __slots__ = ()

1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430
        @abstractmethod
        def __await__(self):
            yield

        @classmethod
        def __subclasshook__(cls, C):
            if cls is Awaitable:
                for B in C.__mro__:
                    if '__await__' in B.__dict__:
                        if B.__dict__['__await__']:
                            return True
                        break
            return NotImplemented

    return Awaitable

try:
    Awaitable = _module.Awaitable
except AttributeError:
    Awaitable = _module.Awaitable = mk_awaitable()

def mk_coroutine():
    from abc import abstractmethod, ABCMeta

    class Coroutine(Awaitable):
        __slots__ = ()

1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460
        @abstractmethod
        def send(self, value):
            '''Send a value into the coroutine.
            Return next yielded value or raise StopIteration.
            '''
            raise StopIteration

        @abstractmethod
        def throw(self, typ, val=None, tb=None):
            '''Raise an exception in the coroutine.
            Return next yielded value or raise StopIteration.
            '''
            if val is None:
                if tb is None:
                    raise typ
                val = typ()
            if tb is not None:
                val = val.with_traceback(tb)
            raise val

        def close(self):
            '''Raise GeneratorExit inside coroutine.
            '''
            try:
                self.throw(GeneratorExit)
            except (GeneratorExit, StopIteration):
                pass
            else:
                raise RuntimeError('coroutine ignored GeneratorExit')

1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472
        @classmethod
        def __subclasshook__(cls, C):
            if cls is Coroutine:
                mro = C.__mro__
                for method in ('__await__', 'send', 'throw', 'close'):
                    for base in mro:
                        if method in base.__dict__:
                            break
                    else:
                        return NotImplemented
                return True
            return NotImplemented
1473

1474 1475 1476 1477 1478 1479 1480
    return Coroutine

try:
    Coroutine = _module.Coroutine
except AttributeError:
    Coroutine = _module.Coroutine = mk_coroutine()
Coroutine.register(_cython_coroutine_type)
1481 1482
""")
#endif
1483 1484 1485 1486
            );
            abc_patched = 1;
            if (unlikely(!module))
                return -1;
1487 1488 1489 1490
            Py_DECREF(module);
        }
    }
#else
1491 1492
    // avoid "unused" warning for __Pyx_Coroutine_patch_module()
    if (0) __Pyx_Coroutine_patch_module(NULL, NULL);
1493 1494 1495 1496 1497
#endif
    return 0;
}


1498 1499 1500 1501 1502 1503
//////////////////// PatchAsyncIO.proto ////////////////////

// run after importing "asyncio" to patch Cython generator support into it
static PyObject* __Pyx_patch_asyncio(PyObject* module); /*proto*/

//////////////////// PatchAsyncIO ////////////////////
1504
//@requires: ImportExport.c::Import
1505
//@requires: PatchModuleWithCoroutine
1506 1507 1508
//@requires: PatchInspect

static PyObject* __Pyx_patch_asyncio(PyObject* module) {
1509 1510 1511
#if PY_VERSION_HEX < 0x030500B1 && \
        (defined(__Pyx_Coroutine_USED) || defined(__Pyx_Generator_USED)) && \
        (!defined(CYTHON_PATCH_ASYNCIO) || CYTHON_PATCH_ASYNCIO)
1512 1513 1514 1515 1516 1517
    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) {
1518
            patch_module = __Pyx_Coroutine_patch_module(
1519
                PyObject_GetAttrString(package, "coroutines"), CSTRING("""\
1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535
coro_types = getattr(_module, '_COROUTINE_TYPES', None)
""")
#ifdef __Pyx_Coroutine_USED
CSTRING("""\
if coro_types is not None and _cython_coroutine_type not in coro_types:
    coro_types = type(coro_types) (tuple(coro_types) + (_cython_coroutine_type,))
""")
#endif
#ifdef __Pyx_Generator_USED
CSTRING("""\
if coro_types is not None and _cython_generator_type not in coro_types:
    coro_types = type(coro_types) (tuple(coro_types) + (_cython_generator_type,))
""")
#endif
CSTRING("""
_module._COROUTINE_TYPES = coro_types
1536
""")
1537
            );
1538
#if PY_VERSION_HEX < 0x03050000
1539 1540 1541 1542 1543
        } else {
            // Py3.4 used to have asyncio.tasks instead of asyncio.coroutines
            PyErr_Clear();
            package = __Pyx_Import(PYIDENT("asyncio.tasks"), NULL, 0);
            if (unlikely(!package)) goto asyncio_done;
1544
            patch_module = __Pyx_Coroutine_patch_module(
1545
                PyObject_GetAttrString(package, "tasks"), CSTRING("""\
1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558
if hasattr(_module, 'iscoroutine'):
    old_coroutine_types = getattr(_module.iscoroutine, '_cython_coroutine_types', None)
    if old_coroutine_types is None or not isinstance(old_coroutine_types, list):
        old_coroutine_types = []
        def cy_wrap(orig_func, type=type, cython_coroutine_types=old_coroutine_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)
""")
#ifdef __Pyx_Coroutine_USED
CSTRING("""\
    if _cython_coroutine_type not in old_coroutine_types: old_coroutine_types.append(_cython_coroutine_type)
1559
""")
1560 1561 1562 1563 1564 1565
#endif
#ifdef __Pyx_Generator_USED
CSTRING("""\
    if _cython_generator_type not in old_coroutine_types: old_coroutine_types.append(_cython_generator_type)
""")
#endif
1566
            );
Stefan Behnel's avatar
Stefan Behnel committed
1567 1568
#endif
// Py<3.5
1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601
        }
        Py_DECREF(package);
        if (unlikely(!patch_module)) goto ignore;
#if PY_VERSION_HEX < 0x03050000
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_GetAttrString(patch_module, "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_DECREF(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;
    }
1602
#else
1603 1604
    // avoid "unused" warning for __Pyx_Coroutine_patch_module()
    if (0) return __Pyx_Coroutine_patch_module(module, NULL);
1605
#endif
1606 1607 1608 1609 1610 1611 1612 1613 1614 1615
    return module;
}


//////////////////// PatchInspect.proto ////////////////////

// run after importing "inspect" to patch Cython generator support into it
static PyObject* __Pyx_patch_inspect(PyObject* module); /*proto*/

//////////////////// PatchInspect ////////////////////
1616
//@requires: PatchModuleWithCoroutine
1617 1618

static PyObject* __Pyx_patch_inspect(PyObject* module) {
1619
#if (defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED)) && (!defined(CYTHON_PATCH_INSPECT) || CYTHON_PATCH_INSPECT)
1620 1621
    static int inspect_patched = 0;
    if (unlikely((!inspect_patched) && module)) {
1622 1623 1624 1625
        module = __Pyx_Coroutine_patch_module(
            module,
#ifdef __Pyx_Generator_USED
            CSTRING("""\
1626 1627 1628 1629 1630 1631 1632
if getattr(_module.isgenerator, '_cython_generator_type', None) is not _cython_generator_type:
    def cy_wrap(orig_func, cython_generator_type=_cython_generator_type, type=type):
        def cy_isgenerator(obj): return type(obj) is cython_generator_type or orig_func(obj)
        cy_isgenerator._cython_generator_type = cython_generator_type
        return cy_isgenerator
    _module.isgenerator = cy_wrap(_module.isgenerator)
""")
1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668
#endif
#ifdef __Pyx_Coroutine_USED
            CSTRING("""\
try:
    _module.iscoroutine
except AttributeError:
    def cy_wrap(cython_coroutine_type=_cython_coroutine_type, type=type):
        try:
            from collections.abc import Coroutine
        except ImportError:
            from collections import Coroutine
        def cy_iscoroutine(obj): return isinstance(obj, Coroutine)
        return cy_iscoroutine

    try:
        _module.iscoroutine = cy_wrap()
    except ImportError:
        pass

try:
    _module.isawaitable
except AttributeError:
    def cy_wrap(cython_coroutine_type=_cython_coroutine_type, type=type):
        try:
            from collections.abc import Awaitable
        except ImportError:
            from collections import Awaitable
        def cy_isawaitable(obj): return isinstance(obj, Awaitable)
        return cy_isawaitable

    try:
        _module.isawaitable = cy_wrap()
    except ImportError:
        pass
""")
#endif
1669 1670 1671
        );
        inspect_patched = 1;
    }
1672
#else
1673 1674
    // avoid "unused" warning for __Pyx_Coroutine_patch_module()
    if (0) return __Pyx_Coroutine_patch_module(module, NULL);
1675
#endif
1676 1677
    return module;
}
1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773


//////////////////// StopAsyncIteration.proto ////////////////////

#define __Pyx_StopAsyncIteration_USED
static PyObject *__Pyx_PyExc_StopAsyncIteration;
static int __pyx_StopAsyncIteration_init(void); /*proto*/

//////////////////// StopAsyncIteration ////////////////////

#if PY_VERSION_HEX < 0x030500B1
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*/
#if PY_MAJOR_VERSION < 3
    0,                                  /*tp_compare*/
#else
    0,                                  /*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_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
};
#endif

static int __pyx_StopAsyncIteration_init(void) {
#if PY_VERSION_HEX >= 0x030500B1
    __Pyx_PyExc_StopAsyncIteration = PyExc_StopAsyncIteration;
#else
    PyObject *builtins = PyEval_GetBuiltins();
    if (likely(builtins)) {
        PyObject *exc = PyMapping_GetItemString(builtins, "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, "StopAsyncIteration", __Pyx_PyExc_StopAsyncIteration) < 0))
        return -1;
#endif
    return 0;
}