[Python-checkins] CVS: python/dist/src/Objects fileobject.c,2.130,2.131

Tim Peters tim_one@users.sourceforge.net
Sat, 22 Sep 2001 21:06:07 -0700


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

Modified Files:
	fileobject.c 
Log Message:
Generalize file.writelines() to allow iterable objects.


Index: fileobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/fileobject.c,v
retrieving revision 2.130
retrieving revision 2.131
diff -C2 -d -r2.130 -r2.131
*** fileobject.c	2001/09/20 21:45:26	2.130
--- fileobject.c	2001/09/23 04:06:05	2.131
***************
*** 1165,1217 ****
  
  static PyObject *
! file_writelines(PyFileObject *f, PyObject *args)
  {
  #define CHUNKSIZE 1000
  	PyObject *list, *line;
  	PyObject *result;
  	int i, j, index, len, nwritten, islist;
  
  	if (f->f_fp == NULL)
  		return err_closed();
- 	if (args == NULL || !PySequence_Check(args)) {
- 		PyErr_SetString(PyExc_TypeError,
- 			   "writelines() argument must be a sequence of strings");
- 		return NULL;
- 	}
- 	islist = PyList_Check(args);
  
! 	/* Strategy: slurp CHUNKSIZE lines into a private list,
! 	   checking that they are all strings, then write that list
! 	   without holding the interpreter lock, then come back for more. */
! 	index = 0;
! 	if (islist)
! 		list = NULL;
  	else {
  		list = PyList_New(CHUNKSIZE);
  		if (list == NULL)
! 			return NULL;
  	}
- 	result = NULL;
  
! 	for (;;) {
  		if (islist) {
  			Py_XDECREF(list);
! 			list = PyList_GetSlice(args, index, index+CHUNKSIZE);
  			if (list == NULL)
! 				return NULL;
  			j = PyList_GET_SIZE(list);
  		}
  		else {
  			for (j = 0; j < CHUNKSIZE; j++) {
! 				line = PySequence_GetItem(args, index+j);
  				if (line == NULL) {
! 					if (PyErr_ExceptionMatches(
! 						PyExc_IndexError)) {
! 						PyErr_Clear();
! 						break;
! 					}
! 					/* Some other error occurred.
! 					   XXX We may lose some output. */
! 					goto error;
  				}
  				PyList_SetItem(list, j, line);
--- 1165,1216 ----
  
  static PyObject *
! file_writelines(PyFileObject *f, PyObject *seq)
  {
  #define CHUNKSIZE 1000
  	PyObject *list, *line;
+ 	PyObject *it;	/* iter(seq) */
  	PyObject *result;
  	int i, j, index, len, nwritten, islist;
  
+ 	assert(seq != NULL);
  	if (f->f_fp == NULL)
  		return err_closed();
  
! 	result = NULL;
! 	list = NULL;
! 	islist = PyList_Check(seq);
! 	if  (islist)
! 		it = NULL;
  	else {
+ 		it = PyObject_GetIter(seq);
+ 		if (it == NULL) {
+ 			PyErr_SetString(PyExc_TypeError,
+ 				"writelines() requires an iterable argument");
+ 			return NULL;
+ 		}
+ 		/* From here on, fail by going to error, to reclaim "it". */
  		list = PyList_New(CHUNKSIZE);
  		if (list == NULL)
! 			goto error;
  	}
  
! 	/* Strategy: slurp CHUNKSIZE lines into a private list,
! 	   checking that they are all strings, then write that list
! 	   without holding the interpreter lock, then come back for more. */
! 	for (index = 0; ; index += CHUNKSIZE) {
  		if (islist) {
  			Py_XDECREF(list);
! 			list = PyList_GetSlice(seq, index, index+CHUNKSIZE);
  			if (list == NULL)
! 				goto error;
  			j = PyList_GET_SIZE(list);
  		}
  		else {
  			for (j = 0; j < CHUNKSIZE; j++) {
! 				line = PyIter_Next(it);
  				if (line == NULL) {
! 					if (PyErr_Occurred())
! 						goto error;
! 					break;
  				}
  				PyList_SetItem(list, j, line);
***************
*** 1272,1276 ****
  		if (j < CHUNKSIZE)
  			break;
- 		index += CHUNKSIZE;
  	}
  
--- 1271,1274 ----
***************
*** 1279,1283 ****
--- 1277,1283 ----
    error:
  	Py_XDECREF(list);
+   	Py_XDECREF(it);
  	return result;
+ #undef CHUNKSIZE
  }
  
***************
*** 1343,1350 ****
  
  static char writelines_doc[] =
! "writelines(list of strings) -> None.  Write the strings to the file.\n"
  "\n"
! "Note that newlines are not added.  This is equivalent to calling write()\n"
! "for each string in the list.";
  
  static char flush_doc[] =
--- 1343,1350 ----
  
  static char writelines_doc[] =
! "writelines(sequence_of_strings) -> None.  Write the strings to the file.\n"
  "\n"
! "Note that newlines are not added.  The sequence can be any iterable object\n"
! "producing strings. This is equivalent to calling write() for each string.";
  
  static char flush_doc[] =