summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2024-01-08 10:47:50 (GMT)
committerGitHub <noreply@github.com>2024-01-08 10:47:50 (GMT)
commit4db8d3be49b3a229932a24f6271d3f062843d08f (patch)
tree84979a161808c217c0622fe1076a7788f23f0242
parent320c160b1ace14be54f63b580af7adabe6b34a97 (diff)
downloadcpython-4db8d3be49b3a229932a24f6271d3f062843d08f.zip
cpython-4db8d3be49b3a229932a24f6271d3f062843d08f.tar.gz
cpython-4db8d3be49b3a229932a24f6271d3f062843d08f.tar.bz2
[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 73c93265634257b1488262097e024c1727260cfd) Co-authored-by: Zackery Spytz <zspytz@gmail.com>
-rw-r--r--Lib/_pyio.py10
-rw-r--r--Lib/test/test_io.py8
-rw-r--r--Misc/NEWS.d/next/Library/2020-10-03-23-47-28.bpo-35928.E0iPAa.rst2
-rw-r--r--Modules/_io/textio.c12
4 files changed, 24 insertions, 8 deletions
diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index 0bfdeaa..16d025b 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -2224,8 +2224,9 @@ class TextIOWrapper(TextIOBase):
self.buffer.write(b)
if self._line_buffering and (haslf or "\r" in s):
self.flush()
- self._set_decoded_chars('')
- self._snapshot = None
+ if self._snapshot is not None:
+ self._set_decoded_chars('')
+ self._snapshot = None
if self._decoder:
self._decoder.reset()
return length
@@ -2539,8 +2540,9 @@ class TextIOWrapper(TextIOBase):
# Read everything.
result = (self._get_decoded_chars() +
decoder.decode(self.buffer.read(), final=True))
- self._set_decoded_chars('')
- self._snapshot = None
+ if self._snapshot is not None:
+ self._set_decoded_chars('')
+ self._snapshot = None
return result
else:
# Keep reading chunks until we have size characters to return.
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index 7853705..3dae789 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -3788,6 +3788,14 @@ class TextIOWrapperTest(unittest.TestCase):
t.write('x')
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):
'''A BytesIO object whose read method returns memoryviews
diff --git a/Misc/NEWS.d/next/Library/2020-10-03-23-47-28.bpo-35928.E0iPAa.rst b/Misc/NEWS.d/next/Library/2020-10-03-23-47-28.bpo-35928.E0iPAa.rst
new file mode 100644
index 0000000..c63e616
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-10-03-23-47-28.bpo-35928.E0iPAa.rst
@@ -0,0 +1,2 @@
+:class:`io.TextIOWrapper` now correctly handles the decoding buffer after
+``read()`` and ``write()``.
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index b994dc3..3de4c06 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -1745,8 +1745,10 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text)
Py_DECREF(ret);
}
- textiowrapper_set_decoded_chars(self, NULL);
- Py_CLEAR(self->snapshot);
+ if (self->snapshot != NULL) {
+ textiowrapper_set_decoded_chars(self, NULL);
+ Py_CLEAR(self->snapshot);
+ }
if (self->decoder) {
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)
goto fail;
- textiowrapper_set_decoded_chars(self, NULL);
- Py_CLEAR(self->snapshot);
+ if (self->snapshot != NULL) {
+ textiowrapper_set_decoded_chars(self, NULL);
+ Py_CLEAR(self->snapshot);
+ }
return result;
}
else {