Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 352f947

Browse files
committed
SF patch 695710: fix bug 678519: cStringIO self iterator
(requested by GvR. patch contributed by Michael Stone)
1 parent 024aaa1 commit 352f947

2 files changed

Lines changed: 59 additions & 68 deletions

File tree

Lib/test/test_StringIO.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ def test_truncate(self):
5858
def test_iterator(self):
5959
eq = self.assertEqual
6060
unless = self.failUnless
61-
it = iter(self._fp)
61+
eq(iter(self._fp), self._fp)
6262
# Does this object support the iteration protocol?
63-
unless(hasattr(it, '__iter__'))
64-
unless(hasattr(it, 'next'))
63+
unless(hasattr(self._fp, '__iter__'))
64+
unless(hasattr(self._fp, 'next'))
6565
i = 0
6666
for line in self._fp:
6767
eq(line, self._line + '\n')

Modules/cStringIO.c

Lines changed: 56 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "Python.h"
33
#include "import.h"
44
#include "cStringIO.h"
5+
#include "structmember.h"
56

67
PyDoc_STRVAR(cStringIO_module_documentation,
78
"A simple fast partial StringIO replacement.\n"
@@ -189,7 +190,8 @@ IO_readline(IOobject *self, PyObject *args) {
189190
int n, m=-1;
190191
char *output;
191192

192-
UNLESS (PyArg_ParseTuple(args, "|i:readline", &m)) return NULL;
193+
if (args)
194+
UNLESS (PyArg_ParseTuple(args, "|i:readline", &m)) return NULL;
193195

194196
if( (n=IO_creadline((PyObject*)self,&output)) < 0) return NULL;
195197
if (m >= 0 && m < n) {
@@ -276,6 +278,21 @@ IO_truncate(IOobject *self, PyObject *args) {
276278
return Py_None;
277279
}
278280

281+
static PyObject *
282+
IO_iternext(Iobject *self)
283+
{
284+
PyObject *next;
285+
next = IO_readline((IOobject *)self, NULL);
286+
if (!next)
287+
return NULL;
288+
if (!PyString_GET_SIZE(next)) {
289+
Py_DECREF(next);
290+
PyErr_SetNone(PyExc_StopIteration);
291+
return NULL;
292+
}
293+
return next;
294+
}
295+
279296

280297

281298

@@ -435,60 +452,53 @@ static struct PyMethodDef O_methods[] = {
435452
{NULL, NULL} /* sentinel */
436453
};
437454

455+
static PyMemberDef O_memberlist[] = {
456+
{"softspace", T_INT, offsetof(Oobject, softspace), 0,
457+
"flag indicating that a space needs to be printed; used by print"},
458+
{NULL} /* Sentinel */
459+
};
460+
438461
static void
439462
O_dealloc(Oobject *self) {
440463
if (self->buf != NULL)
441464
free(self->buf);
442465
PyObject_Del(self);
443466
}
444467

445-
static PyObject *
446-
O_getattr(Oobject *self, char *name) {
447-
if (strcmp(name, "softspace") == 0) {
448-
return PyInt_FromLong(self->softspace);
449-
}
450-
return Py_FindMethod(O_methods, (PyObject *)self, name);
451-
}
452-
453-
static int
454-
O_setattr(Oobject *self, char *name, PyObject *value) {
455-
long x;
456-
if (strcmp(name, "softspace") != 0) {
457-
PyErr_SetString(PyExc_AttributeError, name);
458-
return -1;
459-
}
460-
x = PyInt_AsLong(value);
461-
if (x < 0 && PyErr_Occurred())
462-
return -1;
463-
self->softspace = x;
464-
return 0;
465-
}
466-
467468
PyDoc_STRVAR(Otype__doc__, "Simple type for output to strings.");
468469

469470
static PyTypeObject Otype = {
470471
PyObject_HEAD_INIT(NULL)
471-
0, /*ob_size*/
472-
"cStringIO.StringO", /*tp_name*/
472+
0, /*ob_size*/
473+
"cStringIO.StringO", /*tp_name*/
473474
sizeof(Oobject), /*tp_basicsize*/
474-
0, /*tp_itemsize*/
475+
0, /*tp_itemsize*/
475476
/* methods */
476477
(destructor)O_dealloc, /*tp_dealloc*/
477-
(printfunc)0, /*tp_print*/
478-
(getattrfunc)O_getattr, /*tp_getattr*/
479-
(setattrfunc)O_setattr, /*tp_setattr*/
480-
(cmpfunc)0, /*tp_compare*/
481-
(reprfunc)0, /*tp_repr*/
482-
0, /*tp_as_number*/
483-
0, /*tp_as_sequence*/
484-
0, /*tp_as_mapping*/
485-
(hashfunc)0, /*tp_hash*/
478+
(printfunc)0, /*tp_print*/
479+
0, /*tp_getattr */
480+
0, /*tp_setattr */
481+
(cmpfunc)0, /*tp_compare*/
482+
(reprfunc)0, /*tp_repr*/
483+
0, /*tp_as_number*/
484+
0, /*tp_as_sequence*/
485+
0, /*tp_as_mapping*/
486+
(hashfunc)0, /*tp_hash*/
486487
(ternaryfunc)0, /*tp_call*/
487-
(reprfunc)0, /*tp_str*/
488-
489-
/* Space for future expansion */
490-
0L,0L,0L,0L,
491-
Otype__doc__ /* Documentation string */
488+
(reprfunc)0, /*tp_str*/
489+
0, /*tp_getattro */
490+
0, /*tp_setattro */
491+
0, /*tp_as_buffer */
492+
Py_TPFLAGS_DEFAULT, /*tp_flags*/
493+
Otype__doc__, /*tp_doc */
494+
0, /*tp_traverse */
495+
0, /*tp_clear */
496+
0, /*tp_richcompare */
497+
0, /*tp_weaklistoffset */
498+
PyObject_SelfIter, /*tp_iter */
499+
(iternextfunc)IO_iternext, /*tp_iternext */
500+
O_methods, /*tp_methods */
501+
O_memberlist /*tp_members */
492502
};
493503

494504
static PyObject *
@@ -570,28 +580,6 @@ I_dealloc(Iobject *self) {
570580
PyObject_Del(self);
571581
}
572582

573-
static PyObject *
574-
I_getattr(Iobject *self, char *name) {
575-
return Py_FindMethod(I_methods, (PyObject *)self, name);
576-
}
577-
578-
static PyObject *
579-
I_getiter(Iobject *self)
580-
{
581-
PyObject *myreadline = PyObject_GetAttrString((PyObject*)self,
582-
"readline");
583-
PyObject *emptystring = PyString_FromString("");
584-
PyObject *iter = NULL;
585-
if (!myreadline || !emptystring)
586-
goto finally;
587-
588-
iter = PyCallIter_New(myreadline, emptystring);
589-
finally:
590-
Py_XDECREF(myreadline);
591-
Py_XDECREF(emptystring);
592-
return iter;
593-
}
594-
595583

596584
PyDoc_STRVAR(Itype__doc__,
597585
"Simple type for treating strings as input file streams");
@@ -605,7 +593,7 @@ static PyTypeObject Itype = {
605593
/* methods */
606594
(destructor)I_dealloc, /*tp_dealloc*/
607595
(printfunc)0, /*tp_print*/
608-
(getattrfunc)I_getattr, /*tp_getattr*/
596+
0, /* tp_getattr */
609597
(setattrfunc)0, /*tp_setattr*/
610598
(cmpfunc)0, /*tp_compare*/
611599
(reprfunc)0, /*tp_repr*/
@@ -624,8 +612,9 @@ static PyTypeObject Itype = {
624612
0, /* tp_clear */
625613
0, /* tp_richcompare */
626614
0, /* tp_weaklistoffset */
627-
(getiterfunc)I_getiter, /* tp_iter */
628-
0, /* tp_iternext */
615+
PyObject_SelfIter, /* tp_iter */
616+
(iternextfunc)IO_iternext, /* tp_iternext */
617+
I_methods /* tp_methods */
629618
};
630619

631620
static PyObject *
@@ -707,6 +696,8 @@ initcStringIO(void) {
707696
/* Export C API */
708697
Itype.ob_type=&PyType_Type;
709698
Otype.ob_type=&PyType_Type;
699+
if (PyType_Ready(&Otype) < 0) return;
700+
if (PyType_Ready(&Itype) < 0) return;
710701
PyDict_SetItemString(d,"cStringIO_CAPI",
711702
v = PyCObject_FromVoidPtr(&CAPI,NULL));
712703
Py_XDECREF(v);

0 commit comments

Comments
 (0)