summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Lib/gzip.py
diff options
context:
space:
mode:
authorshadchin <[email protected]>2024-02-12 07:53:52 +0300
committerDaniil Cherednik <[email protected]>2024-02-14 14:26:16 +0000
commit31f2a419764a8ba77c2a970cfc80056c6cd06756 (patch)
treec1995d239eba8571cefc640f6648e1d5dd4ce9e2 /contrib/tools/python3/src/Lib/gzip.py
parentfe2ef02b38d9c85d80060963b265a1df9f38c3bb (diff)
Update Python from 3.11.8 to 3.12.2
Diffstat (limited to 'contrib/tools/python3/src/Lib/gzip.py')
-rw-r--r--contrib/tools/python3/src/Lib/gzip.py74
1 files changed, 50 insertions, 24 deletions
diff --git a/contrib/tools/python3/src/Lib/gzip.py b/contrib/tools/python3/src/Lib/gzip.py
index 5b20e5ba698..177f9080dc5 100644
--- a/contrib/tools/python3/src/Lib/gzip.py
+++ b/contrib/tools/python3/src/Lib/gzip.py
@@ -21,6 +21,9 @@ _COMPRESS_LEVEL_FAST = 1
_COMPRESS_LEVEL_TRADEOFF = 6
_COMPRESS_LEVEL_BEST = 9
+READ_BUFFER_SIZE = 128 * 1024
+_WRITE_BUFFER_SIZE = 4 * io.DEFAULT_BUFFER_SIZE
+
def open(filename, mode="rb", compresslevel=_COMPRESS_LEVEL_BEST,
encoding=None, errors=None, newline=None):
@@ -118,6 +121,21 @@ class BadGzipFile(OSError):
"""Exception raised in some cases for invalid gzip files."""
+class _WriteBufferStream(io.RawIOBase):
+ """Minimal object to pass WriteBuffer flushes into GzipFile"""
+ def __init__(self, gzip_file):
+ self.gzip_file = gzip_file
+
+ def write(self, data):
+ return self.gzip_file._write_raw(data)
+
+ def seekable(self):
+ return False
+
+ def writable(self):
+ return True
+
+
class GzipFile(_compression.BaseStream):
"""The GzipFile class simulates most of the methods of a file object with
the exception of the truncate() method.
@@ -182,6 +200,7 @@ class GzipFile(_compression.BaseStream):
if mode is None:
mode = getattr(fileobj, 'mode', 'rb')
+
if mode.startswith('r'):
self.mode = READ
raw = _GzipReader(fileobj)
@@ -204,6 +223,9 @@ class GzipFile(_compression.BaseStream):
zlib.DEF_MEM_LEVEL,
0)
self._write_mtime = mtime
+ self._buffer_size = _WRITE_BUFFER_SIZE
+ self._buffer = io.BufferedWriter(_WriteBufferStream(self),
+ buffer_size=self._buffer_size)
else:
raise ValueError("Invalid mode: {!r}".format(mode))
@@ -213,14 +235,6 @@ class GzipFile(_compression.BaseStream):
self._write_gzip_header(compresslevel)
@property
- def filename(self):
- import warnings
- warnings.warn("use the name attribute", DeprecationWarning, 2)
- if self.mode == WRITE and self.name[-3:] != ".gz":
- return self.name + ".gz"
- return self.name
-
- @property
def mtime(self):
"""Last modification time read from stream, or None"""
return self._buffer.raw._last_mtime
@@ -237,6 +251,11 @@ class GzipFile(_compression.BaseStream):
self.bufsize = 0
self.offset = 0 # Current file offset for seek(), tell(), etc
+ def tell(self):
+ self._check_not_closed()
+ self._buffer.flush()
+ return super().tell()
+
def _write_gzip_header(self, compresslevel):
self.fileobj.write(b'\037\213') # magic header
self.fileobj.write(b'\010') # compression method
@@ -278,6 +297,10 @@ class GzipFile(_compression.BaseStream):
if self.fileobj is None:
raise ValueError("write() on closed GzipFile object")
+ return self._buffer.write(data)
+
+ def _write_raw(self, data):
+ # Called by our self._buffer underlying WriteBufferStream.
if isinstance(data, (bytes, bytearray)):
length = len(data)
else:
@@ -328,9 +351,9 @@ class GzipFile(_compression.BaseStream):
fileobj = self.fileobj
if fileobj is None:
return
- self.fileobj = None
try:
if self.mode == WRITE:
+ self._buffer.flush()
fileobj.write(self.compress.flush())
write32u(fileobj, self.crc)
# self.size may exceed 2 GiB, or even 4 GiB
@@ -338,6 +361,7 @@ class GzipFile(_compression.BaseStream):
elif self.mode == READ:
self._buffer.close()
finally:
+ self.fileobj = None
myfileobj = self.myfileobj
if myfileobj:
self.myfileobj = None
@@ -346,6 +370,7 @@ class GzipFile(_compression.BaseStream):
def flush(self,zlib_mode=zlib.Z_SYNC_FLUSH):
self._check_not_closed()
if self.mode == WRITE:
+ self._buffer.flush()
# Ensure the compressor's buffer is flushed
self.fileobj.write(self.compress.flush(zlib_mode))
self.fileobj.flush()
@@ -376,6 +401,9 @@ class GzipFile(_compression.BaseStream):
def seek(self, offset, whence=io.SEEK_SET):
if self.mode == WRITE:
+ self._check_not_closed()
+ # Flush buffer to ensure validity of self.offset
+ self._buffer.flush()
if whence != io.SEEK_SET:
if whence == io.SEEK_CUR:
offset = self.offset + offset
@@ -384,10 +412,10 @@ class GzipFile(_compression.BaseStream):
if offset < self.offset:
raise OSError('Negative seek in write mode')
count = offset - self.offset
- chunk = b'\0' * 1024
- for i in range(count // 1024):
+ chunk = b'\0' * self._buffer_size
+ for i in range(count // self._buffer_size):
self.write(chunk)
- self.write(b'\0' * (count % 1024))
+ self.write(b'\0' * (count % self._buffer_size))
elif self.mode == READ:
self._check_not_closed()
return self._buffer.seek(offset, whence)
@@ -454,7 +482,7 @@ def _read_gzip_header(fp):
class _GzipReader(_compression.DecompressReader):
def __init__(self, fp):
- super().__init__(_PaddedFile(fp), zlib.decompressobj,
+ super().__init__(_PaddedFile(fp), zlib._ZlibDecompressor,
wbits=-zlib.MAX_WBITS)
# Set flag indicating start of a new member
self._new_member = True
@@ -502,12 +530,13 @@ class _GzipReader(_compression.DecompressReader):
self._new_member = False
# Read a chunk of data from the file
- buf = self._fp.read(io.DEFAULT_BUFFER_SIZE)
+ if self._decompressor.needs_input:
+ buf = self._fp.read(READ_BUFFER_SIZE)
+ uncompress = self._decompressor.decompress(buf, size)
+ else:
+ uncompress = self._decompressor.decompress(b"", size)
- uncompress = self._decompressor.decompress(buf, size)
- if self._decompressor.unconsumed_tail != b"":
- self._fp.prepend(self._decompressor.unconsumed_tail)
- elif self._decompressor.unused_data != b"":
+ if self._decompressor.unused_data != b"":
# Prepend the already read bytes to the fileobj so they can
# be seen by _read_eof() and _read_gzip_header()
self._fp.prepend(self._decompressor.unused_data)
@@ -518,14 +547,11 @@ class _GzipReader(_compression.DecompressReader):
raise EOFError("Compressed file ended before the "
"end-of-stream marker was reached")
- self._add_read_data( uncompress )
+ self._crc = zlib.crc32(uncompress, self._crc)
+ self._stream_size += len(uncompress)
self._pos += len(uncompress)
return uncompress
- def _add_read_data(self, data):
- self._crc = zlib.crc32(data, self._crc)
- self._stream_size = self._stream_size + len(data)
-
def _read_eof(self):
# We've read to the end of the file
# We check that the computed CRC and size of the
@@ -655,7 +681,7 @@ def main():
f = builtins.open(arg, "rb")
g = open(arg + ".gz", "wb")
while True:
- chunk = f.read(io.DEFAULT_BUFFER_SIZE)
+ chunk = f.read(READ_BUFFER_SIZE)
if not chunk:
break
g.write(chunk)