Issue #21396: Fix TextIOWrapper(..., write_through=True) to not force a flush() on the underlying binary stream.
Patch by akira.
This commit is contained in:
parent
a83ade1d60
commit
c644e7c39f
|
@ -2615,6 +2615,38 @@ class TextIOWrapperTest(unittest.TestCase):
|
|||
txt.write('5')
|
||||
self.assertEqual(b''.join(raw._write_stack), b'123\n45')
|
||||
|
||||
def test_bufio_write_through(self):
|
||||
# Issue #21396: write_through=True doesn't force a flush()
|
||||
# on the underlying binary buffered object.
|
||||
flush_called, write_called = [], []
|
||||
class BufferedWriter(self.BufferedWriter):
|
||||
def flush(self, *args, **kwargs):
|
||||
flush_called.append(True)
|
||||
return super().flush(*args, **kwargs)
|
||||
def write(self, *args, **kwargs):
|
||||
write_called.append(True)
|
||||
return super().write(*args, **kwargs)
|
||||
|
||||
rawio = self.BytesIO()
|
||||
data = b"a"
|
||||
bufio = BufferedWriter(rawio, len(data)*2)
|
||||
textio = self.TextIOWrapper(bufio, encoding='ascii',
|
||||
write_through=True)
|
||||
# write to the buffered io but don't overflow the buffer
|
||||
text = data.decode('ascii')
|
||||
textio.write(text)
|
||||
|
||||
# buffer.flush is not called with write_through=True
|
||||
self.assertFalse(flush_called)
|
||||
# buffer.write *is* called with write_through=True
|
||||
self.assertTrue(write_called)
|
||||
self.assertEqual(rawio.getvalue(), b"") # no flush
|
||||
|
||||
write_called = [] # reset
|
||||
textio.write(text * 10) # total content is larger than bufio buffer
|
||||
self.assertTrue(write_called)
|
||||
self.assertEqual(rawio.getvalue(), data * 11) # all flushed
|
||||
|
||||
def test_read_nonbytes(self):
|
||||
# Issue #17106
|
||||
# Crash when underlying read() returns non-bytes
|
||||
|
|
|
@ -786,6 +786,7 @@ class ProcessTestCase(BaseTestCase):
|
|||
stdout=subprocess.PIPE,
|
||||
universal_newlines=1)
|
||||
p.stdin.write("line1\n")
|
||||
p.stdin.flush()
|
||||
self.assertEqual(p.stdout.readline(), "line1\n")
|
||||
p.stdin.write("line3\n")
|
||||
p.stdin.close()
|
||||
|
|
|
@ -24,6 +24,7 @@ Jim Ahlstrom
|
|||
Farhan Ahmad
|
||||
Matthew Ahrens
|
||||
Nir Aides
|
||||
Akira
|
||||
Yaniv Aknin
|
||||
Jyrki Alakuijala
|
||||
Steve Alexander
|
||||
|
|
|
@ -7,6 +7,12 @@ What's New in Python 3.4.1?
|
|||
|
||||
Release date: TBA
|
||||
|
||||
Library
|
||||
-------
|
||||
|
||||
- Issue #21396: Fix TextIOWrapper(..., write_through=True) to not force a
|
||||
flush() on the underlying binary stream. Patch by akira.
|
||||
|
||||
Tests
|
||||
-----
|
||||
|
||||
|
|
|
@ -1297,7 +1297,7 @@ textiowrapper_write(textio *self, PyObject *args)
|
|||
PyObject *b;
|
||||
Py_ssize_t textlen;
|
||||
int haslf = 0;
|
||||
int needflush = 0;
|
||||
int needflush = 0, text_needflush = 0;
|
||||
|
||||
CHECK_INITIALIZED(self);
|
||||
|
||||
|
@ -1331,8 +1331,8 @@ textiowrapper_write(textio *self, PyObject *args)
|
|||
}
|
||||
|
||||
if (self->write_through)
|
||||
needflush = 1;
|
||||
else if (self->line_buffering &&
|
||||
text_needflush = 1;
|
||||
if (self->line_buffering &&
|
||||
(haslf ||
|
||||
PyUnicode_FindChar(text, '\r', 0, PyUnicode_GET_LENGTH(text), 1) != -1))
|
||||
needflush = 1;
|
||||
|
@ -1363,7 +1363,8 @@ textiowrapper_write(textio *self, PyObject *args)
|
|||
}
|
||||
self->pending_bytes_count += PyBytes_GET_SIZE(b);
|
||||
Py_DECREF(b);
|
||||
if (self->pending_bytes_count > self->chunk_size || needflush) {
|
||||
if (self->pending_bytes_count > self->chunk_size || needflush ||
|
||||
text_needflush) {
|
||||
if (_textiowrapper_writeflush(self) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue