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:52:14 +02:00
commit e619427f7e
3 changed files with 32 additions and 10 deletions

View File

@ -304,7 +304,7 @@ def testAbles(self):
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 @@ def testModeStrings(self):
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

@ -54,6 +54,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 #16853: Add new selectors module. - Issue #16853: Add new selectors module.
- Issue #18882: Add threading.main_thread() function. - Issue #18882: Add threading.main_thread() function.

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;
char finalizing; char finalizing;
@ -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;
@ -219,7 +221,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;
@ -317,8 +319,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;
@ -349,10 +351,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
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
flags |= O_NOINHERIT; flags |= O_NOINHERIT;
#elif defined(O_CLOEXEC) #elif defined(O_CLOEXEC)
@ -432,7 +430,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()). */
@ -1019,7 +1017,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