[Python-checkins] python/dist/src/Objects dictobject.c,2.126,2.127

gvanrossum@users.sourceforge.net gvanrossum@users.sourceforge.net
Tue, 16 Jul 2002 13:30:25 -0700


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv4011

Modified Files:
	dictobject.c 
Log Message:
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).


Index: dictobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v
retrieving revision 2.126
retrieving revision 2.127
diff -C2 -d -r2.126 -r2.127
*** dictobject.c	13 Jun 2002 20:32:57 -0000	2.126
--- dictobject.c	16 Jul 2002 20:30:22 -0000	2.127
***************
*** 1917,1921 ****
  typedef struct {
  	PyObject_HEAD
! 	dictobject *di_dict;
  	int di_used;
  	int di_pos;
--- 1917,1921 ----
  typedef struct {
  	PyObject_HEAD
! 	dictobject *di_dict; /* Set to NULL when iterator is exhausted */
  	int di_used;
  	int di_pos;
***************
*** 1941,1966 ****
  dictiter_dealloc(dictiterobject *di)
  {
! 	Py_DECREF(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)
  {
--- 1941,1949 ----
  dictiter_dealloc(dictiterobject *di)
  {
! 	Py_XDECREF(di->di_dict);
  	PyObject_Del(di);
  }
  
  static PyObject *
  dictiter_getiter(PyObject *it)
  {
***************
*** 1969,1990 ****
  }
  
- 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_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);
! 	}
  	return NULL;
  }
--- 1952,1973 ----
  }
  
  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))
  		return (*di->di_select)(key, value);
! 
! 	Py_DECREF(di->di_dict);
! 	di->di_dict = NULL;
  	return NULL;
  }
***************
*** 2020,2024 ****
  	(getiterfunc)dictiter_getiter,		/* tp_iter */
  	(iternextfunc)dictiter_iternext,	/* tp_iternext */
! 	dictiter_methods,			/* tp_methods */
  	0,					/* tp_members */
  	0,					/* tp_getset */
--- 2003,2007 ----
  	(getiterfunc)dictiter_getiter,		/* tp_iter */
  	(iternextfunc)dictiter_iternext,	/* tp_iternext */
! 	0,					/* tp_methods */
  	0,					/* tp_members */
  	0,					/* tp_getset */