mirror of
https://github.com/python/cpython.git
synced 2025-08-18 15:51:23 +00:00
[3.11] gh-80109: Fix io.TextIOWrapper dropping the internal buffer during write() (GH-22535) (GH-113809)
io.TextIOWrapper was dropping the internal decoding buffer
during read() and write() calls.
(cherry picked from commit 73c9326563
)
Co-authored-by: Zackery Spytz <zspytz@gmail.com>
This commit is contained in:
parent
320c160b1a
commit
4db8d3be49
4 changed files with 24 additions and 8 deletions
10
Lib/_pyio.py
10
Lib/_pyio.py
|
@ -2224,8 +2224,9 @@ class TextIOWrapper(TextIOBase):
|
||||||
self.buffer.write(b)
|
self.buffer.write(b)
|
||||||
if self._line_buffering and (haslf or "\r" in s):
|
if self._line_buffering and (haslf or "\r" in s):
|
||||||
self.flush()
|
self.flush()
|
||||||
self._set_decoded_chars('')
|
if self._snapshot is not None:
|
||||||
self._snapshot = None
|
self._set_decoded_chars('')
|
||||||
|
self._snapshot = None
|
||||||
if self._decoder:
|
if self._decoder:
|
||||||
self._decoder.reset()
|
self._decoder.reset()
|
||||||
return length
|
return length
|
||||||
|
@ -2539,8 +2540,9 @@ class TextIOWrapper(TextIOBase):
|
||||||
# Read everything.
|
# Read everything.
|
||||||
result = (self._get_decoded_chars() +
|
result = (self._get_decoded_chars() +
|
||||||
decoder.decode(self.buffer.read(), final=True))
|
decoder.decode(self.buffer.read(), final=True))
|
||||||
self._set_decoded_chars('')
|
if self._snapshot is not None:
|
||||||
self._snapshot = None
|
self._set_decoded_chars('')
|
||||||
|
self._snapshot = None
|
||||||
return result
|
return result
|
||||||
else:
|
else:
|
||||||
# Keep reading chunks until we have size characters to return.
|
# Keep reading chunks until we have size characters to return.
|
||||||
|
|
|
@ -3788,6 +3788,14 @@ class TextIOWrapperTest(unittest.TestCase):
|
||||||
t.write('x')
|
t.write('x')
|
||||||
t.tell()
|
t.tell()
|
||||||
|
|
||||||
|
def test_issue35928(self):
|
||||||
|
p = self.BufferedRWPair(self.BytesIO(b'foo\nbar\n'), self.BytesIO())
|
||||||
|
f = self.TextIOWrapper(p)
|
||||||
|
res = f.readline()
|
||||||
|
self.assertEqual(res, 'foo\n')
|
||||||
|
f.write(res)
|
||||||
|
self.assertEqual(res + f.readline(), 'foo\nbar\n')
|
||||||
|
|
||||||
|
|
||||||
class MemviewBytesIO(io.BytesIO):
|
class MemviewBytesIO(io.BytesIO):
|
||||||
'''A BytesIO object whose read method returns memoryviews
|
'''A BytesIO object whose read method returns memoryviews
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
:class:`io.TextIOWrapper` now correctly handles the decoding buffer after
|
||||||
|
``read()`` and ``write()``.
|
|
@ -1745,8 +1745,10 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text)
|
||||||
Py_DECREF(ret);
|
Py_DECREF(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
textiowrapper_set_decoded_chars(self, NULL);
|
if (self->snapshot != NULL) {
|
||||||
Py_CLEAR(self->snapshot);
|
textiowrapper_set_decoded_chars(self, NULL);
|
||||||
|
Py_CLEAR(self->snapshot);
|
||||||
|
}
|
||||||
|
|
||||||
if (self->decoder) {
|
if (self->decoder) {
|
||||||
ret = PyObject_CallMethodNoArgs(self->decoder, &_Py_ID(reset));
|
ret = PyObject_CallMethodNoArgs(self->decoder, &_Py_ID(reset));
|
||||||
|
@ -1979,8 +1981,10 @@ _io_TextIOWrapper_read_impl(textio *self, Py_ssize_t n)
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
textiowrapper_set_decoded_chars(self, NULL);
|
if (self->snapshot != NULL) {
|
||||||
Py_CLEAR(self->snapshot);
|
textiowrapper_set_decoded_chars(self, NULL);
|
||||||
|
Py_CLEAR(self->snapshot);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue