[Python-3000-checkins] r54714 - python/branches/p3yk/Modules/_fileio.c

guido.van.rossum python-3000-checkins at python.org
Sun Apr 8 19:44:43 CEST 2007


Author: guido.van.rossum
Date: Sun Apr  8 19:44:42 2007
New Revision: 54714

Modified:
   python/branches/p3yk/Modules/_fileio.c
Log:
Make it possible to instantiate a _FileIO() with an integer file descriptor
instead of a filename.
Add a 'closed' attribute.


Modified: python/branches/p3yk/Modules/_fileio.c
==============================================================================
--- python/branches/p3yk/Modules/_fileio.c	(original)
+++ python/branches/p3yk/Modules/_fileio.c	Sun Apr  8 19:44:42 2007
@@ -22,9 +22,8 @@
  *
  * Unanswered questions:
  *
- * - Add mode, name, and closed properties a la Python 2 file objects?
- * - Do we need a (*close)() in the struct like Python 2 file objects,
- *   for not-quite-ordinary-file objects?
+ * - Add mode and name properties a la Python 2 file objects?
+ * - Check for readable/writable before attempting to read/write?
  */
 
 #ifdef MS_WINDOWS
@@ -55,15 +54,16 @@
 fileio_close(PyFileIOObject *self)
 {
 	if (self->fd >= 0) {
+		int fd = self->fd;
+		self->fd = -1;
 		Py_BEGIN_ALLOW_THREADS
 		errno = 0;
-		close(self->fd);
+		close(fd);
 		Py_END_ALLOW_THREADS
 		if (errno < 0) {
 			PyErr_SetFromErrno(PyExc_IOError);
 			return NULL;
 		}
-		self->fd = -1;
 	}
 
 	Py_RETURN_NONE;
@@ -123,7 +123,7 @@
 fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
 {
 	PyFileIOObject *self = (PyFileIOObject *) oself;
-	static char *kwlist[] = {"filename", "mode", NULL};
+	static char *kwlist[] = {"file", "mode", NULL};
 	char *name = NULL;
 	char *mode = "r";
         char *s;
@@ -131,6 +131,7 @@
 	int ret = 0;
 	int rwa = 0, plus = 0, append = 0;
 	int flags = 0;
+	int fd = -1;
 
 	assert(PyFileIO_Check(oself));
 	if (self->fd >= 0)
@@ -142,8 +143,20 @@
 		Py_DECREF(closeresult);
 	}
 
+	if (PyArg_ParseTupleAndKeywords(args, kwds, "i|s:fileio",
+					kwlist, &fd, &mode)) {
+		if (fd < 0) {
+			PyErr_SetString(PyExc_ValueError,
+					"Negative filedescriptor");
+			return -1;
+		}
+	}
+	else {
+		PyErr_Clear();
+
 #ifdef Py_WIN_WIDE_FILENAMES
-	if (GetVersion() < 0x80000000) {    /* On NT, so wide API available */
+	    if (GetVersion() < 0x80000000) {
+		/* On NT, so wide API available */
 		PyObject *po;
 		if (PyArg_ParseTupleAndKeywords(args, kwds, "U|s:fileio",
 						kwlist, &po, &mode)) {
@@ -155,17 +168,18 @@
 		}
 
 		PyErr_SetString(PyExc_NotImplementedError,
-				"Windows wide filenames are not yet supported");
+			"Windows wide filenames are not yet supported");
 		goto error;
-	}
+	    }
 #endif
 
-	if (!wideargument) {
+	    if (!wideargument) {
 		if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|s:fileio",
 						 kwlist,
 						 Py_FileSystemDefaultEncoding,
 						 &name, &mode))
 			goto error;
+	    }
 	}
 
 	self->readable = self->writable = 0;
@@ -224,13 +238,19 @@
 	flags |= O_BINARY;
 #endif
 
-	Py_BEGIN_ALLOW_THREADS
-	errno = 0;
-	self->fd = open(name, flags, 0666);
-	Py_END_ALLOW_THREADS
-	if (self->fd < 0 || dircheck(self) < 0) {
-		PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
-		goto error;
+	if (fd >= 0) {
+		self->fd = fd;
+		/* XXX Should we set self->own_fd = 0 ??? */
+	}
+	else {
+		Py_BEGIN_ALLOW_THREADS
+		errno = 0;
+		self->fd = open(name, flags, 0666);
+		Py_END_ALLOW_THREADS
+		if (self->fd < 0 || dircheck(self) < 0) {
+			PyErr_SetFromErrnoWithFilename(PyExc_IOError, name);
+			goto error;
+		}
 	}
 
 	goto done;
@@ -652,6 +672,18 @@
 	{NULL,	     NULL}	       /* sentinel */
 };
 
+/* 'closed' is an attribute for backwards compatibility reasons. */
+static PyObject *
+get_closed(PyFileIOObject *f, void *closure)
+{
+	return PyBool_FromLong((long)(f->fd < 0));
+}
+
+static PyGetSetDef fileio_getsetlist[] = {
+	{"closed", (getter)get_closed, NULL, "True if the file is closed"},
+	{0},
+};
+
 PyTypeObject PyFileIO_Type = {
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,
@@ -683,7 +715,7 @@
 	0,					/* tp_iternext */
 	fileio_methods,				/* tp_methods */
 	0,					/* tp_members */
-	0,					/* tp_getset */
+	fileio_getsetlist,			/* tp_getset */
 	0,					/* tp_base */
 	0,					/* tp_dict */
 	0,					/* tp_descr_get */


More information about the Python-3000-checkins mailing list