mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
gh-69528: Distinguish between file modes "wb+" and "rb+" (GH-137834)
Co-authored-by: Xiang Zhang <angwerzx@126.com>
This commit is contained in:
parent
60df1d7e0c
commit
02c1abfc54
7 changed files with 27 additions and 10 deletions
|
|
@ -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):
|
||||
|
|
@ -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
|
||||
|
|
@ -1877,6 +1879,9 @@ def mode(self):
|
|||
return 'ab'
|
||||
elif self._readable:
|
||||
if self._writable:
|
||||
if self._truncate:
|
||||
return 'wb+'
|
||||
else:
|
||||
return 'rb+'
|
||||
else:
|
||||
return 'rb'
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -960,8 +960,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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
The :attr:`~io.FileIO.mode` attribute of files opened in the ``'wb+'`` mode is
|
||||
now ``'wb+'`` instead of ``'rb+'``.
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -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':
|
||||
|
|
@ -1145,11 +1148,18 @@ mode_string(fileio *self)
|
|||
return "ab";
|
||||
}
|
||||
else if (self->readable) {
|
||||
if (self->writable)
|
||||
if (self->writable) {
|
||||
if (self->truncate) {
|
||||
return "wb+";
|
||||
}
|
||||
else {
|
||||
return "rb+";
|
||||
else
|
||||
}
|
||||
}
|
||||
else {
|
||||
return "rb";
|
||||
}
|
||||
}
|
||||
else
|
||||
return "wb";
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue