Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Lib/_pyio.py
Original file line number Diff line number Diff line change
Expand Up @@ -1498,6 +1498,7 @@ class FileIO(RawIOBase):
_writable = False
_appending = False
_seekable = None
_truncate = False
_closefd = True

def __init__(self, file, mode='r', closefd=True, opener=None):
Expand Down Expand Up @@ -1553,6 +1554,7 @@ def __init__(self, file, mode='r', closefd=True, opener=None):
flags = 0
elif 'w' in mode:
self._writable = True
self._truncate = True
flags = os.O_CREAT | os.O_TRUNC
elif 'a' in mode:
self._writable = True
Expand Down Expand Up @@ -1877,7 +1879,10 @@ def mode(self):
return 'ab'
elif self._readable:
if self._writable:
return 'rb+'
if self._truncate:
return 'wb+'
else:
return 'rb+'
else:
return 'rb'
else:
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_gzip.py
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ def test_fileobj_mode(self):
with open(self.filename, mode) as f:
with gzip.GzipFile(fileobj=f) as g:
self.assertEqual(g.mode, gzip.READ)
for mode in "wb", "ab", "xb":
for mode in "wb", "ab", "xb", "wb+", "ab+", "xb+":
if "x" in mode:
os_helper.unlink(self.filename)
with open(self.filename, mode) as f:
Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_io/test_fileio.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,8 +567,8 @@ 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'),
for modes in [('w', 'wb'), ('wb', 'wb'), ('wb+', 'wb+'),
('w+b', 'wb+'), ('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
Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_io/test_general.py
Original file line number Diff line number Diff line change
Expand Up @@ -4358,8 +4358,8 @@ def test_attributes(self):

f = self.open(os_helper.TESTFN, "w+", encoding="utf-8")
self.assertEqual(f.mode, "w+")
self.assertEqual(f.buffer.mode, "rb+") # Does it really matter?
self.assertEqual(f.buffer.raw.mode, "rb+")
self.assertEqual(f.buffer.mode, "wb+")
self.assertEqual(f.buffer.raw.mode, "wb+")

g = self.open(f.fileno(), "wb", closefd=False)
self.assertEqual(g.mode, "wb")
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_tempfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1386,7 +1386,7 @@ def test_properties(self):

f.write(b'x')
self.assertTrue(f._rolled)
self.assertEqual(f.mode, 'rb+')
self.assertEqual(f.mode, 'wb+')
self.assertIsNotNone(f.name)
with self.assertRaises(AttributeError):
f.newlines
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The :attr:`~io.FileIO.mode` attribute of files opened in the ``'wb+'`` mode is
now ``'wb+'`` instead of ``'rb+'``.
16 changes: 13 additions & 3 deletions Modules/_io/fileio.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ typedef struct {
unsigned int writable : 1;
unsigned int appending : 1;
signed int seekable : 2; /* -1 means unknown */
unsigned int truncate : 1;
unsigned int closefd : 1;
char finalizing;
/* Stat result which was grabbed at file open, useful for optimizing common
Expand Down Expand Up @@ -209,6 +210,7 @@ fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
self->writable = 0;
self->appending = 0;
self->seekable = -1;
self->truncate = 0;
self->stat_atopen = NULL;
self->closefd = 1;
self->weakreflist = NULL;
Expand Down Expand Up @@ -341,6 +343,7 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
goto bad_mode;
rwa = 1;
self->writable = 1;
self->truncate = 1;
flags |= O_CREAT | O_TRUNC;
break;
case 'a':
Expand Down Expand Up @@ -1159,10 +1162,17 @@ mode_string(fileio *self)
return "ab";
}
else if (self->readable) {
if (self->writable)
return "rb+";
else
if (self->writable) {
if (self->truncate) {
return "wb+";
}
else {
return "rb+";
}
}
else {
return "rb";
}
}
else
return "wb";
Expand Down
Loading