Index: Lib/io.py =================================================================== --- Lib/io.py (revision 77320) +++ Lib/io.py (working copy) @@ -1019,6 +1019,8 @@ return self.raw.tell() - len(self._read_buf) + self._read_pos def seek(self, pos, whence=0): + if not (0 <= whence <= 2): + raise ValueError("invalid whence value") with self._read_lock: if whence == 1: pos -= len(self._read_buf) - self._read_pos @@ -1097,6 +1099,8 @@ try: while self._write_buf: n = self.raw.write(self._write_buf) + if n > len(self._write_buf) or n < 0: + raise IOError("write() returned incorrect number of bytes : %d vs %d for buf %s"%(n, len(self._write_buf), self._write_buf)) del self._write_buf[:n] written += n except BlockingIOError as e: @@ -1109,6 +1113,8 @@ return self.raw.tell() + len(self._write_buf) def seek(self, pos, whence=0): + if not (0 <= whence <= 2): + raise ValueError("invalid whence") with self._write_lock: self._flush_unlocked() return self.raw.seek(pos, whence) @@ -1197,7 +1203,13 @@ BufferedWriter.__init__(self, raw, buffer_size, max_buffer_size) def seek(self, pos, whence=0): + if not (0 <= whence <= 2): + raise ValueError("invalid whence") self.flush() + if self._read_buf: + # Undo read ahead. + with self._read_lock: + self.raw.seek(self._read_pos - len(self._read_buf), 1) # First do the raw seek, then empty the read buffer, so that # if the raw seek fails, we don't lose buffered data forever. pos = self.raw.seek(pos, whence) Index: Lib/test/test_io.py =================================================================== --- Lib/test/test_io.py (revision 77320) +++ Lib/test/test_io.py (working copy) @@ -100,6 +100,10 @@ self.assertEqual(f.tell(), 13) self.assertEqual(f.truncate(12), 12) self.assertEqual(f.tell(), 12) + self.assertEqual(f.write(b"hij"), 3) + self.assertEqual(f.seek(0,1), 15) + self.assertEqual(f.tell(), 15) + self.assertEqual(f.truncate(12), 12) self.assertRaises(TypeError, f.seek, 0.0) def read_ops(self, f, buffered=False): @@ -122,6 +126,10 @@ 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) @@ -175,6 +183,13 @@ 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): @@ -492,7 +507,7 @@ 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")