diff options
author | Tim Peters <tim.peters@gmail.com> | 2001-05-05 00:14:56 (GMT) |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2001-05-05 00:14:56 (GMT) |
commit | f4848dac41689d1f2f8bd224bd935beae9b8df86 (patch) | |
tree | c4b33c842f923add9fde5d8e4a4619ab6b0c316b | |
parent | 648b4de3d31aab9df142540919accf0cb518e2f3 (diff) | |
download | cpython-f4848dac41689d1f2f8bd224bd935beae9b8df86.zip cpython-f4848dac41689d1f2f8bd224bd935beae9b8df86.tar.gz cpython-f4848dac41689d1f2f8bd224bd935beae9b8df86.tar.bz2 |
Make PyIter_Next() a little smarter (wrt its knowledge of iterator
internals) so clients can be a lot dumber (wrt their knowledge).
-rw-r--r-- | Include/abstract.h | 5 | ||||
-rw-r--r-- | Objects/abstract.c | 27 | ||||
-rw-r--r-- | Python/bltinmodule.c | 61 | ||||
-rw-r--r-- | Python/ceval.c | 8 |
4 files changed, 35 insertions, 66 deletions
diff --git a/Include/abstract.h b/Include/abstract.h index 1dae5f1..ac9e568 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -484,9 +484,8 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ DL_IMPORT(PyObject *) PyIter_Next(PyObject *); /* Takes an iterator object and calls its tp_iternext slot, returning the next value. If the iterator is exhausted, - this can return NULL without setting an exception, *or* - NULL with a StopIteration exception. - NULL with any other exception means an error occurred. */ + this returns NULL without setting an exception. + NULL with an exception means an error occurred. */ /* Number Protocol:*/ diff --git a/Objects/abstract.c b/Objects/abstract.c index 8ee1e5a..7133867 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1276,17 +1276,9 @@ PySequence_List(PyObject *v) for (i = 0; ; i++) { PyObject *item = PyIter_Next(it); if (item == NULL) { - /* We're out of here in any case, but if this is a - * StopIteration exception it's expected, but if - * any other kind of exception it's an error. - */ if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_StopIteration)) - PyErr_Clear(); - else { - Py_DECREF(result); - result = NULL; - } + Py_DECREF(result); + result = NULL; } break; } @@ -1796,14 +1788,27 @@ PyObject_GetIter(PyObject *o) } } +/* 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() + * will be false. + * Else return the next object. PyErr_Occurred() will be false. + */ PyObject * PyIter_Next(PyObject *iter) { + PyObject *result; if (!PyIter_Check(iter)) { PyErr_Format(PyExc_TypeError, "'%.100s' object is not an iterator", iter->ob_type->tp_name); return NULL; } - return (*iter->ob_type->tp_iternext)(iter); + result = (*iter->ob_type->tp_iternext)(iter); + if (result == NULL && + PyErr_Occurred() && + PyErr_ExceptionMatches(PyExc_StopIteration)) + PyErr_Clear(); + return result; } diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 5209607..4a51ccd 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -164,7 +164,7 @@ builtin_filter(PyObject *self, PyObject *args) { PyObject *func, *seq, *result, *it; int len; /* guess for result list size */ - register int i, j; + register int j; if (!PyArg_ParseTuple(args, "OO:filter", &func, &seq)) return NULL; @@ -204,22 +204,15 @@ builtin_filter(PyObject *self, PyObject *args) } /* Build the result list. */ - for (i = j = 0; ; ++i) { + j = 0; + for (;;) { PyObject *item, *good; int ok; item = PyIter_Next(it); if (item == NULL) { - /* We're out of here in any case, but if this is a - * StopIteration exception it's expected, but if - * any other kind of exception it's an error. - */ - if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_StopIteration)) - PyErr_Clear(); - else - goto Fail_result_it; - } + if (PyErr_Occurred()) + goto Fail_result_it; break; } @@ -1030,24 +1023,14 @@ builtin_map(PyObject *self, PyObject *args) if (item) ++numactive; else { - /* StopIteration is *implied* by a - * NULL return from PyIter_Next() if - * PyErr_Occurred() is false. - */ if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches( - PyExc_StopIteration)) - PyErr_Clear(); - else { - Py_XDECREF(alist); - goto Fail_1; - } + Py_XDECREF(alist); + goto Fail_1; } Py_INCREF(Py_None); item = Py_None; sqp->saw_StopIteration = 1; } - } if (alist) PyTuple_SET_ITEM(alist, j, item); @@ -1445,7 +1428,6 @@ Return the dictionary containing the current scope's local variables."; static PyObject * min_max(PyObject *args, int op) { - int i; PyObject *v, *w, *x, *it; if (PyTuple_Size(args) > 1) @@ -1458,21 +1440,13 @@ min_max(PyObject *args, int op) return NULL; w = NULL; /* the result */ - for (i = 0; ; i++) { + for (;;) { x = PyIter_Next(it); if (x == NULL) { - /* We're out of here in any case, but if this is a - * StopIteration exception it's expected, but if - * any other kind of exception it's an error. - */ if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_StopIteration)) - PyErr_Clear(); - else { - Py_XDECREF(w); - Py_DECREF(it); - return NULL; - } + Py_XDECREF(w); + Py_DECREF(it); + return NULL; } break; } @@ -1880,16 +1854,9 @@ builtin_reduce(PyObject *self, PyObject *args) op2 = PyIter_Next(it); if (op2 == NULL) { - /* StopIteration is *implied* by a NULL return from - * PyIter_Next() if PyErr_Occurred() is false. - */ - if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_StopIteration)) - PyErr_Clear(); - else - goto Fail; - } - break; + if (PyErr_Occurred()) + goto Fail; + break; } if (result == NULL) diff --git a/Python/ceval.c b/Python/ceval.c index df160f2..0cdd019 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1894,11 +1894,9 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, PUSH(x); continue; } - if (!PyErr_Occurred() || - PyErr_ExceptionMatches( - PyExc_StopIteration)) - { - x = v = POP(); + if (!PyErr_Occurred()) { + /* iterator ended normally */ + x = v = POP(); Py_DECREF(v); JUMPBY(oparg); continue; |