Skip to content

Commit 889201f

Browse files
Commit
____ Co-authored-by: Xiang Zhang <[email protected]>
1 parent 4e08a9f commit 889201f

File tree

5 files changed

+24
-8
lines changed

5 files changed

+24
-8
lines changed

Lib/_pyio.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,7 @@ class FileIO(RawIOBase):
14981498
_writable = False
14991499
_appending = False
15001500
_seekable = None
1501+
_truncate = False
15011502
_closefd = True
15021503

15031504
def __init__(self, file, mode='r', closefd=True, opener=None):
@@ -1553,6 +1554,7 @@ def __init__(self, file, mode='r', closefd=True, opener=None):
15531554
flags = 0
15541555
elif 'w' in mode:
15551556
self._writable = True
1557+
self._truncate = True
15561558
flags = os.O_CREAT | os.O_TRUNC
15571559
elif 'a' in mode:
15581560
self._writable = True
@@ -1877,7 +1879,10 @@ def mode(self):
18771879
return 'ab'
18781880
elif self._readable:
18791881
if self._writable:
1880-
return 'rb+'
1882+
if self._truncate:
1883+
return 'wb+'
1884+
else:
1885+
return 'rb+'
18811886
else:
18821887
return 'rb'
18831888
else:

Lib/test/test_fileio.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -567,8 +567,8 @@ def testModeStrings(self):
567567
# test that the mode attribute is correct for various mode strings
568568
# given as init args
569569
try:
570-
for modes in [('w', 'wb'), ('wb', 'wb'), ('wb+', 'rb+'),
571-
('w+b', 'rb+'), ('a', 'ab'), ('ab', 'ab'),
570+
for modes in [('w', 'wb'), ('wb', 'wb'), ('wb+', 'wb+'),
571+
('w+b', 'wb+'), ('a', 'ab'), ('ab', 'ab'),
572572
('ab+', 'ab+'), ('a+b', 'ab+'), ('r', 'rb'),
573573
('rb', 'rb'), ('rb+', 'rb+'), ('r+b', 'rb+')]:
574574
# read modes are last so that TESTFN will exist first

Lib/test/test_io.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4337,8 +4337,8 @@ def test_attributes(self):
43374337

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

43434343
g = self.open(f.fileno(), "wb", closefd=False)
43444344
self.assertEqual(g.mode, "wb")
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:mod:`io`: Fix a bug where the ``'wb+'`` mode was treated as ``'rb+'``.

Modules/_io/fileio.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ typedef struct {
7070
unsigned int writable : 1;
7171
unsigned int appending : 1;
7272
signed int seekable : 2; /* -1 means unknown */
73+
unsigned int truncate : 1;
7374
unsigned int closefd : 1;
7475
char finalizing;
7576
/* Stat result which was grabbed at file open, useful for optimizing common
@@ -209,6 +210,7 @@ fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
209210
self->writable = 0;
210211
self->appending = 0;
211212
self->seekable = -1;
213+
self->truncate = 0;
212214
self->stat_atopen = NULL;
213215
self->closefd = 1;
214216
self->weakreflist = NULL;
@@ -341,6 +343,7 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode,
341343
goto bad_mode;
342344
rwa = 1;
343345
self->writable = 1;
346+
self->truncate = 1;
344347
flags |= O_CREAT | O_TRUNC;
345348
break;
346349
case 'a':
@@ -1156,10 +1159,17 @@ mode_string(fileio *self)
11561159
return "ab";
11571160
}
11581161
else if (self->readable) {
1159-
if (self->writable)
1160-
return "rb+";
1161-
else
1162+
if (self->writable) {
1163+
if (self->truncate) {
1164+
return "wb+";
1165+
}
1166+
else {
1167+
return "rb+";
1168+
}
1169+
}
1170+
else {
11621171
return "rb";
1172+
}
11631173
}
11641174
else
11651175
return "wb";

0 commit comments

Comments
 (0)