]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-33361: Fix bug with seeking in StreamRecoders (GH-8278)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 31 May 2019 20:03:22 +0000 (13:03 -0700)
committerBerker Peksag <berker.peksag@gmail.com>
Fri, 31 May 2019 20:03:22 +0000 (23:03 +0300)
(cherry picked from commit a6ec1ce1ac05b1258931422e96eac215b6a05459)

Co-authored-by: Ammar Askar <ammar_askar@hotmail.com>
Lib/codecs.py
Lib/test/test_codecs.py
Misc/NEWS.d/next/Library/2018-07-13-20-17-17.bpo-33361.dx2NVn.rst [new file with mode: 0644]

index 3cd78fc9f1970e3e3c2adeee00a1c015919f4f45..cfca5d38b0795f5f512c7f00b0eb26080470208b 100644 (file)
@@ -847,6 +847,12 @@ class StreamRecoder:
         self.reader.reset()
         self.writer.reset()
 
+    def seek(self, offset, whence=0):
+        # Seeks must be propagated to both the readers and writers
+        # as they might need to reset their internal buffers.
+        self.reader.seek(offset, whence)
+        self.writer.seek(offset, whence)
+
     def __getattr__(self, name,
                     getattr=getattr):
 
index a3a2f6563a1f1bd9fd73e00c761284d4b8482ce9..248ef6fe07dd2895124a3ca89e05fd5b7e294df8 100644 (file)
@@ -3318,6 +3318,31 @@ class StreamRecoderTest(unittest.TestCase):
         sr.write(text.encode('latin1'))
         self.assertEqual(bio.getvalue(), text.encode('utf-8'))
 
+    def test_seeking_read(self):
+        bio = io.BytesIO('line1\nline2\nline3\n'.encode('utf-16-le'))
+        sr = codecs.EncodedFile(bio, 'utf-8', 'utf-16-le')
+
+        self.assertEqual(sr.readline(), b'line1\n')
+        sr.seek(0)
+        self.assertEqual(sr.readline(), b'line1\n')
+        self.assertEqual(sr.readline(), b'line2\n')
+        self.assertEqual(sr.readline(), b'line3\n')
+        self.assertEqual(sr.readline(), b'')
+
+    def test_seeking_write(self):
+        bio = io.BytesIO('123456789\n'.encode('utf-16-le'))
+        sr = codecs.EncodedFile(bio, 'utf-8', 'utf-16-le')
+
+        # Test that seek() only resets its internal buffer when offset
+        # and whence are zero.
+        sr.seek(2)
+        sr.write(b'\nabc\n')
+        self.assertEqual(sr.readline(), b'789\n')
+        sr.seek(0)
+        self.assertEqual(sr.readline(), b'1\n')
+        self.assertEqual(sr.readline(), b'abc\n')
+        self.assertEqual(sr.readline(), b'789\n')
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/NEWS.d/next/Library/2018-07-13-20-17-17.bpo-33361.dx2NVn.rst b/Misc/NEWS.d/next/Library/2018-07-13-20-17-17.bpo-33361.dx2NVn.rst
new file mode 100644 (file)
index 0000000..2b71095
--- /dev/null
@@ -0,0 +1,2 @@
+Fix a bug in :class:`codecs.StreamRecoder` where seeking might leave old data in a
+buffer and break subsequent read calls. Patch by Ammar Askar.