Commit 2147df74 authored by Guido van Rossum's avatar Guido van Rossum

Make StopIteration a sink state. This is done by clearing out the

di_dict field when the end of the list is reached.  Also make the
error ("dictionary changed size during iteration") a sticky state.

Also remove the next() method -- one is supplied automatically by
PyType_Ready() because the tp_iternext slot is set.  That's a good
thing, because the implementation given here was buggy (it never
raised StopIteration).
parent 613bed37
...@@ -1916,7 +1916,7 @@ extern PyTypeObject PyDictIter_Type; /* Forward */ ...@@ -1916,7 +1916,7 @@ extern PyTypeObject PyDictIter_Type; /* Forward */
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
dictobject *di_dict; dictobject *di_dict; /* Set to NULL when iterator is exhausted */
int di_used; int di_used;
int di_pos; int di_pos;
binaryfunc di_select; binaryfunc di_select;
...@@ -1940,27 +1940,10 @@ dictiter_new(dictobject *dict, binaryfunc select) ...@@ -1940,27 +1940,10 @@ dictiter_new(dictobject *dict, binaryfunc select)
static void static void
dictiter_dealloc(dictiterobject *di) dictiter_dealloc(dictiterobject *di)
{ {
Py_DECREF(di->di_dict); Py_XDECREF(di->di_dict);
PyObject_Del(di); PyObject_Del(di);
} }
static PyObject *
dictiter_next(dictiterobject *di, PyObject *args)
{
PyObject *key, *value;
if (di->di_used != di->di_dict->ma_used) {
PyErr_SetString(PyExc_RuntimeError,
"dictionary changed size during iteration");
return NULL;
}
if (PyDict_Next((PyObject *)(di->di_dict), &di->di_pos, &key, &value)) {
return (*di->di_select)(key, value);
}
PyErr_SetObject(PyExc_StopIteration, Py_None);
return NULL;
}
static PyObject * static PyObject *
dictiter_getiter(PyObject *it) dictiter_getiter(PyObject *it)
{ {
...@@ -1968,24 +1951,24 @@ dictiter_getiter(PyObject *it) ...@@ -1968,24 +1951,24 @@ dictiter_getiter(PyObject *it)
return it; return it;
} }
static PyMethodDef dictiter_methods[] = {
{"next", (PyCFunction)dictiter_next, METH_VARARGS,
"it.next() -- get the next value, or raise StopIteration"},
{NULL, NULL} /* sentinel */
};
static PyObject *dictiter_iternext(dictiterobject *di) static PyObject *dictiter_iternext(dictiterobject *di)
{ {
PyObject *key, *value; PyObject *key, *value;
if (di->di_dict == NULL)
return NULL;
if (di->di_used != di->di_dict->ma_used) { if (di->di_used != di->di_dict->ma_used) {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
"dictionary changed size during iteration"); "dictionary changed size during iteration");
di->di_used = -1; /* Make this state sticky */
return NULL; return NULL;
} }
if (PyDict_Next((PyObject *)(di->di_dict), &di->di_pos, &key, &value)) { if (PyDict_Next((PyObject *)(di->di_dict), &di->di_pos, &key, &value))
return (*di->di_select)(key, value); return (*di->di_select)(key, value);
}
Py_DECREF(di->di_dict);
di->di_dict = NULL;
return NULL; return NULL;
} }
...@@ -2019,7 +2002,7 @@ PyTypeObject PyDictIter_Type = { ...@@ -2019,7 +2002,7 @@ PyTypeObject PyDictIter_Type = {
0, /* tp_weaklistoffset */ 0, /* tp_weaklistoffset */
(getiterfunc)dictiter_getiter, /* tp_iter */ (getiterfunc)dictiter_getiter, /* tp_iter */
(iternextfunc)dictiter_iternext, /* tp_iternext */ (iternextfunc)dictiter_iternext, /* tp_iternext */
dictiter_methods, /* tp_methods */ 0, /* tp_methods */
0, /* tp_members */ 0, /* tp_members */
0, /* tp_getset */ 0, /* tp_getset */
0, /* tp_base */ 0, /* tp_base */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment