Issue #18876: The FileIO.mode attribute now better reflects the actual mode under which the file was opened.

Patch by Erik Bray.
This commit is contained in:
Antoine Pitrou 2013-09-04 20:46:33 +02:00
parent c9e1dcdd53
commit e93b63b74b
3 changed files with 32 additions and 11 deletions

View file

@ -304,7 +304,7 @@ class OtherFileTests(unittest.TestCase):
finally: finally:
os.unlink(TESTFN) os.unlink(TESTFN)
def testModeStrings(self): def testInvalidModeStrings(self):
# check invalid mode strings # check invalid mode strings
for mode in ("", "aU", "wU+", "rw", "rt"): for mode in ("", "aU", "wU+", "rw", "rt"):
try: try:
@ -315,6 +315,21 @@ class OtherFileTests(unittest.TestCase):
f.close() f.close()
self.fail('%r is an invalid file mode' % mode) 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): def testUnicodeOpen(self):
# verify repr works for unicode too # verify repr works for unicode too
f = _FileIO(str(TESTFN), "w") f = _FileIO(str(TESTFN), "w")

View file

@ -66,6 +66,9 @@ Core and Builtins
Library Library
------- -------
- Issue #18876: The FileIO.mode attribute now better reflects the actual mode
under which the file was opened. Patch by Erik Bray.
- Issue #18418: After fork(), reinit all threads states, not only active ones. - Issue #18418: After fork(), reinit all threads states, not only active ones.
Patch by A. Jesse Jiryu Davis. Patch by A. Jesse Jiryu Davis.

View file

@ -49,6 +49,7 @@ typedef struct {
unsigned int created : 1; unsigned int created : 1;
unsigned int readable : 1; unsigned int readable : 1;
unsigned int writable : 1; unsigned int writable : 1;
unsigned int appending : 1;
signed int seekable : 2; /* -1 means unknown */ signed int seekable : 2; /* -1 means unknown */
unsigned int closefd : 1; unsigned int closefd : 1;
unsigned int deallocating: 1; unsigned int deallocating: 1;
@ -156,6 +157,7 @@ fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
self->created = 0; self->created = 0;
self->readable = 0; self->readable = 0;
self->writable = 0; self->writable = 0;
self->appending = 0;
self->seekable = -1; self->seekable = -1;
self->closefd = 1; self->closefd = 1;
self->weakreflist = NULL; self->weakreflist = NULL;
@ -216,7 +218,7 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
Py_UNICODE *widename = NULL; Py_UNICODE *widename = NULL;
#endif #endif
int ret = 0; int ret = 0;
int rwa = 0, plus = 0, append = 0; int rwa = 0, plus = 0;
int flags = 0; int flags = 0;
int fd = -1; int fd = -1;
int closefd = 1; int closefd = 1;
@ -309,8 +311,8 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
goto bad_mode; goto bad_mode;
rwa = 1; rwa = 1;
self->writable = 1; self->writable = 1;
flags |= O_CREAT; self->appending = 1;
append = 1; flags |= O_APPEND | O_CREAT;
break; break;
case 'b': case 'b':
break; break;
@ -341,11 +343,6 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
flags |= O_BINARY; flags |= O_BINARY;
#endif #endif
#ifdef O_APPEND
if (append)
flags |= O_APPEND;
#endif
if (fd >= 0) { if (fd >= 0) {
if (check_fd(fd)) if (check_fd(fd))
goto error; goto error;
@ -411,7 +408,7 @@ fileio_init(PyObject *oself, PyObject *args, PyObject *kwds)
if (PyObject_SetAttrString((PyObject *)self, "name", nameobj) < 0) if (PyObject_SetAttrString((PyObject *)self, "name", nameobj) < 0)
goto error; goto error;
if (append) { if (self->appending) {
/* For consistent behaviour, we explicitly seek to the /* For consistent behaviour, we explicitly seek to the
end of file (otherwise, it might be done only on the end of file (otherwise, it might be done only on the
first write()). */ first write()). */
@ -1012,7 +1009,13 @@ mode_string(fileio *self)
else else
return "xb"; return "xb";
} }
if (self->readable) { if (self->appending) {
if (self->readable)
return "ab+";
else
return "ab";
}
else if (self->readable) {
if (self->writable) if (self->writable)
return "rb+"; return "rb+";
else else