1 //////////////////// YieldFrom.proto ////////////////////
3 static CYTHON_INLINE PyObject
* __Pyx_Generator_Yield_From(__pyx_GeneratorObject
*gen
, PyObject
*source
);
5 //////////////////// YieldFrom ////////////////////
8 static CYTHON_INLINE PyObject
* __Pyx_Generator_Yield_From(__pyx_GeneratorObject
*gen
, PyObject
*source
) {
9 PyObject
*source_gen
, *retval
;
10 source_gen
= PyObject_GetIter(source
);
11 if (unlikely(!source_gen
))
13 /* source_gen is now the iterator, make the first next() call */
14 retval
= Py_TYPE(source_gen
)->tp_iternext(source_gen
);
16 gen
->yieldfrom
= source_gen
;
19 Py_DECREF(source_gen
);
23 //////////////////// Generator.proto ////////////////////
24 #define __Pyx_Generator_USED
25 #include <structmember.h>
26 #include <frameobject.h>
28 typedef PyObject
*(*__pyx_generator_body_t
)(PyObject
*, PyObject
*);
32 __pyx_generator_body_t body
;
36 PyObject
*exc_traceback
;
37 PyObject
*gi_weakreflist
;
41 // using T_BOOL for property below requires char value
43 } __pyx_GeneratorObject
;
45 static __pyx_GeneratorObject
*__Pyx_Generator_New(__pyx_generator_body_t body
,
47 static int __pyx_Generator_init(void);
48 static int __Pyx_Generator_clear(PyObject
* self
);
50 #if 1 || PY_VERSION_HEX < 0x030300B0
51 static int __Pyx_PyGen_FetchStopIterationValue(PyObject
**pvalue
);
53 #define __Pyx_PyGen_FetchStopIterationValue(pvalue) PyGen_FetchStopIterationValue(pvalue)
56 //////////////////// Generator ////////////////////
57 //@requires: Exceptions.c::PyErrFetchRestore
58 //@requires: Exceptions.c::SwapException
59 //@requires: Exceptions.c::RaiseException
60 //@requires: ObjectHandling.c::PyObjectCallMethod
61 //@requires: CommonTypes.c::FetchCommonType
63 static PyObject
*__Pyx_Generator_Next(PyObject
*self
);
64 static PyObject
*__Pyx_Generator_Send(PyObject
*self
, PyObject
*value
);
65 static PyObject
*__Pyx_Generator_Close(PyObject
*self
);
66 static PyObject
*__Pyx_Generator_Throw(PyObject
*gen
, PyObject
*args
);
68 static PyTypeObject
*__pyx_GeneratorType
= 0;
70 #define __Pyx_Generator_CheckExact(obj) (Py_TYPE(obj) == __pyx_GeneratorType)
71 #define __Pyx_Generator_Undelegate(gen) Py_CLEAR((gen)->yieldfrom)
73 // If StopIteration exception is set, fetches its 'value'
74 // attribute if any, otherwise sets pvalue to None.
76 // Returns 0 if no exception or StopIteration is set.
77 // If any other exception is set, returns -1 and leaves
79 #if 1 || PY_VERSION_HEX < 0x030300B0
80 static int __Pyx_PyGen_FetchStopIterationValue(PyObject
**pvalue
) {
81 PyObject
*et
, *ev
, *tb
;
82 PyObject
*value
= NULL
;
84 __Pyx_ErrFetch(&et
, &ev
, &tb
);
94 if (unlikely(et
!= PyExc_StopIteration
) &&
95 unlikely(!PyErr_GivenExceptionMatches(et
, PyExc_StopIteration
))) {
96 __Pyx_ErrRestore(et
, ev
, tb
);
100 // most common case: plain StopIteration without or with separate argument
101 if (likely(et
== PyExc_StopIteration
)) {
102 if (likely(!ev
) || !PyObject_IsInstance(ev
, PyExc_StopIteration
)) {
103 // PyErr_SetObject() and friends put the value directly into ev
114 // otherwise: normalise and check what that gives us
115 PyErr_NormalizeException(&et
, &ev
, &tb
);
116 if (unlikely(!PyObject_IsInstance(ev
, PyExc_StopIteration
))) {
117 // looks like normalisation failed - raise the new exception
118 __Pyx_ErrRestore(et
, ev
, tb
);
123 #if PY_VERSION_HEX >= 0x030300A0
124 value
= ((PyStopIterationObject
*)ev
)->value
;
129 PyObject
* args
= PyObject_GetAttr(ev
, PYIDENT("args"));
132 value
= PyObject_GetItem(args
, 0);
135 if (unlikely(!value
)) {
136 __Pyx_ErrRestore(NULL
, NULL
, NULL
);
148 void __Pyx_Generator_ExceptionClear(__pyx_GeneratorObject
*self
) {
149 PyObject
*exc_type
= self
->exc_type
;
150 PyObject
*exc_value
= self
->exc_value
;
151 PyObject
*exc_traceback
= self
->exc_traceback
;
153 self
->exc_type
= NULL
;
154 self
->exc_value
= NULL
;
155 self
->exc_traceback
= NULL
;
157 Py_XDECREF(exc_type
);
158 Py_XDECREF(exc_value
);
159 Py_XDECREF(exc_traceback
);
163 int __Pyx_Generator_CheckRunning(__pyx_GeneratorObject
*gen
) {
164 if (unlikely(gen
->is_running
)) {
165 PyErr_SetString(PyExc_ValueError
,
166 "generator already executing");
173 PyObject
*__Pyx_Generator_SendEx(__pyx_GeneratorObject
*self
, PyObject
*value
) {
176 assert(!self
->is_running
);
178 if (unlikely(self
->resume_label
== 0)) {
179 if (unlikely(value
&& value
!= Py_None
)) {
180 PyErr_SetString(PyExc_TypeError
,
181 "can't send non-None value to a "
182 "just-started generator");
187 if (unlikely(self
->resume_label
== -1)) {
188 PyErr_SetNone(PyExc_StopIteration
);
194 #if CYTHON_COMPILING_IN_PYPY
195 // FIXME: what to do in PyPy?
197 /* Generators always return to their most recent caller, not
198 * necessarily their creator. */
199 if (self
->exc_traceback
) {
200 PyThreadState
*tstate
= PyThreadState_GET();
201 PyTracebackObject
*tb
= (PyTracebackObject
*) self
->exc_traceback
;
202 PyFrameObject
*f
= tb
->tb_frame
;
204 Py_XINCREF(tstate
->frame
);
205 assert(f
->f_back
== NULL
);
206 f
->f_back
= tstate
->frame
;
209 __Pyx_ExceptionSwap(&self
->exc_type
, &self
->exc_value
,
210 &self
->exc_traceback
);
212 __Pyx_Generator_ExceptionClear(self
);
215 self
->is_running
= 1;
216 retval
= self
->body((PyObject
*) self
, value
);
217 self
->is_running
= 0;
220 __Pyx_ExceptionSwap(&self
->exc_type
, &self
->exc_value
,
221 &self
->exc_traceback
);
222 #if CYTHON_COMPILING_IN_PYPY
223 // FIXME: what to do in PyPy?
225 /* Don't keep the reference to f_back any longer than necessary. It
226 * may keep a chain of frames alive or it could create a reference
228 if (self
->exc_traceback
) {
229 PyTracebackObject
*tb
= (PyTracebackObject
*) self
->exc_traceback
;
230 PyFrameObject
*f
= tb
->tb_frame
;
235 __Pyx_Generator_ExceptionClear(self
);
242 PyObject
*__Pyx_Generator_FinishDelegation(__pyx_GeneratorObject
*gen
) {
244 PyObject
*val
= NULL
;
245 __Pyx_Generator_Undelegate(gen
);
246 __Pyx_PyGen_FetchStopIterationValue(&val
);
247 // val == NULL on failure => pass on exception
248 ret
= __Pyx_Generator_SendEx(gen
, val
);
253 static PyObject
*__Pyx_Generator_Next(PyObject
*self
) {
254 __pyx_GeneratorObject
*gen
= (__pyx_GeneratorObject
*) self
;
255 PyObject
*yf
= gen
->yieldfrom
;
256 if (unlikely(__Pyx_Generator_CheckRunning(gen
)))
260 // FIXME: does this really need an INCREF() ?
262 /* YieldFrom code ensures that yf is an iterator */
264 ret
= Py_TYPE(yf
)->tp_iternext(yf
);
270 return __Pyx_Generator_FinishDelegation(gen
);
272 return __Pyx_Generator_SendEx(gen
, Py_None
);
275 static PyObject
*__Pyx_Generator_Send(PyObject
*self
, PyObject
*value
) {
276 __pyx_GeneratorObject
*gen
= (__pyx_GeneratorObject
*) self
;
277 PyObject
*yf
= gen
->yieldfrom
;
278 if (unlikely(__Pyx_Generator_CheckRunning(gen
)))
282 // FIXME: does this really need an INCREF() ?
285 if (__Pyx_Generator_CheckExact(yf
)) {
286 ret
= __Pyx_Generator_Send(yf
, value
);
288 if (value
== Py_None
)
289 ret
= PyIter_Next(yf
);
291 ret
= __Pyx_PyObject_CallMethod1(yf
, PYIDENT("send"), value
);
298 return __Pyx_Generator_FinishDelegation(gen
);
300 return __Pyx_Generator_SendEx(gen
, value
);
303 // This helper function is used by gen_close and gen_throw to
304 // close a subiterator being delegated to by yield-from.
305 static int __Pyx_Generator_CloseIter(__pyx_GeneratorObject
*gen
, PyObject
*yf
) {
306 PyObject
*retval
= NULL
;
309 if (__Pyx_Generator_CheckExact(yf
)) {
310 retval
= __Pyx_Generator_Close(yf
);
316 meth
= PyObject_GetAttr(yf
, PYIDENT("close"));
317 if (unlikely(!meth
)) {
318 if (!PyErr_ExceptionMatches(PyExc_AttributeError
)) {
319 PyErr_WriteUnraisable(yf
);
323 retval
= PyObject_CallFunction(meth
, NULL
);
334 static PyObject
*__Pyx_Generator_Close(PyObject
*self
) {
335 __pyx_GeneratorObject
*gen
= (__pyx_GeneratorObject
*) self
;
336 PyObject
*retval
, *raised_exception
;
337 PyObject
*yf
= gen
->yieldfrom
;
340 if (unlikely(__Pyx_Generator_CheckRunning(gen
)))
345 err
= __Pyx_Generator_CloseIter(gen
, yf
);
346 __Pyx_Generator_Undelegate(gen
);
350 #if PY_VERSION_HEX < 0x02050000
351 PyErr_SetNone(PyExc_StopIteration
);
353 PyErr_SetNone(PyExc_GeneratorExit
);
355 retval
= __Pyx_Generator_SendEx(gen
, NULL
);
358 PyErr_SetString(PyExc_RuntimeError
,
359 "generator ignored GeneratorExit");
362 raised_exception
= PyErr_Occurred();
363 if (!raised_exception
364 || raised_exception
== PyExc_StopIteration
365 #if PY_VERSION_HEX >= 0x02050000
366 || raised_exception
== PyExc_GeneratorExit
367 || PyErr_GivenExceptionMatches(raised_exception
, PyExc_GeneratorExit
)
369 || PyErr_GivenExceptionMatches(raised_exception
, PyExc_StopIteration
))
371 if (raised_exception
) PyErr_Clear(); /* ignore these errors */
378 static PyObject
*__Pyx_Generator_Throw(PyObject
*self
, PyObject
*args
) {
379 __pyx_GeneratorObject
*gen
= (__pyx_GeneratorObject
*) self
;
382 PyObject
*val
= NULL
;
383 PyObject
*yf
= gen
->yieldfrom
;
385 if (!PyArg_UnpackTuple(args
, (char *)"throw", 1, 3, &typ
, &val
, &tb
))
388 if (unlikely(__Pyx_Generator_CheckRunning(gen
)))
394 #if PY_VERSION_HEX >= 0x02050000
395 if (PyErr_GivenExceptionMatches(typ
, PyExc_GeneratorExit
)) {
396 int err
= __Pyx_Generator_CloseIter(gen
, yf
);
398 __Pyx_Generator_Undelegate(gen
);
400 return __Pyx_Generator_SendEx(gen
, NULL
);
405 if (__Pyx_Generator_CheckExact(yf
)) {
406 ret
= __Pyx_Generator_Throw(yf
, args
);
408 PyObject
*meth
= PyObject_GetAttr(yf
, PYIDENT("throw"));
409 if (unlikely(!meth
)) {
411 if (!PyErr_ExceptionMatches(PyExc_AttributeError
)) {
416 __Pyx_Generator_Undelegate(gen
);
420 ret
= PyObject_CallObject(meth
, args
);
426 ret
= __Pyx_Generator_FinishDelegation(gen
);
431 __Pyx_Raise(typ
, val
, tb
, NULL
);
432 return __Pyx_Generator_SendEx(gen
, NULL
);
435 static int __Pyx_Generator_traverse(PyObject
*self
, visitproc visit
, void *arg
) {
436 __pyx_GeneratorObject
*gen
= (__pyx_GeneratorObject
*) self
;
438 Py_VISIT(gen
->closure
);
439 Py_VISIT(gen
->classobj
);
440 Py_VISIT(gen
->yieldfrom
);
441 Py_VISIT(gen
->exc_type
);
442 Py_VISIT(gen
->exc_value
);
443 Py_VISIT(gen
->exc_traceback
);
447 static int __Pyx_Generator_clear(PyObject
*self
) {
448 __pyx_GeneratorObject
*gen
= (__pyx_GeneratorObject
*) self
;
450 Py_CLEAR(gen
->closure
);
451 Py_CLEAR(gen
->classobj
);
452 Py_CLEAR(gen
->yieldfrom
);
453 Py_CLEAR(gen
->exc_type
);
454 Py_CLEAR(gen
->exc_value
);
455 Py_CLEAR(gen
->exc_traceback
);
459 static void __Pyx_Generator_dealloc(PyObject
*self
) {
460 __pyx_GeneratorObject
*gen
= (__pyx_GeneratorObject
*) self
;
462 PyObject_GC_UnTrack(gen
);
463 if (gen
->gi_weakreflist
!= NULL
)
464 PyObject_ClearWeakRefs(self
);
466 if (gen
->resume_label
> 0) {
467 /* Generator is paused, so we need to close */
468 PyObject_GC_Track(self
);
469 #if PY_VERSION_HEX >= 0x030400a1
470 if (PyObject_CallFinalizerFromDealloc(self
))
472 Py_TYPE(gen
)->tp_del(self
);
473 if (self
->ob_refcnt
> 0)
475 return; /* resurrected. :( */
476 PyObject_GC_UnTrack(self
);
479 __Pyx_Generator_clear(self
);
480 PyObject_GC_Del(gen
);
483 static void __Pyx_Generator_del(PyObject
*self
) {
485 PyObject
*error_type
, *error_value
, *error_traceback
;
486 __pyx_GeneratorObject
*gen
= (__pyx_GeneratorObject
*) self
;
488 if (gen
->resume_label
<= 0)
491 #if PY_VERSION_HEX < 0x030400a1
492 /* Temporarily resurrect the object. */
493 assert(self
->ob_refcnt
== 0);
497 /* Save the current exception, if any. */
498 __Pyx_ErrFetch(&error_type
, &error_value
, &error_traceback
);
500 res
= __Pyx_Generator_Close(self
);
503 PyErr_WriteUnraisable(self
);
507 /* Restore the saved exception. */
508 __Pyx_ErrRestore(error_type
, error_value
, error_traceback
);
510 #if PY_VERSION_HEX < 0x030400a1
511 /* Undo the temporary resurrection; can't use DECREF here, it would
512 * cause a recursive call.
514 assert(self
->ob_refcnt
> 0);
515 if (--self
->ob_refcnt
== 0)
516 return; /* this is the normal path out */
518 /* close() resurrected it! Make it look like the original Py_DECREF
522 Py_ssize_t refcnt
= self
->ob_refcnt
;
523 _Py_NewReference(self
);
524 self
->ob_refcnt
= refcnt
;
526 #if CYTHON_COMPILING_IN_CPYTHON
527 assert(PyType_IS_GC(self
->ob_type
) &&
528 _Py_AS_GC(self
)->gc
.gc_refs
!= _PyGC_REFS_UNTRACKED
);
530 /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
531 * we need to undo that. */
534 /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
535 * chain, so no more to do there.
536 * If COUNT_ALLOCS, the original decref bumped tp_frees, and
537 * _Py_NewReference bumped tp_allocs: both of those need to be
541 --Py_TYPE(self
)->tp_frees
;
542 --Py_TYPE(self
)->tp_allocs
;
547 static PyMemberDef __pyx_Generator_memberlist
[] = {
548 {(char *) "gi_running",
549 #if PY_VERSION_HEX >= 0x02060000
554 offsetof(__pyx_GeneratorObject
, is_running
),
560 static PyMethodDef __pyx_Generator_methods
[] = {
561 {__Pyx_NAMESTR("send"), (PyCFunction
) __Pyx_Generator_Send
, METH_O
, 0},
562 {__Pyx_NAMESTR("throw"), (PyCFunction
) __Pyx_Generator_Throw
, METH_VARARGS
, 0},
563 {__Pyx_NAMESTR("close"), (PyCFunction
) __Pyx_Generator_Close
, METH_NOARGS
, 0},
567 static PyTypeObject __pyx_GeneratorType_type
= {
568 PyVarObject_HEAD_INIT(0, 0)
569 __Pyx_NAMESTR("generator"), /*tp_name*/
570 sizeof(__pyx_GeneratorObject
), /*tp_basicsize*/
572 (destructor
) __Pyx_Generator_dealloc
,/*tp_dealloc*/
576 #if PY_MAJOR_VERSION < 3
583 0, /*tp_as_sequence*/
591 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
| Py_TPFLAGS_HAVE_FINALIZE
, /* tp_flags*/
593 (traverseproc
) __Pyx_Generator_traverse
, /*tp_traverse*/
595 0, /*tp_richcompare*/
596 offsetof(__pyx_GeneratorObject
, gi_weakreflist
), /* tp_weaklistoffse */
598 (iternextfunc
) __Pyx_Generator_Next
, /*tp_iternext*/
599 __pyx_Generator_methods
, /*tp_methods*/
600 __pyx_Generator_memberlist
, /*tp_members*/
617 #if PY_VERSION_HEX >= 0x030400a1
620 __Pyx_Generator_del
, /*tp_del*/
622 #if PY_VERSION_HEX >= 0x02060000
623 0, /*tp_version_tag*/
625 #if PY_VERSION_HEX >= 0x030400a1
626 __Pyx_Generator_del
, /*tp_finalize*/
630 static __pyx_GeneratorObject
*__Pyx_Generator_New(__pyx_generator_body_t body
,
632 __pyx_GeneratorObject
*gen
=
633 PyObject_GC_New(__pyx_GeneratorObject
, &__pyx_GeneratorType_type
);
639 gen
->closure
= closure
;
642 gen
->resume_label
= 0;
643 gen
->classobj
= NULL
;
644 gen
->yieldfrom
= NULL
;
645 gen
->exc_type
= NULL
;
646 gen
->exc_value
= NULL
;
647 gen
->exc_traceback
= NULL
;
648 gen
->gi_weakreflist
= NULL
;
650 PyObject_GC_Track(gen
);
654 static int __pyx_Generator_init(void) {
655 /* on Windows, C-API functions can't be used in slots statically */
656 __pyx_GeneratorType_type
.tp_getattro
= PyObject_GenericGetAttr
;
657 __pyx_GeneratorType_type
.tp_iter
= PyObject_SelfIter
;
659 __pyx_GeneratorType
= __Pyx_FetchCommonType(&__pyx_GeneratorType_type
);
660 if (__pyx_GeneratorType
== NULL
) {