Issue #9962: GzipFile now has the peek() method.
This commit is contained in:
parent
4c2e4fa242
commit
c3ed2e7f83
|
@ -25,10 +25,10 @@ The module defines the following items:
|
||||||
|
|
||||||
.. class:: GzipFile(filename=None, mode=None, compresslevel=9, fileobj=None, mtime=None)
|
.. class:: GzipFile(filename=None, mode=None, compresslevel=9, fileobj=None, mtime=None)
|
||||||
|
|
||||||
Constructor for the :class:`GzipFile` class, which simulates most of the methods
|
Constructor for the :class:`GzipFile` class, which simulates most of the
|
||||||
of a :term:`file object`, with the exception of the :meth:`readinto` and
|
methods of a :term:`file object`, with the exception of the :meth:`truncate`
|
||||||
:meth:`truncate` methods. At least one of *fileobj* and *filename* must be
|
method. At least one of *fileobj* and *filename* must be given a non-trivial
|
||||||
given a non-trivial value.
|
value.
|
||||||
|
|
||||||
The new class instance is based on *fileobj*, which can be a regular file, a
|
The new class instance is based on *fileobj*, which can be a regular file, a
|
||||||
:class:`StringIO` object, or any other object which simulates a file. It
|
:class:`StringIO` object, or any other object which simulates a file. It
|
||||||
|
@ -66,8 +66,9 @@ The module defines the following items:
|
||||||
writing as *fileobj*, and retrieve the resulting memory buffer using the
|
writing as *fileobj*, and retrieve the resulting memory buffer using the
|
||||||
:class:`io.BytesIO` object's :meth:`~io.BytesIO.getvalue` method.
|
:class:`io.BytesIO` object's :meth:`~io.BytesIO.getvalue` method.
|
||||||
|
|
||||||
:class:`GzipFile` supports the whole :class:`io.BufferedIOBase` interface,
|
:class:`GzipFile` supports the :class:`io.BufferedIOBase` interface,
|
||||||
including iteration and the :keyword:`with` statement.
|
including iteration and the :keyword:`with` statement. Only the
|
||||||
|
:meth:`truncate` method isn't implemented.
|
||||||
|
|
||||||
.. versionchanged:: 3.1
|
.. versionchanged:: 3.1
|
||||||
Support for the :keyword:`with` statement was added.
|
Support for the :keyword:`with` statement was added.
|
||||||
|
@ -78,6 +79,9 @@ The module defines the following items:
|
||||||
.. versionchanged:: 3.2
|
.. versionchanged:: 3.2
|
||||||
Support for unseekable files was added.
|
Support for unseekable files was added.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.2
|
||||||
|
The :meth:`peek` method was implemented.
|
||||||
|
|
||||||
|
|
||||||
.. function:: open(filename, mode='rb', compresslevel=9)
|
.. function:: open(filename, mode='rb', compresslevel=9)
|
||||||
|
|
||||||
|
|
25
Lib/gzip.py
25
Lib/gzip.py
|
@ -204,7 +204,10 @@ class GzipFile(io.BufferedIOBase):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
s = repr(self.fileobj)
|
fileobj = self.fileobj
|
||||||
|
if isinstance(fileobj, _PaddedFile):
|
||||||
|
fileobj = fileobj.file
|
||||||
|
s = repr(fileobj)
|
||||||
return '<gzip ' + s[1:-1] + ' ' + hex(id(self)) + '>'
|
return '<gzip ' + s[1:-1] + ' ' + hex(id(self)) + '>'
|
||||||
|
|
||||||
def _init_write(self, filename):
|
def _init_write(self, filename):
|
||||||
|
@ -336,6 +339,26 @@ class GzipFile(io.BufferedIOBase):
|
||||||
self.offset += size
|
self.offset += size
|
||||||
return chunk
|
return chunk
|
||||||
|
|
||||||
|
def peek(self, n):
|
||||||
|
if self.mode != READ:
|
||||||
|
import errno
|
||||||
|
raise IOError(errno.EBADF, "read() on write-only GzipFile object")
|
||||||
|
|
||||||
|
# Do not return ridiculously small buffers
|
||||||
|
if n < 100:
|
||||||
|
n = 100
|
||||||
|
if self.extrasize == 0:
|
||||||
|
if self.fileobj is None:
|
||||||
|
return b''
|
||||||
|
try:
|
||||||
|
self._read(max(self.max_read_chunk, n))
|
||||||
|
except EOFError:
|
||||||
|
pass
|
||||||
|
offset = self.offset - self.extrastart
|
||||||
|
remaining = self.extrasize
|
||||||
|
assert remaining == len(self.extrabuf) - offset
|
||||||
|
return self.extrabuf[offset:offset + n]
|
||||||
|
|
||||||
def _unread(self, buf):
|
def _unread(self, buf):
|
||||||
self.extrasize = len(buf) + self.extrasize
|
self.extrasize = len(buf) + self.extrasize
|
||||||
self.offset -= len(buf)
|
self.offset -= len(buf)
|
||||||
|
|
|
@ -286,6 +286,28 @@ class TestGzip(unittest.TestCase):
|
||||||
with gzip.GzipFile(fileobj=buf, mode="rb") as f:
|
with gzip.GzipFile(fileobj=buf, mode="rb") as f:
|
||||||
self.assertEqual(f.read(), uncompressed)
|
self.assertEqual(f.read(), uncompressed)
|
||||||
|
|
||||||
|
def test_peek(self):
|
||||||
|
uncompressed = data1 * 200
|
||||||
|
with gzip.GzipFile(self.filename, "wb") as f:
|
||||||
|
f.write(uncompressed)
|
||||||
|
|
||||||
|
def sizes():
|
||||||
|
while True:
|
||||||
|
for n in range(5, 50, 10):
|
||||||
|
yield n
|
||||||
|
|
||||||
|
with gzip.GzipFile(self.filename, "rb") as f:
|
||||||
|
f.max_read_chunk = 33
|
||||||
|
nread = 0
|
||||||
|
for n in sizes():
|
||||||
|
s = f.peek(n)
|
||||||
|
if s == b'':
|
||||||
|
break
|
||||||
|
self.assertEqual(f.read(len(s)), s)
|
||||||
|
nread += len(s)
|
||||||
|
self.assertEqual(f.read(100), b'')
|
||||||
|
self.assertEqual(nread, len(uncompressed))
|
||||||
|
|
||||||
# Testing compress/decompress shortcut functions
|
# Testing compress/decompress shortcut functions
|
||||||
|
|
||||||
def test_compress(self):
|
def test_compress(self):
|
||||||
|
|
|
@ -76,6 +76,8 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #9962: GzipFile now has the peek() method.
|
||||||
|
|
||||||
- Issue #9090: When a socket with a timeout fails with EWOULDBLOCK or EAGAIN,
|
- Issue #9090: When a socket with a timeout fails with EWOULDBLOCK or EAGAIN,
|
||||||
retry the select() loop instead of bailing out. This is because select()
|
retry the select() loop instead of bailing out. This is because select()
|
||||||
can incorrectly report a socket as ready for reading (for example, if it
|
can incorrectly report a socket as ready for reading (for example, if it
|
||||||
|
|
Loading…
Reference in New Issue