summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2003-04-24 15:50:11 (GMT)
committerRaymond Hettinger <python@rcn.com>2003-04-24 15:50:11 (GMT)
commit352f9477da79cfeba9afdb97e4554f7eca5b77db (patch)
treef7db5033e19a9eb873ad827c2b10eee165270603
parent024aaa1bfe27cbc47c2a7f88c21c9bb1b6605191 (diff)
downloadcpython-352f9477da79cfeba9afdb97e4554f7eca5b77db.zip
cpython-352f9477da79cfeba9afdb97e4554f7eca5b77db.tar.gz
cpython-352f9477da79cfeba9afdb97e4554f7eca5b77db.tar.bz2
SF patch 695710: fix bug 678519: cStringIO self iterator
(requested by GvR. patch contributed by Michael Stone)
-rw-r--r--Lib/test/test_StringIO.py6
-rw-r--r--Modules/cStringIO.c121
2 files changed, 59 insertions, 68 deletions
diff --git a/Lib/test/test_StringIO.py b/Lib/test/test_StringIO.py
index d8dc8b8..74bdf59 100644
--- a/Lib/test/test_StringIO.py
+++ b/Lib/test/test_StringIO.py
@@ -58,10 +58,10 @@ class TestGenericStringIO(unittest.TestCase):
def test_iterator(self):
eq = self.assertEqual
unless = self.failUnless
- it = iter(self._fp)
+ eq(iter(self._fp), self._fp)
# Does this object support the iteration protocol?
- unless(hasattr(it, '__iter__'))
- unless(hasattr(it, 'next'))
+ unless(hasattr(self._fp, '__iter__'))
+ unless(hasattr(self._fp, 'next'))
i = 0
for line in self._fp:
eq(line, self._line + '\n')
diff --git a/Modules/cStringIO.c b/Modules/cStringIO.c
index 4cabc5b..bc23c77 100644
--- a/Modules/cStringIO.c
+++ b/Modules/cStringIO.c
@@ -2,6 +2,7 @@
#include "Python.h"
#include "import.h"
#include "cStringIO.h"
+#include "structmember.h"
PyDoc_STRVAR(cStringIO_module_documentation,
"A simple fast partial StringIO replacement.\n"
@@ -189,7 +190,8 @@ IO_readline(IOobject *self, PyObject *args) {
int n, m=-1;
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 (m >= 0 && m < n) {
@@ -276,6 +278,21 @@ IO_truncate(IOobject *self, PyObject *args) {
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 */
};
+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
O_dealloc(Oobject *self) {
if (self->buf != NULL)
@@ -442,53 +465,40 @@ O_dealloc(Oobject *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.");
static PyTypeObject Otype = {
PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "cStringIO.StringO", /*tp_name*/
+ 0, /*ob_size*/
+ "cStringIO.StringO", /*tp_name*/
sizeof(Oobject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
+ 0, /*tp_itemsize*/
/* methods */
(destructor)O_dealloc, /*tp_dealloc*/
- (printfunc)0, /*tp_print*/
- (getattrfunc)O_getattr, /*tp_getattr*/
- (setattrfunc)O_setattr, /*tp_setattr*/
- (cmpfunc)0, /*tp_compare*/
- (reprfunc)0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- (hashfunc)0, /*tp_hash*/
+ (printfunc)0, /*tp_print*/
+ 0, /*tp_getattr */
+ 0, /*tp_setattr */
+ (cmpfunc)0, /*tp_compare*/
+ (reprfunc)0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ (hashfunc)0, /*tp_hash*/
(ternaryfunc)0, /*tp_call*/
- (reprfunc)0, /*tp_str*/
-
- /* Space for future expansion */
- 0L,0L,0L,0L,
- Otype__doc__ /* Documentation string */
+ (reprfunc)0, /*tp_str*/
+ 0, /*tp_getattro */
+ 0, /*tp_setattro */
+ 0, /*tp_as_buffer */
+ 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 *
@@ -570,28 +580,6 @@ I_dealloc(Iobject *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__,
"Simple type for treating strings as input file streams");
@@ -605,7 +593,7 @@ static PyTypeObject Itype = {
/* methods */
(destructor)I_dealloc, /*tp_dealloc*/
(printfunc)0, /*tp_print*/
- (getattrfunc)I_getattr, /*tp_getattr*/
+ 0, /* tp_getattr */
(setattrfunc)0, /*tp_setattr*/
(cmpfunc)0, /*tp_compare*/
(reprfunc)0, /*tp_repr*/
@@ -624,8 +612,9 @@ static PyTypeObject Itype = {
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
- (getiterfunc)I_getiter, /* tp_iter */
- 0, /* tp_iternext */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)IO_iternext, /* tp_iternext */
+ I_methods /* tp_methods */
};
static PyObject *
@@ -707,6 +696,8 @@ initcStringIO(void) {
/* Export C API */
Itype.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",
v = PyCObject_FromVoidPtr(&CAPI,NULL));
Py_XDECREF(v);