summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2002-07-16 20:30:22 (GMT)
committerGuido van Rossum <guido@python.org>2002-07-16 20:30:22 (GMT)
commit2147df748fa0a44beede227af9e595fe96fd7a14 (patch)
treec94b7dc11af97eebb6b2efbe0db4fe2e3f0910b5 /Objects
parent613bed3726af921be64900bd0cb8209193873411 (diff)
downloadcpython-2147df748fa0a44beede227af9e595fe96fd7a14.zip
cpython-2147df748fa0a44beede227af9e595fe96fd7a14.tar.gz
cpython-2147df748fa0a44beede227af9e595fe96fd7a14.tar.bz2
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).
Diffstat (limited to 'Objects')
-rw-r--r--Objects/dictobject.c39
1 files changed, 11 insertions, 28 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index d7bbef9..2619160 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1916,7 +1916,7 @@ extern PyTypeObject PyDictIter_Type; /* Forward */
typedef struct {
PyObject_HEAD
- dictobject *di_dict;
+ dictobject *di_dict; /* Set to NULL when iterator is exhausted */
int di_used;
int di_pos;
binaryfunc di_select;
@@ -1940,52 +1940,35 @@ dictiter_new(dictobject *dict, binaryfunc select)
static void
dictiter_dealloc(dictiterobject *di)
{
- Py_DECREF(di->di_dict);
+ Py_XDECREF(di->di_dict);
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 *
dictiter_getiter(PyObject *it)
{
Py_INCREF(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)
{
PyObject *key, *value;
+ if (di->di_dict == NULL)
+ return NULL;
+
if (di->di_used != di->di_dict->ma_used) {
PyErr_SetString(PyExc_RuntimeError,
"dictionary changed size during iteration");
+ di->di_used = -1; /* Make this state sticky */
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);
- }
+
+ Py_DECREF(di->di_dict);
+ di->di_dict = NULL;
return NULL;
}
@@ -2019,7 +2002,7 @@ PyTypeObject PyDictIter_Type = {
0, /* tp_weaklistoffset */
(getiterfunc)dictiter_getiter, /* tp_iter */
(iternextfunc)dictiter_iternext, /* tp_iternext */
- dictiter_methods, /* tp_methods */
+ 0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */