mirror of
https://github.com/python/cpython.git
synced 2025-12-31 04:23:37 +00:00
gh-105201: Add PyIter_NextItem() (#122331)
Return -1 and set an exception on error; return 0 if the iterator is exhausted, and return 1 if the next item was fetched successfully. Prefer this API to PyIter_Next(), which requires the caller to use PyErr_Occurred() to differentiate between iterator exhaustion and errors. Co-authered-by: Irit Katriel <iritkatriel@yahoo.com>
This commit is contained in:
parent
540fcc62f5
commit
e006c7371d
12 changed files with 156 additions and 40 deletions
|
|
@ -2881,7 +2881,50 @@ PyAIter_Check(PyObject *obj)
|
|||
tp->tp_as_async->am_anext != &_PyObject_NextNotImplemented);
|
||||
}
|
||||
|
||||
static int
|
||||
iternext(PyObject *iter, PyObject **item)
|
||||
{
|
||||
iternextfunc tp_iternext = Py_TYPE(iter)->tp_iternext;
|
||||
if ((*item = tp_iternext(iter))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
/* When the iterator is exhausted it must return NULL;
|
||||
* a StopIteration exception may or may not be set. */
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
return 0;
|
||||
}
|
||||
if (_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) {
|
||||
_PyErr_Clear(tstate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Error case: an exception (different than StopIteration) is set. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Return 1 and set 'item' to the next item of 'iter' on success.
|
||||
* Return 0 and set 'item' to NULL when there are no remaining values.
|
||||
* Return -1, set 'item' to NULL and set an exception on error.
|
||||
*/
|
||||
int
|
||||
PyIter_NextItem(PyObject *iter, PyObject **item)
|
||||
{
|
||||
assert(iter != NULL);
|
||||
assert(item != NULL);
|
||||
|
||||
if (Py_TYPE(iter)->tp_iternext == NULL) {
|
||||
*item = NULL;
|
||||
PyErr_Format(PyExc_TypeError, "expected an iterator, got '%T'", iter);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return iternext(iter, item);
|
||||
}
|
||||
|
||||
/* Return next item.
|
||||
*
|
||||
* If an error occurs, return NULL. PyErr_Occurred() will be true.
|
||||
* If the iteration terminates normally, return NULL and clear the
|
||||
* PyExc_StopIteration exception (if it was set). PyErr_Occurred()
|
||||
|
|
@ -2891,17 +2934,9 @@ PyAIter_Check(PyObject *obj)
|
|||
PyObject *
|
||||
PyIter_Next(PyObject *iter)
|
||||
{
|
||||
PyObject *result;
|
||||
result = (*Py_TYPE(iter)->tp_iternext)(iter);
|
||||
if (result == NULL) {
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
if (_PyErr_Occurred(tstate)
|
||||
&& _PyErr_ExceptionMatches(tstate, PyExc_StopIteration))
|
||||
{
|
||||
_PyErr_Clear(tstate);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
PyObject *item;
|
||||
(void)iternext(iter, &item);
|
||||
return item;
|
||||
}
|
||||
|
||||
PySendResult
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue