[Patches] New builtin function repeat?
Neil Schemenauer
nascheme@enme.ucalgary.ca
Wed, 5 Apr 2000 19:44:35 -0600
--G4iJoqBmSsgzjUCe
Content-Type: text/plain; charset=us-ascii
I made this module some time about but I still think it is neat.
It creates a new function called repeat (I'm not stuck on the
name). You can use it like this:
for line in repeat(sys.stdin.readline):
...
The repeat function creates a new sequence object. The function
supplied is called for __getitem__. By default, a false value
returned from the function will raise an IndexError. You can
specifiy an alternate termination value. For example:
for line in repeat(sys.stdin.readline, ''):
...
would work as well.
While I'm throwing out crazy ideas, how about adding some
sequence methods to PyFileObject? You could then do:
file = open(...)
for line in file:
...
Too weird? Here is a patch and the module.
Neil
--
"The lyf so short, the craft so long to lerne." -- Chaucer
--G4iJoqBmSsgzjUCe
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="file-seq.diff"
diff -cr Python-cvs/Objects/fileobject.c Python-file/Objects/fileobject.c
*** Python-cvs/Objects/fileobject.c Fri Mar 24 22:32:30 2000
--- Python-file/Objects/fileobject.c Wed Apr 5 19:37:13 2000
***************
*** 1040,1045 ****
--- 1040,1099 ----
return PyMember_Set((char *)f, file_memberlist, name, v);
}
+ /* as_sequence */
+
+ static PyObject *
+ file_getitem(self, index)
+ PyObject *self;
+ int index;
+ {
+ PyObject *line;
+ if ((line = PyFile_GetLine(self, 0)) == NULL) {
+ return NULL;
+ }
+ if (!PyObject_IsTrue(line)) {
+ Py_DECREF(line);
+ PyErr_SetString(PyExc_IndexError, "file index out of range");
+ return NULL;
+ }
+ return line;
+ }
+
+ static int
+ file_length(self)
+ PyObject *self;
+ {
+ return 0;
+ }
+
+ static PyObject *
+ file_concat(self, other)
+ PyObject *self;
+ PyObject *other;
+ {
+ PyErr_SetString(PyExc_AttributeError, "__concat__");
+ return NULL;
+ }
+
+ static PyObject *
+ file_repeat(self, count)
+ PyObject *self;
+ int count;
+ {
+ PyErr_SetString(PyExc_AttributeError, "__repeat__");
+ return NULL;
+ }
+
+ static PySequenceMethods file_as_sequence = {
+ (inquiry)file_length, /*sq_length*/
+ (binaryfunc)file_concat, /*sq_concat*/
+ (intargfunc)file_repeat, /*sq_repeat*/
+ (intargfunc)file_getitem, /*sq_item*/
+ (intintargfunc)0, /*sq_slice*/
+ (intobjargproc)0, /*sq_ass_item*/
+ (intintobjargproc)0, /*sq_ass_slice*/
+ };
+
PyTypeObject PyFile_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0,
***************
*** 1052,1057 ****
--- 1106,1113 ----
(setattrfunc)file_setattr, /*tp_setattr*/
0, /*tp_compare*/
(reprfunc)file_repr, /*tp_repr*/
+ 0, /*tp_as_number*/
+ &file_as_sequence, /*tp_as_sequence*/
};
/* Interface for the 'soft space' between print items. */
--G4iJoqBmSsgzjUCe
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="repeatmodule.c"
/*
* A little Python extension module so you can do stuff like:
*
* import sys
* from repeat import repeat
* for line in repeat(sys.stdin.readline):
* ...
*
* repeat(<function>, [<until>]) -> RepeatObject
*
* RepeatObjects are sequences that only support the method __getitem__.
* <function> is called on __getitem__. If <until> is not specified a
* false value from <function> raises an IndexError. If <until> is
* specified, if the value is equal to <until> then IndexError is
* raised.
*
*
* Neil Schemenauer <nascheme@ucalgary.ca> April, 2000
*
*/
#include "Python.h"
typedef struct {
PyObject_HEAD
PyObject *function;
PyObject *until;
} repeatObject;
staticforward PyTypeObject repeat_Type;
static repeatObject *
newrepeatObject(args)
PyObject *args;
{
repeatObject *self;
PyObject *function;
PyObject *until;
until = NULL;
if (!PyArg_ParseTuple(args, "O|O", &function, &until))
return NULL;
if (!PyCallable_Check(function)) {
PyErr_SetString(PyExc_TypeError, "callable object required");
return NULL;
}
self = PyObject_NEW(repeatObject, &repeat_Type);
if (self == NULL)
return NULL;
Py_INCREF(function);
self->function = function;
if (until != NULL)
Py_INCREF(until);
self->until = until;
return self;
}
static void
repeat_dealloc(self)
repeatObject *self;
{
Py_XDECREF(self->function);
Py_XDECREF(self->until);
PyMem_DEL(self);
}
static PyObject *
repeat_getitem(self, index)
repeatObject *self;
int index;
{
PyObject *item;
item = PyEval_CallObject(self->function, NULL);
if ( item == NULL ) {
return NULL;
}
if ( (self->until && PyObject_Compare(item, self->until) == 0) ||
(!self->until && !PyObject_IsTrue(item)) ) {
PyErr_SetString(PyExc_IndexError, "repeat completed");
return NULL;
}
return item;
}
static int
repeat_length(self)
PyObject *self;
{
return 0;
}
static PyObject *
repeat_concat(self, other)
PyObject *self;
PyObject *other;
{
PyErr_SetString(PyExc_AttributeError, "__concat__");
return NULL;
}
static PyObject *
repeat_repeat(self, count)
PyObject *self;
int count;
{
PyErr_SetString(PyExc_AttributeError, "__repeat__");
return NULL;
}
static PyMethodDef repeat_methods[] = {
{NULL, NULL} /* sentinel */
};
static PySequenceMethods repeat_as_sequence = {
(inquiry)repeat_length, /*sq_length*/
(binaryfunc)repeat_concat, /*sq_concat*/
(intargfunc)repeat_repeat, /*sq_repeat*/
(intargfunc)repeat_getitem, /*sq_item*/
(intintargfunc)0, /*sq_slice*/
(intobjargproc)0, /*sq_ass_item*/
(intintobjargproc)0, /*sq_ass_slice*/
};
staticforward PyTypeObject repeat_Type = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"repeat", /*tp_name*/
sizeof(repeatObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)repeat_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
&repeat_as_sequence, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
};
static PyObject *
repeat_new(self, args)
PyObject *self; /* Not used */
PyObject *args;
{
repeatObject *rv;
rv = newrepeatObject(args);
if ( rv == NULL )
return NULL;
return (PyObject *)rv;
}
/* List of functions defined in the module */
static PyMethodDef repeatmodule_methods[] = {
{"repeat", repeat_new, 1},
{NULL, NULL} /* sentinel */
};
/* Initialization function for the module (*must* be called initrepeat) */
void
initrepeat()
{
PyObject *m, *d;
/* Create the module and add the functions */
repeat_Type.ob_type = &PyType_Type;
m = Py_InitModule("repeat", repeatmodule_methods);
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
}
--G4iJoqBmSsgzjUCe--