From c400610321dcd16bff1e45ecb72a51244d43fbac Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 15 May 2010 20:33:07 +0000 Subject: [PATCH] Issue #7640: In the new `io` module, fix relative seek() for buffered readable streams when the internal buffer isn't empty. Patch by Pascal Chambon. --- Lib/io.py | 4 ++++ Lib/test/test_io.py | 17 ++++++++++++++++- Misc/NEWS | 4 ++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Lib/io.py b/Lib/io.py index 54de5040ae9..1458b471fa0 100644 --- a/Lib/io.py +++ b/Lib/io.py @@ -1199,6 +1199,10 @@ class BufferedRandom(BufferedWriter, BufferedReader): self.flush() # First do the raw seek, then empty the read buffer, so that # if the raw seek fails, we don't lose buffered data forever. + if self._read_buf and whence == 1: + # Undo read ahead. + with self._read_lock: + self.raw.seek(self._read_pos - len(self._read_buf), 1) pos = self.raw.seek(pos, whence) with self._read_lock: self._reset_read_buf() diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index c732b1fe685..aebe67bd87f 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -107,6 +107,10 @@ class IOTest(unittest.TestCase): self.assertEqual(f.truncate(12), 12) self.assertEqual(f.tell(), 13) + self.assertEqual(f.write(b"hij"), 3) + self.assertEqual(f.seek(0,1), 16) + self.assertEqual(f.tell(), 16) + self.assertEqual(f.truncate(12), 12) self.assertRaises(TypeError, f.seek, 0.0) def read_ops(self, f, buffered=False): @@ -129,6 +133,10 @@ class IOTest(unittest.TestCase): self.assertEqual(f.seek(-6, 1), 5) self.assertEqual(f.read(5), b" worl") self.assertEqual(f.tell(), 10) + f.seek(0) + f.read(2) + f.seek(0, 1) + self.assertEqual(f.tell(), 2) self.assertRaises(TypeError, f.seek, 0.0) if buffered: f.seek(0) @@ -182,6 +190,13 @@ class IOTest(unittest.TestCase): self.assertEqual(f.writable(), False) self.assertEqual(f.seekable(), True) self.read_ops(f, True) + f = io.open(test_support.TESTFN, "r+b") + self.assertEqual(f.readable(), True) + self.assertEqual(f.writable(), True) + self.assertEqual(f.seekable(), True) + self.write_ops(f) + f.seek(0) + self.read_ops(f, True) f.close() def test_readline(self): @@ -513,7 +528,7 @@ class BufferedWriterTest(unittest.TestCase): self.assertEquals(b"abcdefghijkl", writer._write_stack[0]) def testWriteNonBlocking(self): - raw = MockNonBlockWriterIO((9, 2, 22, -6, 10, 12, 12)) + raw = MockNonBlockWriterIO((9, 2, 10, -6, 10, 8, 12)) bufio = io.BufferedWriter(raw, 8, 16) bufio.write(b"asdf") diff --git a/Misc/NEWS b/Misc/NEWS index 17a657a4dd3..e219439d18f 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -39,6 +39,10 @@ Core and Builtins Library ------- +- Issue #7640: In the new `io` module, fix relative seek() for buffered + readable streams when the internal buffer isn't empty. Patch by Pascal + Chambon. + - Issue #5099: subprocess.Popen.__del__ no longer references global objects, leading to issues during interpreter shutdown.