mirror of
https://github.com/python/cpython.git
synced 2025-10-01 04:42:10 +00:00
[3.6] bpo-32228: Reset raw_pos after unwinding the raw stream (GH-4858) (#5389)
Ensure that ``truncate()`` preserves the file position (as reported by ``tell()``) after writes longer than the buffer size..
(cherry picked from commit 059f58ce93
)
This commit is contained in:
parent
33febfb039
commit
1d896ed2cd
3 changed files with 28 additions and 4 deletions
|
@ -1703,6 +1703,23 @@ class BufferedWriterTest(unittest.TestCase, CommonBufferedTests):
|
||||||
with self.open(support.TESTFN, "rb", buffering=0) as f:
|
with self.open(support.TESTFN, "rb", buffering=0) as f:
|
||||||
self.assertEqual(f.read(), b"abc")
|
self.assertEqual(f.read(), b"abc")
|
||||||
|
|
||||||
|
def test_truncate_after_write(self):
|
||||||
|
# Ensure that truncate preserves the file position after
|
||||||
|
# writes longer than the buffer size.
|
||||||
|
# Issue: https://bugs.python.org/issue32228
|
||||||
|
with self.open(support.TESTFN, "wb") as f:
|
||||||
|
# Fill with some buffer
|
||||||
|
f.write(b'\x00' * 10000)
|
||||||
|
buffer_sizes = [8192, 4096, 200]
|
||||||
|
for buffer_size in buffer_sizes:
|
||||||
|
with self.open(support.TESTFN, "r+b", buffering=buffer_size) as f:
|
||||||
|
f.write(b'\x00' * (buffer_size + 1))
|
||||||
|
# After write write_pos and write_end are set to 0
|
||||||
|
f.read(1)
|
||||||
|
# read operation makes sure that pos != raw_pos
|
||||||
|
f.truncate()
|
||||||
|
self.assertEqual(f.tell(), buffer_size + 2)
|
||||||
|
|
||||||
@unittest.skipUnless(threading, 'Threading required for this test.')
|
@unittest.skipUnless(threading, 'Threading required for this test.')
|
||||||
@support.requires_resource('cpu')
|
@support.requires_resource('cpu')
|
||||||
def test_threads(self):
|
def test_threads(self):
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Ensure that ``truncate()`` preserves the file position (as reported by ``tell()``) after writes longer than the buffer size.
|
|
@ -1311,7 +1311,6 @@ _io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence)
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
goto end;
|
goto end;
|
||||||
Py_CLEAR(res);
|
Py_CLEAR(res);
|
||||||
_bufferedwriter_reset_buf(self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: align on block boundary and read buffer if needed? */
|
/* TODO: align on block boundary and read buffer if needed? */
|
||||||
|
@ -1878,8 +1877,6 @@ _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* `restore_pos` is 1 if we need to restore the raw stream position at
|
|
||||||
the end, 0 otherwise. */
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_bufferedwriter_flush_unlocked(buffered *self)
|
_bufferedwriter_flush_unlocked(buffered *self)
|
||||||
{
|
{
|
||||||
|
@ -1920,9 +1917,18 @@ _bufferedwriter_flush_unlocked(buffered *self)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
_bufferedwriter_reset_buf(self);
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
|
/* This ensures that after return from this function,
|
||||||
|
VALID_WRITE_BUFFER(self) returns false.
|
||||||
|
|
||||||
|
This is a required condition because when a tell() is called
|
||||||
|
after flushing and if VALID_READ_BUFFER(self) is false, we need
|
||||||
|
VALID_WRITE_BUFFER(self) to be false to have
|
||||||
|
RAW_OFFSET(self) == 0.
|
||||||
|
|
||||||
|
Issue: https://bugs.python.org/issue32228 */
|
||||||
|
_bufferedwriter_reset_buf(self);
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue