From: Antoine Pitrou Date: Wed, 4 Sep 2013 18:46:33 +0000 (+0200) Subject: Issue #18876: The FileIO.mode attribute now better reflects the actual mode under... X-Git-Tag: v2.7.6rc1~178 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=213fec4bff53e24626172a9963e4e90d62a3e082;p=thirdparty%2FPython%2Fcpython.git Issue #18876: The FileIO.mode attribute now better reflects the actual mode under which the file was opened. Patch by Erik Bray. --- diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py index b74cec24f79a..e7955cce3ee3 100644 --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -305,7 +305,7 @@ class OtherFileTests(unittest.TestCase): finally: os.unlink(TESTFN) - def testModeStrings(self): + def testInvalidModeStrings(self): # check invalid mode strings for mode in ("", "aU", "wU+", "rw", "rt"): try: @@ -316,6 +316,21 @@ class OtherFileTests(unittest.TestCase): f.close() self.fail('%r is an invalid file mode' % mode) + def testModeStrings(self): + # test that the mode attribute is correct for various mode strings + # given as init args + try: + for modes in [('w', 'wb'), ('wb', 'wb'), ('wb+', 'rb+'), + ('w+b', 'rb+'), ('a', 'ab'), ('ab', 'ab'), + ('ab+', 'ab+'), ('a+b', 'ab+'), ('r', 'rb'), + ('rb', 'rb'), ('rb+', 'rb+'), ('r+b', 'rb+')]: + # read modes are last so that TESTFN will exist first + with _FileIO(TESTFN, modes[0]) as f: + self.assertEqual(f.mode, modes[1]) + finally: + if os.path.exists(TESTFN): + os.unlink(TESTFN) + def testUnicodeOpen(self): # verify repr works for unicode too f = _FileIO(str(TESTFN), "w") diff --git a/Misc/ACKS b/Misc/ACKS index 8977c02fa28a..8d29290a7094 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -124,6 +124,7 @@ Monty Brandenberg Georg Brandl Christopher Brannon Terrence Brannon +Erik Bray Brian Brazil Dave Brennan Tom Bridgman diff --git a/Misc/NEWS b/Misc/NEWS index afb7464be0fe..7ef400ea8880 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,9 @@ Core and Builtins Library ------- +- Issue #18876: The FileIO.mode attribute now better reflects the actual mode + under which the file was opened. Patch by Erik Bray. + - Issue #18851: Avoid a double close of subprocess pipes when the child process fails starting. diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 6cd7d817c8d6..5946e6a2bcc5 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -47,6 +47,7 @@ typedef struct { int fd; unsigned int readable : 1; unsigned int writable : 1; + unsigned int appending : 1; signed int seekable : 2; /* -1 means unknown */ unsigned int closefd : 1; PyObject *weakreflist; @@ -124,6 +125,7 @@ fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) self->fd = -1; self->readable = 0; self->writable = 0; + self->appending = 0; self->seekable = -1; self->closefd = 1; self->weakreflist = NULL; @@ -184,7 +186,7 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) Py_UNICODE *widename = NULL; #endif int ret = 0; - int rwa = 0, plus = 0, append = 0; + int rwa = 0, plus = 0; int flags = 0; int fd = -1; int closefd = 1; @@ -279,8 +281,8 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) goto bad_mode; rwa = 1; self->writable = 1; - flags |= O_CREAT; - append = 1; + self->appending = 1; + flags |= O_APPEND | O_CREAT; break; case 'b': break; @@ -311,11 +313,6 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) flags |= O_BINARY; #endif -#ifdef O_APPEND - if (append) - flags |= O_APPEND; -#endif - if (fd >= 0) { if (check_fd(fd)) goto error; @@ -356,7 +353,7 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) if (PyObject_SetAttrString((PyObject *)self, "name", nameobj) < 0) goto error; - if (append) { + if (self->appending) { /* For consistent behaviour, we explicitly seek to the end of file (otherwise, it might be done only on the first write()). */ @@ -898,7 +895,13 @@ fileio_truncate(fileio *self, PyObject *args) static char * mode_string(fileio *self) { - if (self->readable) { + if (self->appending) { + if (self->readable) + return "ab+"; + else + return "ab"; + } + else if (self->readable) { if (self->writable) return "rb+"; else