mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
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
5 changed files with 45 additions and 4 deletions
|
@ -2615,6 +2615,38 @@ class TextIOWrapperTest(unittest.TestCase):
|
||||||
txt.write('5')
|
txt.write('5')
|
||||||
self.assertEqual(b''.join(raw._write_stack), b'123\n45')
|
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):
|
def test_read_nonbytes(self):
|
||||||
# Issue #17106
|
# Issue #17106
|
||||||
# Crash when underlying read() returns non-bytes
|
# Crash when underlying read() returns non-bytes
|
||||||
|
|
|
@ -786,6 +786,7 @@ class ProcessTestCase(BaseTestCase):
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
universal_newlines=1)
|
universal_newlines=1)
|
||||||
p.stdin.write("line1\n")
|
p.stdin.write("line1\n")
|
||||||
|
p.stdin.flush()
|
||||||
self.assertEqual(p.stdout.readline(), "line1\n")
|
self.assertEqual(p.stdout.readline(), "line1\n")
|
||||||
p.stdin.write("line3\n")
|
p.stdin.write("line3\n")
|
||||||
p.stdin.close()
|
p.stdin.close()
|
||||||
|
|
|
@ -24,6 +24,7 @@ Jim Ahlstrom
|
||||||
Farhan Ahmad
|
Farhan Ahmad
|
||||||
Matthew Ahrens
|
Matthew Ahrens
|
||||||
Nir Aides
|
Nir Aides
|
||||||
|
Akira
|
||||||
Yaniv Aknin
|
Yaniv Aknin
|
||||||
Jyrki Alakuijala
|
Jyrki Alakuijala
|
||||||
Steve Alexander
|
Steve Alexander
|
||||||
|
|
|
@ -7,6 +7,12 @@ What's New in Python 3.4.1?
|
||||||
|
|
||||||
Release date: TBA
|
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
|
Tests
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|
|
@ -1297,7 +1297,7 @@ textiowrapper_write(textio *self, PyObject *args)
|
||||||
PyObject *b;
|
PyObject *b;
|
||||||
Py_ssize_t textlen;
|
Py_ssize_t textlen;
|
||||||
int haslf = 0;
|
int haslf = 0;
|
||||||
int needflush = 0;
|
int needflush = 0, text_needflush = 0;
|
||||||
|
|
||||||
CHECK_INITIALIZED(self);
|
CHECK_INITIALIZED(self);
|
||||||
|
|
||||||
|
@ -1331,8 +1331,8 @@ textiowrapper_write(textio *self, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->write_through)
|
if (self->write_through)
|
||||||
needflush = 1;
|
text_needflush = 1;
|
||||||
else if (self->line_buffering &&
|
if (self->line_buffering &&
|
||||||
(haslf ||
|
(haslf ||
|
||||||
PyUnicode_FindChar(text, '\r', 0, PyUnicode_GET_LENGTH(text), 1) != -1))
|
PyUnicode_FindChar(text, '\r', 0, PyUnicode_GET_LENGTH(text), 1) != -1))
|
||||||
needflush = 1;
|
needflush = 1;
|
||||||
|
@ -1363,7 +1363,8 @@ textiowrapper_write(textio *self, PyObject *args)
|
||||||
}
|
}
|
||||||
self->pending_bytes_count += PyBytes_GET_SIZE(b);
|
self->pending_bytes_count += PyBytes_GET_SIZE(b);
|
||||||
Py_DECREF(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)
|
if (_textiowrapper_writeflush(self) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue