[Python-3000-checkins] r58713 - in python/branches/py3k-pep3137: Doc/c-api/concrete.rst Include/fileobject.h Lib/fileinput.py Lib/io.py Lib/quopri.py Lib/test/test_io.py Misc/NEWS Modules/_fileio.c Objects/fileobject.c Python/import.c Python/pythonrun.c Python/symtable.c

guido.van.rossum python-3000-checkins at python.org
Tue Oct 30 18:35:35 CET 2007


Author: guido.van.rossum
Date: Tue Oct 30 18:35:34 2007
New Revision: 58713

Modified:
   python/branches/py3k-pep3137/   (props changed)
   python/branches/py3k-pep3137/Doc/c-api/concrete.rst
   python/branches/py3k-pep3137/Include/fileobject.h
   python/branches/py3k-pep3137/Lib/fileinput.py
   python/branches/py3k-pep3137/Lib/io.py
   python/branches/py3k-pep3137/Lib/quopri.py
   python/branches/py3k-pep3137/Lib/test/test_io.py
   python/branches/py3k-pep3137/Misc/NEWS
   python/branches/py3k-pep3137/Modules/_fileio.c
   python/branches/py3k-pep3137/Objects/fileobject.c
   python/branches/py3k-pep3137/Python/import.c
   python/branches/py3k-pep3137/Python/pythonrun.c
   python/branches/py3k-pep3137/Python/symtable.c
Log:
Merged revisions 58703-58712 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/branches/py3k

........
  r58704 | guido.van.rossum | 2007-10-29 10:39:59 -0700 (Mon, 29 Oct 2007) | 5 lines
  
  Patch 1341 by Amaury Forgeot d'Arc.
  This patch corrects test_fileinput on Windows: when redirecting stdout,
  os.open should be given O_BINARY, because the file descriptor is then
  wrapped in a text-mode file; os.fdopen(fd, "w").
........
  r58705 | martin.v.loewis | 2007-10-29 12:54:24 -0700 (Mon, 29 Oct 2007) | 2 lines
  
  Bug #1356: Avoid using the C99 keyword 'restrict'.
........
  r58711 | guido.van.rossum | 2007-10-30 10:27:30 -0700 (Tue, 30 Oct 2007) | 7 lines
  
  Patch 1329 (partial) by Christian Heimes.
  Add a closefd flag to open() which can be set to False to prevent closing
  the file descriptor when close() is called or when the object is destroyed.
  Useful to ensure that sys.std{in,out,err} keep their file descriptors open
  when Python is uninitialized.  (This was always a feature in 2.x, it just
  wasn't implemented in 3.0 yet.)
........


Modified: python/branches/py3k-pep3137/Doc/c-api/concrete.rst
==============================================================================
--- python/branches/py3k-pep3137/Doc/c-api/concrete.rst	(original)
+++ python/branches/py3k-pep3137/Doc/c-api/concrete.rst	Tue Oct 30 18:35:34 2007
@@ -2401,12 +2401,12 @@
    :ctype:`PyFileObject`.
 
 
-.. cfunction:: PyFile_FromFd(int fd, char *name, char *mode, int buffering, char *encoding, char *newline)
+.. cfunction:: PyFile_FromFd(int fd, char *name, char *mode, int buffering, char *encoding, char *newline, int closefd)
 
    Create a new :ctype:`PyFileObject` from the file descriptor of an already
    opened file *fd*. The arguments *name*, *encoding* and *newline* can be
-   *NULL* as well as buffering can be *-1* to use the defaults. Return *NULL* on
-   failure.
+   *NULL* to use the defaults; *buffering* can be *-1* to use the default.
+   Return *NULL* on failure.
 
    .. warning::
 

Modified: python/branches/py3k-pep3137/Include/fileobject.h
==============================================================================
--- python/branches/py3k-pep3137/Include/fileobject.h	(original)
+++ python/branches/py3k-pep3137/Include/fileobject.h	Tue Oct 30 18:35:34 2007
@@ -8,7 +8,8 @@
 
 #define PY_STDIOTEXTMODE "b"
 
-PyAPI_FUNC(PyObject *) PyFile_FromFd(int, char *, char *, int, char *, char *);
+PyAPI_FUNC(PyObject *) PyFile_FromFd(int, char *, char *, int, char *, char *,
+				     int);
 PyAPI_FUNC(PyObject *) PyFile_GetLine(PyObject *, int);
 PyAPI_FUNC(int) PyFile_WriteObject(PyObject *, PyObject *, int);
 PyAPI_FUNC(int) PyFile_WriteString(const char *, PyObject *);

Modified: python/branches/py3k-pep3137/Lib/fileinput.py
==============================================================================
--- python/branches/py3k-pep3137/Lib/fileinput.py	(original)
+++ python/branches/py3k-pep3137/Lib/fileinput.py	Tue Oct 30 18:35:34 2007
@@ -326,9 +326,11 @@
                     except OSError:
                         self._output = open(self._filename, "w")
                     else:
-                        fd = os.open(self._filename,
-                                     os.O_CREAT | os.O_WRONLY | os.O_TRUNC,
-                                     perm)
+                        mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC
+                        if hasattr(os, 'O_BINARY'):
+                            mode |= os.O_BINARY
+
+                        fd = os.open(self._filename, mode, perm)
                         self._output = os.fdopen(fd, "w")
                         try:
                             if hasattr(os, 'chmod'):

Modified: python/branches/py3k-pep3137/Lib/io.py
==============================================================================
--- python/branches/py3k-pep3137/Lib/io.py	(original)
+++ python/branches/py3k-pep3137/Lib/io.py	Tue Oct 30 18:35:34 2007
@@ -49,7 +49,8 @@
         self.characters_written = characters_written
 
 
-def open(file, mode="r", buffering=None, encoding=None, newline=None):
+def open(file, mode="r", buffering=None, encoding=None, newline=None,
+         closefd=True):
     r"""Replacement for the built-in open function.
 
     Args:
@@ -81,9 +82,12 @@
           other legal values, any `'\n'` characters written are
           translated to the given string.
 
+      closefd: optional argument to keep the underlying file descriptor
+               open when the file is closed.  It must not be false when
+               a filename is given.
+
     (*) If a file descriptor is given, it is closed when the returned
-    I/O object is closed.  If you don't want this to happen, use
-    os.dup() to create a duplicate file descriptor.
+    I/O object is closed, unless closefd=False is give.
 
     Mode strings characters:
       'r': open for reading (default)
@@ -138,7 +142,8 @@
                  (reading and "r" or "") +
                  (writing and "w" or "") +
                  (appending and "a" or "") +
-                 (updating and "+" or ""))
+                 (updating and "+" or ""),
+                 closefd)
     if buffering is None:
         buffering = -1
     if buffering < 0 and raw.isatty():

Modified: python/branches/py3k-pep3137/Lib/quopri.py
==============================================================================
--- python/branches/py3k-pep3137/Lib/quopri.py	(original)
+++ python/branches/py3k-pep3137/Lib/quopri.py	Tue Oct 30 18:35:34 2007
@@ -227,12 +227,14 @@
                 sys.stderr.write("%s: can't open (%s)\n" % (file, msg))
                 sts = 1
                 continue
-        if deco:
-            decode(fp, sys.stdout.buffer)
-        else:
-            encode(fp, sys.stdout.buffer, tabs)
-        if fp is not sys.stdin:
-            fp.close()
+        try:
+            if deco:
+                decode(fp, sys.stdout.buffer)
+            else:
+                encode(fp, sys.stdout.buffer, tabs)
+        finally:
+            if file != '-':
+                fp.close()
     if sts:
         sys.exit(sts)
 

Modified: python/branches/py3k-pep3137/Lib/test/test_io.py
==============================================================================
--- python/branches/py3k-pep3137/Lib/test/test_io.py	(original)
+++ python/branches/py3k-pep3137/Lib/test/test_io.py	Tue Oct 30 18:35:34 2007
@@ -259,6 +259,9 @@
         self.assertEqual(f.write(a), n)
         f.close()
 
+    def test_closefd(self):
+        self.assertRaises(ValueError, io.open, test_support.TESTFN, 'w',
+                          closefd=False)
 
 class MemorySeekTestMixin:
 

Modified: python/branches/py3k-pep3137/Misc/NEWS
==============================================================================
--- python/branches/py3k-pep3137/Misc/NEWS	(original)
+++ python/branches/py3k-pep3137/Misc/NEWS	Tue Oct 30 18:35:34 2007
@@ -28,6 +28,9 @@
   with `Py_FileSystemDefaultEncoding` and a new API method 
   `PyUnicode_DecodeFSDefault(char*)` was added.
 
+- io.open() and _fileio.FileIO have grown a new argument closefd. A false
+  value disables the closing of the file descriptor.
+
 Extension Modules
 -----------------
 

Modified: python/branches/py3k-pep3137/Modules/_fileio.c
==============================================================================
--- python/branches/py3k-pep3137/Modules/_fileio.c	(original)
+++ python/branches/py3k-pep3137/Modules/_fileio.c	Tue Oct 30 18:35:34 2007
@@ -33,6 +33,7 @@
 	unsigned readable : 1;
 	unsigned writable : 1;
 	int seekable : 2; /* -1 means unknown */
+	int closefd : 1;
 	PyObject *weakreflist;
 } PyFileIOObject;
 
@@ -59,6 +60,13 @@
 static PyObject *
 fileio_close(PyFileIOObject *self)
 {
+	if (!self->closefd) {
+		if (PyErr_WarnEx(PyExc_RuntimeWarning,
+				 "Trying to close unclosable fd!", 3) < 0) {
+			return NULL;
+		}
+		Py_RETURN_NONE;
+	}
 	errno = internal_close(self);
 	if (errno < 0) {
 		PyErr_SetFromErrno(PyExc_IOError);
@@ -119,7 +127,7 @@
 fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
 {
 	PyFileIOObject *self = (PyFileIOObject *) oself;
-	static char *kwlist[] = {"file", "mode", NULL};
+	static char *kwlist[] = {"file", "mode", "closefd", NULL};
 	char *name = NULL;
 	char *mode = "r";
 	char *s;
@@ -130,6 +138,7 @@
 	int rwa = 0, plus = 0, append = 0;
 	int flags = 0;
 	int fd = -1;
+	int closefd = 1;
 
 	assert(PyFileIO_Check(oself));
 	if (self->fd >= 0) {
@@ -138,8 +147,8 @@
 			return -1;
 	}
 
-	if (PyArg_ParseTupleAndKeywords(args, kwds, "i|s:fileio",
-					kwlist, &fd, &mode)) {
+	if (PyArg_ParseTupleAndKeywords(args, kwds, "i|si:fileio",
+					kwlist, &fd, &mode, &closefd)) {
 		if (fd < 0) {
 			PyErr_SetString(PyExc_ValueError,
 					"Negative filedescriptor");
@@ -153,8 +162,9 @@
 	    if (GetVersion() < 0x80000000) {
 		/* On NT, so wide API available */
 		PyObject *po;
-		if (PyArg_ParseTupleAndKeywords(args, kwds, "U|s:fileio",
-						kwlist, &po, &mode)) {
+		if (PyArg_ParseTupleAndKeywords(args, kwds, "U|si:fileio",
+						kwlist, &po, &mode, &closefd)
+						) {
 			widename = PyUnicode_AS_UNICODE(po);
 		} else {
 			/* Drop the argument parsing error as narrow
@@ -162,13 +172,13 @@
 			PyErr_Clear();
 		}
 	    }
-	    if (widename == NULL) 
+	    if (widename == NULL)
 #endif
 	    {
-		if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|s:fileio",
+		if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:fileio",
 						 kwlist,
 						 Py_FileSystemDefaultEncoding,
-						 &name, &mode))
+						 &name, &mode, &closefd))
 			goto error;
 	    }
 	}
@@ -237,8 +247,16 @@
 
 	if (fd >= 0) {
 		self->fd = fd;
+		self->closefd = closefd;
 	}
 	else {
+		self->closefd = 1;
+		if (!closefd) {
+			PyErr_SetString(PyExc_ValueError,
+                            "Cannot use closefd=True with file name");
+			goto error;
+		}
+
 		Py_BEGIN_ALLOW_THREADS
 		errno = 0;
 #ifdef MS_WINDOWS
@@ -270,7 +288,7 @@
 	if (self->weakreflist != NULL)
 		PyObject_ClearWeakRefs((PyObject *) self);
 
-	if (self->fd >= 0) {
+	if (self->fd >= 0 && self->closefd) {
 		errno = internal_close(self);
 		if (errno < 0) {
 #ifdef HAVE_STRERROR

Modified: python/branches/py3k-pep3137/Objects/fileobject.c
==============================================================================
--- python/branches/py3k-pep3137/Objects/fileobject.c	(original)
+++ python/branches/py3k-pep3137/Objects/fileobject.c	Tue Oct 30 18:35:34 2007
@@ -27,15 +27,15 @@
 
 PyObject *
 PyFile_FromFd(int fd, char *name, char *mode, int buffering, char *encoding,
-	      char *newline)
+	      char *newline, int closefd)
 {
 	PyObject *io, *stream, *nameobj = NULL;
 
 	io = PyImport_ImportModule("io");
 	if (io == NULL)
 		return NULL;
-	stream = PyObject_CallMethod(io, "open", "isiss", fd, mode,
-				     buffering, encoding, newline);
+	stream = PyObject_CallMethod(io, "open", "isissi", fd, mode,
+				     buffering, encoding, newline, closefd);
 	Py_DECREF(io);
 	if (stream == NULL)
 		return NULL;

Modified: python/branches/py3k-pep3137/Python/import.c
==============================================================================
--- python/branches/py3k-pep3137/Python/import.c	(original)
+++ python/branches/py3k-pep3137/Python/import.c	Tue Oct 30 18:35:34 2007
@@ -2589,7 +2589,7 @@
 				   (char*)PyUnicode_GetDefaultEncoding();
 		}
 		fob = PyFile_FromFd(fd, pathname, fdp->mode, -1,
-					(char*)encoding, NULL);
+				    (char*)encoding, NULL, 1);
 		if (fob == NULL) {
 			close(fd);
 			PyMem_FREE(found_encoding);

Modified: python/branches/py3k-pep3137/Python/pythonrun.c
==============================================================================
--- python/branches/py3k-pep3137/Python/pythonrun.c	(original)
+++ python/branches/py3k-pep3137/Python/pythonrun.c	Tue Oct 30 18:35:34 2007
@@ -720,7 +720,7 @@
 
 	/* Set sys.stdin */
 	if (!(std = PyFile_FromFd(fileno(stdin), "<stdin>", "r", -1,
-				      NULL, "\n"))) {
+				  NULL, "\n", 0))) {
 		goto error;
 	}
 	PySys_SetObject("__stdin__", std);
@@ -729,16 +729,16 @@
 
 	/* Set sys.stdout */
 	if (!(std = PyFile_FromFd(fileno(stdout), "<stdout>", "w", -1,
-				      NULL, "\n"))) {
+				  NULL, "\n", 0))) {
             goto error;
         }
 	PySys_SetObject("__stdout__", std);
 	PySys_SetObject("stdout", std);
 	Py_DECREF(std);
 
-	/* Set sys.stderr */
+	/* Set sys.stderr, replaces the preliminary stderr */
 	if (!(std = PyFile_FromFd(fileno(stderr), "<stderr>", "w", -1,
-				      NULL, "\n"))) {
+				  NULL, "\n", 0))) {
             goto error;
         }
         PySys_SetObject("__stderr__", std);

Modified: python/branches/py3k-pep3137/Python/symtable.c
==============================================================================
--- python/branches/py3k-pep3137/Python/symtable.c	(original)
+++ python/branches/py3k-pep3137/Python/symtable.c	Tue Oct 30 18:35:34 2007
@@ -465,12 +465,12 @@
    Note that the current block's free variables are included in free.
    That's safe because no name can be free and local in the same scope.
 
-   The 'restrict' argument may be set to a string to restrict the analysis
+   The 'restricted' argument may be set to a string to restrict the analysis
    to the one variable whose name equals that string (e.g. "__class__").
 */
 
 static int
-analyze_cells(PyObject *scopes, PyObject *free, const char *restrict)
+analyze_cells(PyObject *scopes, PyObject *free, const char *restricted)
 {
         PyObject *name, *v, *v_cell;
 	int success = 0;
@@ -487,8 +487,8 @@
 			continue;
 		if (!PySet_Contains(free, name))
 			continue;
-		if (restrict != NULL &&
-                    PyUnicode_CompareWithASCIIString(name, restrict))
+		if (restricted != NULL &&
+                    PyUnicode_CompareWithASCIIString(name, restricted))
 			continue;
 		/* Replace LOCAL with CELL for this name, and remove
 		   from free. It is safe to replace the value of name 


More information about the Python-3000-checkins mailing list