Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
make PyIter_NextItem return 0 for exhausted iterator and 1 when it pr…
…ovides a new value
  • Loading branch information
iritkatriel committed Jun 1, 2023
commit edc54c8507f0de242c7743452ab488c011591bdf
2 changes: 1 addition & 1 deletion Doc/c-api/iter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ something like this::

PyObject *item;
int res;
while ((res = PyIter_NextItem(iterator, &item)) == 0 && item != NULL) {
while ((res = PyIter_NextItem(iterator, &item)) == 1) {
/* do something with item */
...
/* release reference when done */
Expand Down
3 changes: 2 additions & 1 deletion Include/abstract.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,8 @@ PyAPI_FUNC(int) PyAIter_Check(PyObject *);
setting *item to the next value, or to NULL if the iterator
is exhausted.

Return 0 on success and -1 on error. */
Return 1 if *item was set to a new value, 0 if the iterator is
exhausted and -1 on error. */
PyAPI_FUNC(int) PyIter_NextItem(PyObject *iter, PyObject **item);

/* Takes an iterator object and calls its tp_iternext slot,
Expand Down
6 changes: 5 additions & 1 deletion Modules/_testcapimodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,10 +310,14 @@ call_pyiter_nextitem(PyObject* self, PyObject *args)
if (ret < 0) {
return NULL;
}
if (item == NULL) {
else if (ret == 0) {
assert(item == NULL);
assert(!PyErr_Occurred());
Py_RETURN_NONE;
}
assert(ret == 1);
assert(item != NULL);
assert(!PyErr_Occurred());
return item;
}

Expand Down
2 changes: 1 addition & 1 deletion Modules/_xxtestfuzz/fuzzer.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ static int fuzz_csv_reader(const char* data, size_t size) {
if (reader) {
/* Consume all of the reader as an iterator */
PyObject* parsed_line;
while (PyIter_NextItem(reader, &parsed_line) == 0) {
while (PyIter_NextItem(reader, &parsed_line) == 1) {
Py_DECREF(parsed_line);
}
}
Expand Down
10 changes: 6 additions & 4 deletions Objects/abstract.c
Original file line number Diff line number Diff line change
Expand Up @@ -2833,9 +2833,10 @@ PyAIter_Check(PyObject *obj)
tp->tp_as_async->am_anext != &_PyObject_NextNotImplemented);
}

/* Set *item to the next item. Return 0 on success and -1 on error.
* If the iteration terminates normally, set *item to NULL and clear
* the PyExc_StopIteration exception (if it was set).
/* If the iterator has another value to return, set *item to this value
* and return 1.
* If the iterator is exhausted, set *item to NULL and return 0.
* On error (other than StopIteration) from tp_iternext, return -1.
*/
int
PyIter_NextItem(PyObject *iter, PyObject **item)
Expand All @@ -2852,8 +2853,9 @@ PyIter_NextItem(PyObject *iter, PyObject **item)
return -1;
}
}
return 0;
}
return 0;
return 1;
}

/* Return next item.
Expand Down