diff -r c8c9971bdc53 Doc/library/bz2.rst --- a/Doc/library/bz2.rst Thu Feb 27 18:48:13 2014 -0500 +++ b/Doc/library/bz2.rst Thu Mar 06 16:55:26 2014 +0800 @@ -89,11 +89,11 @@ :class:`BZ2File` also provides the following method: - .. method:: peek([n]) + .. method:: peek(n=-1) - Return buffered data without advancing the file position. At least one - byte of data will be returned (unless at EOF). The exact number of bytes - returned is unspecified. + Return n bytes of buffered data without advancing the file position. If + n is omitted or negative, returns all the remaining bytes. The exact + number of bytes returned is unspecified. .. note:: While calling :meth:`peek` does not change the file position of the :class:`BZ2File`, it may change the position of the underlying file diff -r c8c9971bdc53 Lib/bz2.py --- a/Lib/bz2.py Thu Feb 27 18:48:13 2014 -0500 +++ b/Lib/bz2.py Thu Mar 06 16:55:26 2014 +0800 @@ -265,17 +265,20 @@ if return_data: return b"".join(blocks) - def peek(self, n=0): - """Return buffered data without advancing the file position. + def peek(self, n=-1): + """Return n bytes of buffered data without advancing the file position. - Always returns at least one byte of data, unless at EOF. - The exact number of bytes returned is unspecified. + If n is omitted or negative, returns all the remaining bytes. The exact + number of bytes returned is unspecified. """ with self._lock: self._check_can_read() - if not self._fill_buffer(): + if not self._fill_buffer() or n == 0: return b"" - return self._buffer[self._buffer_offset:] + elif n < 0: + return self._buffer[self._buffer_offset:] + else: + return self._buffer[self._buffer_offset:self._buffer_offset+n] def read(self, size=-1): """Read up to size uncompressed bytes from the file. diff -r c8c9971bdc53 Lib/test/test_bz2.py --- a/Lib/test/test_bz2.py Thu Feb 27 18:48:13 2014 -0500 +++ b/Lib/test/test_bz2.py Thu Mar 06 16:55:26 2014 +0800 @@ -173,6 +173,21 @@ self.assertNotEqual(len(pdata), 0) self.assertTrue(self.TEXT.startswith(pdata)) self.assertEqual(bz2f.read(), self.TEXT) + pdata = bz2f.peek() + self.assertEqual(len(pdata), 0) + + def testPeekLimited(self): + self.createTempFile() + with BZ2File(self.filename) as bz2f: + for expected in [b'root:x:0:0:root:/root:/bin/bash\n', + b'bin:x:1:1:bin:/bin:\n']: + expected_length = len(expected) + pdata = bz2f.peek(n=expected_length) + self.assertEqual(pdata, expected) + data = bz2f.read(size=expected_length) + self.assertEqual(data, expected) + pdata = bz2f.peek(n=0) + self.assertEqual(pdata, b'') def testReadInto(self): self.createTempFile() @@ -564,6 +579,21 @@ self.assertNotEqual(len(pdata), 0) self.assertTrue(self.TEXT.startswith(pdata)) self.assertEqual(bz2f.read(), self.TEXT) + pdata = bz2f.peek() + self.assertEqual(len(pdata), 0) + + def testPeekBytesIOLimited(self): + with BytesIO(self.DATA) as bio: + with BZ2File(bio) as bz2f: + for expected in [b'root:x:0:0:root:/root:/bin/bash\n', + b'bin:x:1:1:bin:/bin:\n']: + expected_length = len(expected) + pdata = bz2f.peek(n=expected_length) + self.assertEqual(pdata, expected) + data = bz2f.read(size=expected_length) + self.assertEqual(data, expected) + pdata = bz2f.peek(n=0) + self.assertEqual(pdata, b'') def testWriteBytesIO(self): with BytesIO() as bio: