summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-05-05 00:14:56 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-05-05 00:14:56 (GMT)
commitf4848dac41689d1f2f8bd224bd935beae9b8df86 (patch)
treec4b33c842f923add9fde5d8e4a4619ab6b0c316b
parent648b4de3d31aab9df142540919accf0cb518e2f3 (diff)
downloadcpython-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.h5
-rw-r--r--Objects/abstract.c27
-rw-r--r--Python/bltinmodule.c61
-rw-r--r--Python/ceval.c8
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;