1 /* Iterator objects */
2 
3 #include "Python.h"
4 #include "pycore_call.h"          // _PyObject_CallNoArgs()
5 #include "pycore_object.h"        // _PyObject_GC_TRACK()
6 
7 typedef struct {
8     PyObject_HEAD
9     Py_ssize_t it_index;
10     PyObject *it_seq; /* Set to NULL when iterator is exhausted */
11 } seqiterobject;
12 
13 PyObject *
PySeqIter_New(PyObject * seq)14 PySeqIter_New(PyObject *seq)
15 {
16     seqiterobject *it;
17 
18     if (!PySequence_Check(seq)) {
19         PyErr_BadInternalCall();
20         return NULL;
21     }
22     it = PyObject_GC_New(seqiterobject, &PySeqIter_Type);
23     if (it == NULL)
24         return NULL;
25     it->it_index = 0;
26     Py_INCREF(seq);
27     it->it_seq = seq;
28     _PyObject_GC_TRACK(it);
29     return (PyObject *)it;
30 }
31 
32 static void
iter_dealloc(seqiterobject * it)33 iter_dealloc(seqiterobject *it)
34 {
35     _PyObject_GC_UNTRACK(it);
36     Py_XDECREF(it->it_seq);
37     PyObject_GC_Del(it);
38 }
39 
40 static int
iter_traverse(seqiterobject * it,visitproc visit,void * arg)41 iter_traverse(seqiterobject *it, visitproc visit, void *arg)
42 {
43     Py_VISIT(it->it_seq);
44     return 0;
45 }
46 
47 static PyObject *
iter_iternext(PyObject * iterator)48 iter_iternext(PyObject *iterator)
49 {
50     seqiterobject *it;
51     PyObject *seq;
52     PyObject *result;
53 
54     assert(PySeqIter_Check(iterator));
55     it = (seqiterobject *)iterator;
56     seq = it->it_seq;
57     if (seq == NULL)
58         return NULL;
59     if (it->it_index == PY_SSIZE_T_MAX) {
60         PyErr_SetString(PyExc_OverflowError,
61                         "iter index too large");
62         return NULL;
63     }
64 
65     result = PySequence_GetItem(seq, it->it_index);
66     if (result != NULL) {
67         it->it_index++;
68         return result;
69     }
70     if (PyErr_ExceptionMatches(PyExc_IndexError) ||
71         PyErr_ExceptionMatches(PyExc_StopIteration))
72     {
73         PyErr_Clear();
74         it->it_seq = NULL;
75         Py_DECREF(seq);
76     }
77     return NULL;
78 }
79 
80 static PyObject *
iter_len(seqiterobject * it,PyObject * Py_UNUSED (ignored))81 iter_len(seqiterobject *it, PyObject *Py_UNUSED(ignored))
82 {
83     Py_ssize_t seqsize, len;
84 
85     if (it->it_seq) {
86         if (_PyObject_HasLen(it->it_seq)) {
87             seqsize = PySequence_Size(it->it_seq);
88             if (seqsize == -1)
89                 return NULL;
90         }
91         else {
92             Py_RETURN_NOTIMPLEMENTED;
93         }
94         len = seqsize - it->it_index;
95         if (len >= 0)
96             return PyLong_FromSsize_t(len);
97     }
98     return PyLong_FromLong(0);
99 }
100 
101 PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
102 
103 static PyObject *
iter_reduce(seqiterobject * it,PyObject * Py_UNUSED (ignored))104 iter_reduce(seqiterobject *it, PyObject *Py_UNUSED(ignored))
105 {
106     PyObject *iter = _PyEval_GetBuiltin(&_Py_ID(iter));
107 
108     /* _PyEval_GetBuiltin can invoke arbitrary code,
109      * call must be before access of iterator pointers.
110      * see issue #101765 */
111 
112     if (it->it_seq != NULL)
113         return Py_BuildValue("N(O)n", iter, it->it_seq, it->it_index);
114     else
115         return Py_BuildValue("N(())", iter);
116 }
117 
118 PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
119 
120 static PyObject *
iter_setstate(seqiterobject * it,PyObject * state)121 iter_setstate(seqiterobject *it, PyObject *state)
122 {
123     Py_ssize_t index = PyLong_AsSsize_t(state);
124     if (index == -1 && PyErr_Occurred())
125         return NULL;
126     if (it->it_seq != NULL) {
127         if (index < 0)
128             index = 0;
129         it->it_index = index;
130     }
131     Py_RETURN_NONE;
132 }
133 
134 PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
135 
136 static PyMethodDef seqiter_methods[] = {
137     {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc},
138     {"__reduce__", (PyCFunction)iter_reduce, METH_NOARGS, reduce_doc},
139     {"__setstate__", (PyCFunction)iter_setstate, METH_O, setstate_doc},
140     {NULL,              NULL}           /* sentinel */
141 };
142 
143 PyTypeObject PySeqIter_Type = {
144     PyVarObject_HEAD_INIT(&PyType_Type, 0)
145     "iterator",                                 /* tp_name */
146     sizeof(seqiterobject),                      /* tp_basicsize */
147     0,                                          /* tp_itemsize */
148     /* methods */
149     (destructor)iter_dealloc,                   /* tp_dealloc */
150     0,                                          /* tp_vectorcall_offset */
151     0,                                          /* tp_getattr */
152     0,                                          /* tp_setattr */
153     0,                                          /* tp_as_async */
154     0,                                          /* tp_repr */
155     0,                                          /* tp_as_number */
156     0,                                          /* tp_as_sequence */
157     0,                                          /* tp_as_mapping */
158     0,                                          /* tp_hash */
159     0,                                          /* tp_call */
160     0,                                          /* tp_str */
161     PyObject_GenericGetAttr,                    /* tp_getattro */
162     0,                                          /* tp_setattro */
163     0,                                          /* tp_as_buffer */
164     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
165     0,                                          /* tp_doc */
166     (traverseproc)iter_traverse,                /* tp_traverse */
167     0,                                          /* tp_clear */
168     0,                                          /* tp_richcompare */
169     0,                                          /* tp_weaklistoffset */
170     PyObject_SelfIter,                          /* tp_iter */
171     iter_iternext,                              /* tp_iternext */
172     seqiter_methods,                            /* tp_methods */
173     0,                                          /* tp_members */
174 };
175 
176 /* -------------------------------------- */
177 
178 typedef struct {
179     PyObject_HEAD
180     PyObject *it_callable; /* Set to NULL when iterator is exhausted */
181     PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
182 } calliterobject;
183 
184 PyObject *
PyCallIter_New(PyObject * callable,PyObject * sentinel)185 PyCallIter_New(PyObject *callable, PyObject *sentinel)
186 {
187     calliterobject *it;
188     it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
189     if (it == NULL)
190         return NULL;
191     Py_INCREF(callable);
192     it->it_callable = callable;
193     Py_INCREF(sentinel);
194     it->it_sentinel = sentinel;
195     _PyObject_GC_TRACK(it);
196     return (PyObject *)it;
197 }
198 static void
calliter_dealloc(calliterobject * it)199 calliter_dealloc(calliterobject *it)
200 {
201     _PyObject_GC_UNTRACK(it);
202     Py_XDECREF(it->it_callable);
203     Py_XDECREF(it->it_sentinel);
204     PyObject_GC_Del(it);
205 }
206 
207 static int
calliter_traverse(calliterobject * it,visitproc visit,void * arg)208 calliter_traverse(calliterobject *it, visitproc visit, void *arg)
209 {
210     Py_VISIT(it->it_callable);
211     Py_VISIT(it->it_sentinel);
212     return 0;
213 }
214 
215 static PyObject *
calliter_iternext(calliterobject * it)216 calliter_iternext(calliterobject *it)
217 {
218     PyObject *result;
219 
220     if (it->it_callable == NULL) {
221         return NULL;
222     }
223 
224     result = _PyObject_CallNoArgs(it->it_callable);
225     if (result != NULL && it->it_sentinel != NULL){
226         int ok;
227 
228         ok = PyObject_RichCompareBool(it->it_sentinel, result, Py_EQ);
229         if (ok == 0) {
230             return result; /* Common case, fast path */
231         }
232 
233         if (ok > 0) {
234             Py_CLEAR(it->it_callable);
235             Py_CLEAR(it->it_sentinel);
236         }
237     }
238     else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
239         PyErr_Clear();
240         Py_CLEAR(it->it_callable);
241         Py_CLEAR(it->it_sentinel);
242     }
243     Py_XDECREF(result);
244     return NULL;
245 }
246 
247 static PyObject *
calliter_reduce(calliterobject * it,PyObject * Py_UNUSED (ignored))248 calliter_reduce(calliterobject *it, PyObject *Py_UNUSED(ignored))
249 {
250     PyObject *iter = _PyEval_GetBuiltin(&_Py_ID(iter));
251 
252     /* _PyEval_GetBuiltin can invoke arbitrary code,
253      * call must be before access of iterator pointers.
254      * see issue #101765 */
255 
256     if (it->it_callable != NULL && it->it_sentinel != NULL)
257         return Py_BuildValue("N(OO)", iter, it->it_callable, it->it_sentinel);
258     else
259         return Py_BuildValue("N(())", iter);
260 }
261 
262 static PyMethodDef calliter_methods[] = {
263     {"__reduce__", (PyCFunction)calliter_reduce, METH_NOARGS, reduce_doc},
264     {NULL,              NULL}           /* sentinel */
265 };
266 
267 PyTypeObject PyCallIter_Type = {
268     PyVarObject_HEAD_INIT(&PyType_Type, 0)
269     "callable_iterator",                        /* tp_name */
270     sizeof(calliterobject),                     /* tp_basicsize */
271     0,                                          /* tp_itemsize */
272     /* methods */
273     (destructor)calliter_dealloc,               /* tp_dealloc */
274     0,                                          /* tp_vectorcall_offset */
275     0,                                          /* tp_getattr */
276     0,                                          /* tp_setattr */
277     0,                                          /* tp_as_async */
278     0,                                          /* tp_repr */
279     0,                                          /* tp_as_number */
280     0,                                          /* tp_as_sequence */
281     0,                                          /* tp_as_mapping */
282     0,                                          /* tp_hash */
283     0,                                          /* tp_call */
284     0,                                          /* tp_str */
285     PyObject_GenericGetAttr,                    /* tp_getattro */
286     0,                                          /* tp_setattro */
287     0,                                          /* tp_as_buffer */
288     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
289     0,                                          /* tp_doc */
290     (traverseproc)calliter_traverse,            /* tp_traverse */
291     0,                                          /* tp_clear */
292     0,                                          /* tp_richcompare */
293     0,                                          /* tp_weaklistoffset */
294     PyObject_SelfIter,                          /* tp_iter */
295     (iternextfunc)calliter_iternext,            /* tp_iternext */
296     calliter_methods,                           /* tp_methods */
297 };
298 
299 
300 /* -------------------------------------- */
301 
302 typedef struct {
303     PyObject_HEAD
304     PyObject *wrapped;
305     PyObject *default_value;
306 } anextawaitableobject;
307 
308 static void
anextawaitable_dealloc(anextawaitableobject * obj)309 anextawaitable_dealloc(anextawaitableobject *obj)
310 {
311     _PyObject_GC_UNTRACK(obj);
312     Py_XDECREF(obj->wrapped);
313     Py_XDECREF(obj->default_value);
314     PyObject_GC_Del(obj);
315 }
316 
317 static int
anextawaitable_traverse(anextawaitableobject * obj,visitproc visit,void * arg)318 anextawaitable_traverse(anextawaitableobject *obj, visitproc visit, void *arg)
319 {
320     Py_VISIT(obj->wrapped);
321     Py_VISIT(obj->default_value);
322     return 0;
323 }
324 
325 static PyObject *
anextawaitable_getiter(anextawaitableobject * obj)326 anextawaitable_getiter(anextawaitableobject *obj)
327 {
328     assert(obj->wrapped != NULL);
329     PyObject *awaitable = _PyCoro_GetAwaitableIter(obj->wrapped);
330     if (awaitable == NULL) {
331         return NULL;
332     }
333     if (Py_TYPE(awaitable)->tp_iternext == NULL) {
334         /* _PyCoro_GetAwaitableIter returns a Coroutine, a Generator,
335          * or an iterator. Of these, only coroutines lack tp_iternext.
336          */
337         assert(PyCoro_CheckExact(awaitable));
338         unaryfunc getter = Py_TYPE(awaitable)->tp_as_async->am_await;
339         PyObject *new_awaitable = getter(awaitable);
340         if (new_awaitable == NULL) {
341             Py_DECREF(awaitable);
342             return NULL;
343         }
344         Py_SETREF(awaitable, new_awaitable);
345         if (!PyIter_Check(awaitable)) {
346             PyErr_SetString(PyExc_TypeError,
347                             "__await__ returned a non-iterable");
348             Py_DECREF(awaitable);
349             return NULL;
350         }
351     }
352     return awaitable;
353 }
354 
355 static PyObject *
anextawaitable_iternext(anextawaitableobject * obj)356 anextawaitable_iternext(anextawaitableobject *obj)
357 {
358     /* Consider the following class:
359      *
360      *     class A:
361      *         async def __anext__(self):
362      *             ...
363      *     a = A()
364      *
365      * Then `await anext(a)` should call
366      * a.__anext__().__await__().__next__()
367      *
368      * On the other hand, given
369      *
370      *     async def agen():
371      *         yield 1
372      *         yield 2
373      *     gen = agen()
374      *
375      * Then `await anext(gen)` can just call
376      * gen.__anext__().__next__()
377      */
378     PyObject *awaitable = anextawaitable_getiter(obj);
379     if (awaitable == NULL) {
380         return NULL;
381     }
382     PyObject *result = (*Py_TYPE(awaitable)->tp_iternext)(awaitable);
383     Py_DECREF(awaitable);
384     if (result != NULL) {
385         return result;
386     }
387     if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration)) {
388         _PyGen_SetStopIterationValue(obj->default_value);
389     }
390     return NULL;
391 }
392 
393 
394 static PyObject *
anextawaitable_proxy(anextawaitableobject * obj,char * meth,PyObject * arg)395 anextawaitable_proxy(anextawaitableobject *obj, char *meth, PyObject *arg) {
396     PyObject *awaitable = anextawaitable_getiter(obj);
397     if (awaitable == NULL) {
398         return NULL;
399     }
400     PyObject *ret = PyObject_CallMethod(awaitable, meth, "O", arg);
401     Py_DECREF(awaitable);
402     if (ret != NULL) {
403         return ret;
404     }
405     if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration)) {
406         /* `anextawaitableobject` is only used by `anext()` when
407          * a default value is provided. So when we have a StopAsyncIteration
408          * exception we replace it with a `StopIteration(default)`, as if
409          * it was the return value of `__anext__()` coroutine.
410          */
411         _PyGen_SetStopIterationValue(obj->default_value);
412     }
413     return NULL;
414 }
415 
416 
417 static PyObject *
anextawaitable_send(anextawaitableobject * obj,PyObject * arg)418 anextawaitable_send(anextawaitableobject *obj, PyObject *arg) {
419     return anextawaitable_proxy(obj, "send", arg);
420 }
421 
422 
423 static PyObject *
anextawaitable_throw(anextawaitableobject * obj,PyObject * arg)424 anextawaitable_throw(anextawaitableobject *obj, PyObject *arg) {
425     return anextawaitable_proxy(obj, "throw", arg);
426 }
427 
428 
429 static PyObject *
anextawaitable_close(anextawaitableobject * obj,PyObject * arg)430 anextawaitable_close(anextawaitableobject *obj, PyObject *arg) {
431     return anextawaitable_proxy(obj, "close", arg);
432 }
433 
434 
435 PyDoc_STRVAR(send_doc,
436 "send(arg) -> send 'arg' into the wrapped iterator,\n\
437 return next yielded value or raise StopIteration.");
438 
439 
440 PyDoc_STRVAR(throw_doc,
441 "throw(typ[,val[,tb]]) -> raise exception in the wrapped iterator,\n\
442 return next yielded value or raise StopIteration.");
443 
444 
445 PyDoc_STRVAR(close_doc,
446 "close() -> raise GeneratorExit inside generator.");
447 
448 
449 static PyMethodDef anextawaitable_methods[] = {
450     {"send",(PyCFunction)anextawaitable_send, METH_O, send_doc},
451     {"throw",(PyCFunction)anextawaitable_throw, METH_VARARGS, throw_doc},
452     {"close",(PyCFunction)anextawaitable_close, METH_VARARGS, close_doc},
453     {NULL, NULL}        /* Sentinel */
454 };
455 
456 
457 static PyAsyncMethods anextawaitable_as_async = {
458     PyObject_SelfIter,                          /* am_await */
459     0,                                          /* am_aiter */
460     0,                                          /* am_anext */
461     0,                                          /* am_send  */
462 };
463 
464 PyTypeObject _PyAnextAwaitable_Type = {
465     PyVarObject_HEAD_INIT(&PyType_Type, 0)
466     "anext_awaitable",                          /* tp_name */
467     sizeof(anextawaitableobject),               /* tp_basicsize */
468     0,                                          /* tp_itemsize */
469     /* methods */
470     (destructor)anextawaitable_dealloc,         /* tp_dealloc */
471     0,                                          /* tp_vectorcall_offset */
472     0,                                          /* tp_getattr */
473     0,                                          /* tp_setattr */
474     &anextawaitable_as_async,                   /* tp_as_async */
475     0,                                          /* tp_repr */
476     0,                                          /* tp_as_number */
477     0,                                          /* tp_as_sequence */
478     0,                                          /* tp_as_mapping */
479     0,                                          /* tp_hash */
480     0,                                          /* tp_call */
481     0,                                          /* tp_str */
482     PyObject_GenericGetAttr,                    /* tp_getattro */
483     0,                                          /* tp_setattro */
484     0,                                          /* tp_as_buffer */
485     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
486     0,                                          /* tp_doc */
487     (traverseproc)anextawaitable_traverse,      /* tp_traverse */
488     0,                                          /* tp_clear */
489     0,                                          /* tp_richcompare */
490     0,                                          /* tp_weaklistoffset */
491     PyObject_SelfIter,                          /* tp_iter */
492     (unaryfunc)anextawaitable_iternext,         /* tp_iternext */
493     anextawaitable_methods,                     /* tp_methods */
494 };
495 
496 PyObject *
PyAnextAwaitable_New(PyObject * awaitable,PyObject * default_value)497 PyAnextAwaitable_New(PyObject *awaitable, PyObject *default_value)
498 {
499     anextawaitableobject *anext = PyObject_GC_New(
500             anextawaitableobject, &_PyAnextAwaitable_Type);
501     if (anext == NULL) {
502         return NULL;
503     }
504     Py_INCREF(awaitable);
505     anext->wrapped = awaitable;
506     Py_INCREF(default_value);
507     anext->default_value = default_value;
508     _PyObject_GC_TRACK(anext);
509     return (PyObject *)anext;
510 }
511