mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	SF patch 695710: fix bug 678519: cStringIO self iterator
(requested by GvR. patch contributed by Michael Stone)
This commit is contained in:
		
							parent
							
								
									024aaa1bfe
								
							
						
					
					
						commit
						352f9477da
					
				
					 2 changed files with 59 additions and 68 deletions
				
			
		|  | @ -58,10 +58,10 @@ def test_truncate(self): | ||||||
|     def test_iterator(self): |     def test_iterator(self): | ||||||
|         eq = self.assertEqual |         eq = self.assertEqual | ||||||
|         unless = self.failUnless |         unless = self.failUnless | ||||||
|         it = iter(self._fp) |         eq(iter(self._fp), self._fp) | ||||||
|         # Does this object support the iteration protocol? |         # Does this object support the iteration protocol? | ||||||
|         unless(hasattr(it, '__iter__')) |         unless(hasattr(self._fp, '__iter__')) | ||||||
|         unless(hasattr(it, 'next')) |         unless(hasattr(self._fp, 'next')) | ||||||
|         i = 0 |         i = 0 | ||||||
|         for line in self._fp: |         for line in self._fp: | ||||||
|             eq(line, self._line + '\n') |             eq(line, self._line + '\n') | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| #include "Python.h" | #include "Python.h" | ||||||
| #include "import.h" | #include "import.h" | ||||||
| #include "cStringIO.h" | #include "cStringIO.h" | ||||||
|  | #include "structmember.h" | ||||||
| 
 | 
 | ||||||
| PyDoc_STRVAR(cStringIO_module_documentation, | PyDoc_STRVAR(cStringIO_module_documentation, | ||||||
| "A simple fast partial StringIO replacement.\n" | "A simple fast partial StringIO replacement.\n" | ||||||
|  | @ -189,7 +190,8 @@ IO_readline(IOobject *self, PyObject *args) { | ||||||
|         int n, m=-1; |         int n, m=-1; | ||||||
|         char *output; |         char *output; | ||||||
| 
 | 
 | ||||||
|         UNLESS (PyArg_ParseTuple(args, "|i:readline", &m)) return NULL; |         if (args) | ||||||
|  |                 UNLESS (PyArg_ParseTuple(args, "|i:readline", &m)) return NULL; | ||||||
| 
 | 
 | ||||||
|         if( (n=IO_creadline((PyObject*)self,&output)) < 0) return NULL; |         if( (n=IO_creadline((PyObject*)self,&output)) < 0) return NULL; | ||||||
|         if (m >= 0 && m < n) { |         if (m >= 0 && m < n) { | ||||||
|  | @ -276,6 +278,21 @@ IO_truncate(IOobject *self, PyObject *args) { | ||||||
|         return Py_None; |         return Py_None; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static PyObject * | ||||||
|  | IO_iternext(Iobject *self) | ||||||
|  | { | ||||||
|  | 	PyObject *next; | ||||||
|  | 	next = IO_readline((IOobject *)self, NULL); | ||||||
|  | 	if (!next) | ||||||
|  | 		return NULL; | ||||||
|  | 	if (!PyString_GET_SIZE(next)) { | ||||||
|  | 		Py_DECREF(next); | ||||||
|  | 		PyErr_SetNone(PyExc_StopIteration); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	return next; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -435,6 +452,12 @@ static struct PyMethodDef O_methods[] = { | ||||||
|   {NULL,	 NULL}		/* sentinel */ |   {NULL,	 NULL}		/* sentinel */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static PyMemberDef O_memberlist[] = { | ||||||
|  | 	{"softspace",	T_INT,	offsetof(Oobject, softspace),	0, | ||||||
|  | 	 "flag indicating that a space needs to be printed; used by print"}, | ||||||
|  | 	{NULL} /* Sentinel */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| static void | static void | ||||||
| O_dealloc(Oobject *self) { | O_dealloc(Oobject *self) { | ||||||
|         if (self->buf != NULL) |         if (self->buf != NULL) | ||||||
|  | @ -442,53 +465,40 @@ O_dealloc(Oobject *self) { | ||||||
|         PyObject_Del(self); |         PyObject_Del(self); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static PyObject * |  | ||||||
| O_getattr(Oobject *self, char *name) { |  | ||||||
|         if (strcmp(name, "softspace") == 0) { |  | ||||||
|                 return PyInt_FromLong(self->softspace); |  | ||||||
|         } |  | ||||||
|         return Py_FindMethod(O_methods, (PyObject *)self, name); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int |  | ||||||
| O_setattr(Oobject *self, char *name, PyObject *value) { |  | ||||||
| 	long x; |  | ||||||
| 	if (strcmp(name, "softspace") != 0) { |  | ||||||
| 		PyErr_SetString(PyExc_AttributeError, name); |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
| 	x = PyInt_AsLong(value); |  | ||||||
| 	if (x < 0 && PyErr_Occurred()) |  | ||||||
| 		return -1; |  | ||||||
| 	self->softspace = x; |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| PyDoc_STRVAR(Otype__doc__, "Simple type for output to strings."); | PyDoc_STRVAR(Otype__doc__, "Simple type for output to strings."); | ||||||
| 
 | 
 | ||||||
| static PyTypeObject Otype = { | static PyTypeObject Otype = { | ||||||
|   PyObject_HEAD_INIT(NULL) |   PyObject_HEAD_INIT(NULL) | ||||||
|   0,	       		/*ob_size*/ |   0,	       			/*ob_size*/ | ||||||
|   "cStringIO.StringO",   		/*tp_name*/ |   "cStringIO.StringO",   	/*tp_name*/ | ||||||
|   sizeof(Oobject),       	/*tp_basicsize*/ |   sizeof(Oobject),       	/*tp_basicsize*/ | ||||||
|   0,	       		/*tp_itemsize*/ |   0,	       			/*tp_itemsize*/ | ||||||
|   /* methods */ |   /* methods */ | ||||||
|   (destructor)O_dealloc,	/*tp_dealloc*/ |   (destructor)O_dealloc,	/*tp_dealloc*/ | ||||||
|   (printfunc)0,		/*tp_print*/ |   (printfunc)0,			/*tp_print*/ | ||||||
|   (getattrfunc)O_getattr,	/*tp_getattr*/ |   0,		 		/*tp_getattr */ | ||||||
|   (setattrfunc)O_setattr,	/*tp_setattr*/ |   0,		 		/*tp_setattr */ | ||||||
|   (cmpfunc)0,		/*tp_compare*/ |   (cmpfunc)0,			/*tp_compare*/ | ||||||
|   (reprfunc)0,		/*tp_repr*/ |   (reprfunc)0,			/*tp_repr*/ | ||||||
|   0,			/*tp_as_number*/ |   0,				/*tp_as_number*/ | ||||||
|   0,			/*tp_as_sequence*/ |   0,				/*tp_as_sequence*/ | ||||||
|   0,			/*tp_as_mapping*/ |   0,				/*tp_as_mapping*/ | ||||||
|   (hashfunc)0,		/*tp_hash*/ |   (hashfunc)0,			/*tp_hash*/ | ||||||
|   (ternaryfunc)0,		/*tp_call*/ |   (ternaryfunc)0,		/*tp_call*/ | ||||||
|   (reprfunc)0,		/*tp_str*/ |   (reprfunc)0,			/*tp_str*/ | ||||||
|    |   0,				/*tp_getattro */ | ||||||
|   /* Space for future expansion */ |   0,				/*tp_setattro */ | ||||||
|   0L,0L,0L,0L, |   0,				/*tp_as_buffer */ | ||||||
|   Otype__doc__ 		/* Documentation string */ |   Py_TPFLAGS_DEFAULT,		/*tp_flags*/ | ||||||
|  |   Otype__doc__, 		/*tp_doc */ | ||||||
|  |   0,				/*tp_traverse */ | ||||||
|  |   0,				/*tp_clear */ | ||||||
|  |   0,				/*tp_richcompare */ | ||||||
|  |   0,				/*tp_weaklistoffset */ | ||||||
|  |   PyObject_SelfIter,		/*tp_iter */ | ||||||
|  |   (iternextfunc)IO_iternext,	/*tp_iternext */ | ||||||
|  |   O_methods,			/*tp_methods */ | ||||||
|  |   O_memberlist			/*tp_members */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static PyObject * | static PyObject * | ||||||
|  | @ -570,28 +580,6 @@ I_dealloc(Iobject *self) { | ||||||
|   PyObject_Del(self); |   PyObject_Del(self); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static PyObject * |  | ||||||
| I_getattr(Iobject *self, char *name) { |  | ||||||
|   return Py_FindMethod(I_methods, (PyObject *)self, name); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static PyObject * |  | ||||||
| I_getiter(Iobject *self) |  | ||||||
| { |  | ||||||
| 	PyObject *myreadline = PyObject_GetAttrString((PyObject*)self, |  | ||||||
| 						      "readline"); |  | ||||||
| 	PyObject *emptystring = PyString_FromString(""); |  | ||||||
| 	PyObject *iter = NULL; |  | ||||||
| 	if (!myreadline || !emptystring) |  | ||||||
| 		goto finally; |  | ||||||
| 
 |  | ||||||
| 	iter = PyCallIter_New(myreadline, emptystring); |  | ||||||
|   finally: |  | ||||||
| 	Py_XDECREF(myreadline); |  | ||||||
| 	Py_XDECREF(emptystring); |  | ||||||
| 	return iter; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| PyDoc_STRVAR(Itype__doc__, | PyDoc_STRVAR(Itype__doc__, | ||||||
| "Simple type for treating strings as input file streams"); | "Simple type for treating strings as input file streams"); | ||||||
|  | @ -605,7 +593,7 @@ static PyTypeObject Itype = { | ||||||
|   /* methods */ |   /* methods */ | ||||||
|   (destructor)I_dealloc,		/*tp_dealloc*/ |   (destructor)I_dealloc,		/*tp_dealloc*/ | ||||||
|   (printfunc)0,				/*tp_print*/ |   (printfunc)0,				/*tp_print*/ | ||||||
|   (getattrfunc)I_getattr,		/*tp_getattr*/ |   0,		 			/* tp_getattr */ | ||||||
|   (setattrfunc)0,			/*tp_setattr*/ |   (setattrfunc)0,			/*tp_setattr*/ | ||||||
|   (cmpfunc)0,				/*tp_compare*/ |   (cmpfunc)0,				/*tp_compare*/ | ||||||
|   (reprfunc)0,				/*tp_repr*/ |   (reprfunc)0,				/*tp_repr*/ | ||||||
|  | @ -624,8 +612,9 @@ static PyTypeObject Itype = { | ||||||
|   0,					/* tp_clear */ |   0,					/* tp_clear */ | ||||||
|   0,					/* tp_richcompare */ |   0,					/* tp_richcompare */ | ||||||
|   0,					/* tp_weaklistoffset */ |   0,					/* tp_weaklistoffset */ | ||||||
|   (getiterfunc)I_getiter,		/* tp_iter */ |   PyObject_SelfIter,			/* tp_iter */ | ||||||
|   0,					/* tp_iternext */ |   (iternextfunc)IO_iternext,		/* tp_iternext */ | ||||||
|  |   I_methods				/* tp_methods */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static PyObject * | static PyObject * | ||||||
|  | @ -707,6 +696,8 @@ initcStringIO(void) { | ||||||
|   /* Export C API */ |   /* Export C API */ | ||||||
|   Itype.ob_type=&PyType_Type; |   Itype.ob_type=&PyType_Type; | ||||||
|   Otype.ob_type=&PyType_Type; |   Otype.ob_type=&PyType_Type; | ||||||
|  |   if (PyType_Ready(&Otype) < 0) return; | ||||||
|  |   if (PyType_Ready(&Itype) < 0) return; | ||||||
|   PyDict_SetItemString(d,"cStringIO_CAPI", |   PyDict_SetItemString(d,"cStringIO_CAPI", | ||||||
| 		       v = PyCObject_FromVoidPtr(&CAPI,NULL)); | 		       v = PyCObject_FromVoidPtr(&CAPI,NULL)); | ||||||
|   Py_XDECREF(v); |   Py_XDECREF(v); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Raymond Hettinger
						Raymond Hettinger