annotate lib/python/gzip_plus.py @ 353:6b1137bdbd0d trim

give access to block offsets via callback
author Henry S. Thompson <ht@inf.ed.ac.uk>
date Mon, 16 Mar 2026 10:43:01 +0000
parents 4ead0a390a29
children a0d476144685
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
350
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
1 """Functions that read and write gzipped files.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
2
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
3 The user of the file doesn't have to worry about the compression,
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
4 but random access is not allowed."""
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
5
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
6 # based on Andrew Kuchling's minigzip.py distributed with the zlib module
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
7
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
8 import _compression
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
9 import builtins
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
10 import io
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
11 import os
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
12 import struct
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
13 import sys
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
14 import time
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
15 import weakref
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
16 import zlib
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
17
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
18 __all__ = ["BadGzipFile", "GzipFile", "open", "compress", "decompress"]
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
19
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
20 FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
21
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
22 READ = 'rb'
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
23 WRITE = 'wb'
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
24
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
25 _COMPRESS_LEVEL_FAST = 1
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
26 _COMPRESS_LEVEL_TRADEOFF = 6
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
27 _COMPRESS_LEVEL_BEST = 9
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
28
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
29 READ_BUFFER_SIZE = 128 * 1024
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
30 _WRITE_BUFFER_SIZE = 4 * io.DEFAULT_BUFFER_SIZE
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
31
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
32
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
33 def open(filename, mode="rb", compresslevel=_COMPRESS_LEVEL_BEST,
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
34 encoding=None, errors=None, newline=None):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
35 """Open a gzip-compressed file in binary or text mode.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
36
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
37 The filename argument can be an actual filename (a str or bytes object), or
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
38 an existing file object to read from or write to.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
39
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
40 The mode argument can be "r", "rb", "w", "wb", "x", "xb", "a" or "ab" for
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
41 binary mode, or "rt", "wt", "xt" or "at" for text mode. The default mode is
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
42 "rb", and the default compresslevel is 9.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
43
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
44 For binary mode, this function is equivalent to the GzipFile constructor:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
45 GzipFile(filename, mode, compresslevel). In this case, the encoding, errors
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
46 and newline arguments must not be provided.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
47
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
48 For text mode, a GzipFile object is created, and wrapped in an
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
49 io.TextIOWrapper instance with the specified encoding, error handling
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
50 behavior, and line ending(s).
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
51
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
52 """
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
53 if "t" in mode:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
54 if "b" in mode:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
55 raise ValueError("Invalid mode: %r" % (mode,))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
56 else:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
57 if encoding is not None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
58 raise ValueError("Argument 'encoding' not supported in binary mode")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
59 if errors is not None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
60 raise ValueError("Argument 'errors' not supported in binary mode")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
61 if newline is not None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
62 raise ValueError("Argument 'newline' not supported in binary mode")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
63
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
64 gz_mode = mode.replace("t", "")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
65 if isinstance(filename, (str, bytes, os.PathLike)):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
66 binary_file = GzipFile(filename, gz_mode, compresslevel)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
67 elif hasattr(filename, "read") or hasattr(filename, "write"):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
68 binary_file = GzipFile(None, gz_mode, compresslevel, filename)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
69 else:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
70 raise TypeError("filename must be a str or bytes object, or a file")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
71
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
72 if "t" in mode:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
73 encoding = io.text_encoding(encoding)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
74 return io.TextIOWrapper(binary_file, encoding, errors, newline)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
75 else:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
76 return binary_file
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
77
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
78 def write32u(output, value):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
79 # The L format writes the bit pattern correctly whether signed
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
80 # or unsigned.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
81 output.write(struct.pack("<L", value))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
82
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
83 class _PaddedFile:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
84 """Minimal read-only file object that prepends a string to the contents
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
85 of an actual file. Shouldn't be used outside of gzip.py, as it lacks
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
86 essential functionality."""
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
87
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
88 def __init__(self, f, prepend=b''):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
89 #print('i',len(prepend))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
90 self._buffer = prepend
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
91 self._length = len(prepend)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
92 self.file = f
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
93 self._read = 0
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
94 self._pos = 0
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
95
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
96 def tell(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
97 if self._read is None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
98 return self.file.tell()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
99 else:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
100 return self._pos
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
101
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
102 def read(self, size):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
103 #print('r',size, self._read, self._length, self._pos)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
104 if self._read is None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
105 res = self.file.read(size)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
106 self._pos += len(res)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
107 #print('r1', self._pos)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
108 return res
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
109 if self._read + size <= self._length:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
110 read = self._read
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
111 self._read += size
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
112 self._pos += size
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
113 #print('r2', self._pos)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
114 return self._buffer[read:self._read]
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
115 else:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
116 read = self._read
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
117 self._read = None
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
118 avail = self._length - read
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
119 balance = size - avail
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
120 res = self.file.read(balance)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
121 self._pos += avail + len(res)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
122 #print('r3', self._pos)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
123 return self._buffer[read:] + res
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
124
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
125 def prepend(self, prepend=b''):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
126 #print('p',len(prepend))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
127 self._pos -= len(prepend)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
128 if self._read is None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
129 self._buffer = prepend
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
130 else: # Assume data was read since the last prepend() call
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
131 self._read -= len(prepend)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
132 return
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
133 self._length = len(self._buffer)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
134 self._read = 0
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
135
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
136 def seek(self, off):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
137 #print('o',off)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
138 self._read = None
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
139 self._buffer = None
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
140 self._pos = self.file.seek(off)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
141 return self._pos
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
142
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
143 def seekable(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
144 return True # Allows fast-forwarding even in unseekable streams
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
145
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
146
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
147 class BadGzipFile(OSError):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
148 """Exception raised in some cases for invalid gzip files."""
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
149
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
150
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
151 class _WriteBufferStream(io.RawIOBase):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
152 """Minimal object to pass WriteBuffer flushes into GzipFile"""
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
153 def __init__(self, gzip_file):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
154 self.gzip_file = weakref.ref(gzip_file)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
155
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
156 def write(self, data):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
157 gzip_file = self.gzip_file()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
158 if gzip_file is None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
159 raise RuntimeError("lost gzip_file")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
160 return gzip_file._write_raw(data)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
161
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
162 def seekable(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
163 return False
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
164
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
165 def writable(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
166 return True
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
167
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
168
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
169 class GzipFile(_compression.BaseStream):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
170 """The GzipFile class simulates most of the methods of a file object with
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
171 the exception of the truncate() method.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
172
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
173 This class only supports opening files in binary mode. If you need to open a
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
174 compressed file in text mode, use the gzip.open() function.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
175
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
176 """
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
177
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
178 # Overridden with internal file object to be closed, if only a filename
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
179 # is passed in
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
180 myfileobj = None
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
181
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
182 def __init__(self, filename=None, mode=None,
353
6b1137bdbd0d give access to block offsets via callback
Henry S. Thompson <ht@inf.ed.ac.uk>
parents: 350
diff changeset
183 compresslevel=_COMPRESS_LEVEL_BEST, fileobj=None, mtime=None,
6b1137bdbd0d give access to block offsets via callback
Henry S. Thompson <ht@inf.ed.ac.uk>
parents: 350
diff changeset
184 eob_callback=None):
350
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
185 """Constructor for the GzipFile class.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
186
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
187 At least one of fileobj and filename must be given a
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
188 non-trivial value.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
189
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
190 The new class instance is based on fileobj, which can be a regular
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
191 file, an io.BytesIO object, or any other object which simulates a file.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
192 It defaults to None, in which case filename is opened to provide
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
193 a file object.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
194
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
195 When fileobj is not None, the filename argument is only used to be
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
196 included in the gzip file header, which may include the original
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
197 filename of the uncompressed file. It defaults to the filename of
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
198 fileobj, if discernible; otherwise, it defaults to the empty string,
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
199 and in this case the original filename is not included in the header.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
200
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
201 The mode argument can be any of 'r', 'rb', 'a', 'ab', 'w', 'wb', 'x', or
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
202 'xb' depending on whether the file will be read or written. The default
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
203 is the mode of fileobj if discernible; otherwise, the default is 'rb'.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
204 A mode of 'r' is equivalent to one of 'rb', and similarly for 'w' and
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
205 'wb', 'a' and 'ab', and 'x' and 'xb'.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
206
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
207 The compresslevel argument is an integer from 0 to 9 controlling the
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
208 level of compression; 1 is fastest and produces the least compression,
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
209 and 9 is slowest and produces the most compression. 0 is no compression
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
210 at all. The default is 9.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
211
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
212 The optional mtime argument is the timestamp requested by gzip. The time
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
213 is in Unix format, i.e., seconds since 00:00:00 UTC, January 1, 1970.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
214 If mtime is omitted or None, the current time is used. Use mtime = 0
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
215 to generate a compressed stream that does not depend on creation time.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
216
353
6b1137bdbd0d give access to block offsets via callback
Henry S. Thompson <ht@inf.ed.ac.uk>
parents: 350
diff changeset
217 The optional eobCallback will be called with block boundaries if provided.
350
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
218 """
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
219
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
220 if mode and ('t' in mode or 'U' in mode):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
221 raise ValueError("Invalid mode: {!r}".format(mode))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
222 if mode and 'b' not in mode:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
223 mode += 'b'
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
224
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
225 try:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
226 if fileobj is None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
227 fileobj = self.myfileobj = builtins.open(filename, mode or 'rb')
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
228 if filename is None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
229 filename = getattr(fileobj, 'name', '')
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
230 if not isinstance(filename, (str, bytes)):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
231 filename = ''
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
232 else:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
233 filename = os.fspath(filename)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
234 origmode = mode
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
235 if mode is None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
236 mode = getattr(fileobj, 'mode', 'rb')
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
237
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
238
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
239 if mode.startswith('r'):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
240 self.mode = READ
353
6b1137bdbd0d give access to block offsets via callback
Henry S. Thompson <ht@inf.ed.ac.uk>
parents: 350
diff changeset
241 raw = _GzipReader(fileobj, eob_callback)
350
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
242 self._buffer = io.BufferedReader(raw)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
243 self.name = filename
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
244
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
245 elif mode.startswith(('w', 'a', 'x')):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
246 if origmode is None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
247 import warnings
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
248 warnings.warn(
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
249 "GzipFile was opened for writing, but this will "
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
250 "change in future Python releases. "
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
251 "Specify the mode argument for opening it for writing.",
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
252 FutureWarning, 2)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
253 self.mode = WRITE
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
254 self._init_write(filename)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
255 self.compress = zlib.compressobj(compresslevel,
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
256 zlib.DEFLATED,
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
257 -zlib.MAX_WBITS,
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
258 zlib.DEF_MEM_LEVEL,
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
259 0)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
260 self._write_mtime = mtime
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
261 self._buffer_size = _WRITE_BUFFER_SIZE
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
262 self._buffer = io.BufferedWriter(_WriteBufferStream(self),
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
263 buffer_size=self._buffer_size)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
264 else:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
265 raise ValueError("Invalid mode: {!r}".format(mode))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
266
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
267 self.fileobj = fileobj
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
268
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
269 if self.mode == WRITE:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
270 self._write_gzip_header(compresslevel)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
271 except:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
272 # Avoid a ResourceWarning if the write fails,
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
273 # eg read-only file or KeyboardInterrupt
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
274 self._close()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
275 raise
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
276
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
277 @property
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
278 def mtime(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
279 """Last modification time read from stream, or None"""
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
280 return self._buffer.raw._last_mtime
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
281
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
282 def __repr__(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
283 s = repr(self.fileobj)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
284 return '<gzip ' + s[1:-1] + ' ' + hex(id(self)) + '>'
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
285
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
286 def _init_write(self, filename):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
287 self.name = filename
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
288 self.crc = zlib.crc32(b"")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
289 self.size = 0
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
290 self.writebuf = []
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
291 self.bufsize = 0
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
292 self.offset = 0 # Current file offset for seek(), tell(), etc
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
293
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
294 def tell(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
295 self._check_not_closed()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
296 self._buffer.flush()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
297 return super().tell()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
298
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
299 def _write_gzip_header(self, compresslevel):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
300 self.fileobj.write(b'\037\213') # magic header
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
301 self.fileobj.write(b'\010') # compression method
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
302 try:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
303 # RFC 1952 requires the FNAME field to be Latin-1. Do not
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
304 # include filenames that cannot be represented that way.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
305 fname = os.path.basename(self.name)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
306 if not isinstance(fname, bytes):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
307 fname = fname.encode('latin-1')
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
308 if fname.endswith(b'.gz'):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
309 fname = fname[:-3]
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
310 except UnicodeEncodeError:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
311 fname = b''
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
312 flags = 0
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
313 if fname:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
314 flags = FNAME
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
315 self.fileobj.write(chr(flags).encode('latin-1'))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
316 mtime = self._write_mtime
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
317 if mtime is None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
318 mtime = time.time()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
319 write32u(self.fileobj, int(mtime))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
320 if compresslevel == _COMPRESS_LEVEL_BEST:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
321 xfl = b'\002'
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
322 elif compresslevel == _COMPRESS_LEVEL_FAST:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
323 xfl = b'\004'
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
324 else:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
325 xfl = b'\000'
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
326 self.fileobj.write(xfl)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
327 self.fileobj.write(b'\377')
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
328 if fname:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
329 self.fileobj.write(fname + b'\000')
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
330
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
331 def write(self,data):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
332 self._check_not_closed()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
333 if self.mode != WRITE:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
334 import errno
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
335 raise OSError(errno.EBADF, "write() on read-only GzipFile object")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
336
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
337 if self.fileobj is None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
338 raise ValueError("write() on closed GzipFile object")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
339
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
340 return self._buffer.write(data)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
341
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
342 def _write_raw(self, data):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
343 # Called by our self._buffer underlying WriteBufferStream.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
344 if isinstance(data, (bytes, bytearray)):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
345 length = len(data)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
346 else:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
347 # accept any data that supports the buffer protocol
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
348 data = memoryview(data)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
349 length = data.nbytes
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
350
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
351 if length > 0:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
352 self.fileobj.write(self.compress.compress(data))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
353 self.size += length
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
354 self.crc = zlib.crc32(data, self.crc)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
355 self.offset += length
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
356
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
357 return length
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
358
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
359 def read(self, size=-1):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
360 self._check_not_closed()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
361 if self.mode != READ:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
362 import errno
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
363 raise OSError(errno.EBADF, "read() on write-only GzipFile object")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
364 return self._buffer.read(size)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
365
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
366 def read1(self, size=-1):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
367 """Implements BufferedIOBase.read1()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
368
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
369 Reads up to a buffer's worth of data if size is negative."""
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
370 self._check_not_closed()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
371 if self.mode != READ:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
372 import errno
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
373 raise OSError(errno.EBADF, "read1() on write-only GzipFile object")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
374
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
375 if size < 0:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
376 size = io.DEFAULT_BUFFER_SIZE
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
377 return self._buffer.read1(size)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
378
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
379 def peek(self, n):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
380 self._check_not_closed()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
381 if self.mode != READ:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
382 import errno
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
383 raise OSError(errno.EBADF, "peek() on write-only GzipFile object")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
384 return self._buffer.peek(n)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
385
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
386 @property
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
387 def closed(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
388 return self.fileobj is None
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
389
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
390 def close(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
391 fileobj = self.fileobj
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
392 if fileobj is None or self._buffer.closed:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
393 return
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
394 try:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
395 if self.mode == WRITE:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
396 self._buffer.flush()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
397 fileobj.write(self.compress.flush())
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
398 write32u(fileobj, self.crc)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
399 # self.size may exceed 2 GiB, or even 4 GiB
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
400 write32u(fileobj, self.size & 0xffffffff)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
401 elif self.mode == READ:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
402 self._buffer.close()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
403 finally:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
404 self._close()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
405
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
406 def _close(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
407 self.fileobj = None
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
408 myfileobj = self.myfileobj
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
409 if myfileobj is not None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
410 self.myfileobj = None
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
411 myfileobj.close()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
412
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
413 def flush(self,zlib_mode=zlib.Z_SYNC_FLUSH):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
414 self._check_not_closed()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
415 if self.mode == WRITE:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
416 self._buffer.flush()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
417 # Ensure the compressor's buffer is flushed
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
418 self.fileobj.write(self.compress.flush(zlib_mode))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
419 self.fileobj.flush()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
420
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
421 def fileno(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
422 """Invoke the underlying file object's fileno() method.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
423
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
424 This will raise AttributeError if the underlying file object
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
425 doesn't support fileno().
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
426 """
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
427 return self.fileobj.fileno()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
428
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
429 def rewind(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
430 '''Return the uncompressed stream file position indicator to the
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
431 beginning of the file'''
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
432 if self.mode != READ:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
433 raise OSError("Can't rewind in write mode")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
434 self._buffer.seek(0)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
435
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
436 def readable(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
437 return self.mode == READ
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
438
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
439 def writable(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
440 return self.mode == WRITE
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
441
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
442 def seekable(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
443 return True
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
444
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
445 def seek(self, offset, whence=io.SEEK_SET):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
446 if self.mode == WRITE:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
447 self._check_not_closed()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
448 # Flush buffer to ensure validity of self.offset
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
449 self._buffer.flush()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
450 if whence != io.SEEK_SET:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
451 if whence == io.SEEK_CUR:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
452 offset = self.offset + offset
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
453 else:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
454 raise ValueError('Seek from end not supported')
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
455 if offset < self.offset:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
456 raise OSError('Negative seek in write mode')
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
457 count = offset - self.offset
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
458 chunk = b'\0' * self._buffer_size
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
459 for i in range(count // self._buffer_size):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
460 self.write(chunk)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
461 self.write(b'\0' * (count % self._buffer_size))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
462 elif self.mode == READ:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
463 self._check_not_closed()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
464 return self._buffer.seek(offset, whence)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
465
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
466 return self.offset
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
467
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
468 def readline(self, size=-1):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
469 self._check_not_closed()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
470 return self._buffer.readline(size)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
471
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
472
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
473 def _read_exact(fp, n):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
474 '''Read exactly *n* bytes from `fp`
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
475
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
476 This method is required because fp may be unbuffered,
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
477 i.e. return short reads.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
478 '''
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
479 data = fp.read(n)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
480 while len(data) < n:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
481 b = fp.read(n - len(data))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
482 if not b:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
483 raise EOFError("Compressed file ended before the "
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
484 "end-of-stream marker was reached")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
485 data += b
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
486 return data
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
487
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
488
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
489 def _read_gzip_header(fp):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
490 '''Read a gzip header from `fp` and progress to the end of the header.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
491
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
492 Returns last mtime if header was present or None otherwise.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
493 '''
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
494 magic = fp.read(2)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
495 if magic == b'':
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
496 return None
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
497
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
498 if magic != b'\037\213':
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
499 raise BadGzipFile('Not a gzipped file (%r)' % magic)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
500
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
501 (method, flag, last_mtime) = struct.unpack("<BBIxx", _read_exact(fp, 8))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
502 if method != 8:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
503 raise BadGzipFile('Unknown compression method')
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
504
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
505 if flag & FEXTRA:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
506 # Read & discard the extra field, if present
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
507 extra_len, = struct.unpack("<H", _read_exact(fp, 2))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
508 _read_exact(fp, extra_len)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
509 if flag & FNAME:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
510 # Read and discard a null-terminated string containing the filename
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
511 while True:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
512 s = fp.read(1)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
513 if not s or s==b'\000':
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
514 break
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
515 if flag & FCOMMENT:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
516 # Read and discard a null-terminated string containing a comment
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
517 while True:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
518 s = fp.read(1)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
519 if not s or s==b'\000':
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
520 break
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
521 if flag & FHCRC:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
522 _read_exact(fp, 2) # Read & discard the 16-bit header CRC
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
523 return last_mtime
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
524
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
525
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
526 class _GzipReader(_compression.DecompressReader):
353
6b1137bdbd0d give access to block offsets via callback
Henry S. Thompson <ht@inf.ed.ac.uk>
parents: 350
diff changeset
527 def __init__(self, fp, eob_callback):
350
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
528 super().__init__(_PaddedFile(fp), zlib._ZlibDecompressor,
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
529 wbits=-zlib.MAX_WBITS)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
530 # Set flag indicating start of a new member
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
531 self._new_member = True
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
532 self._last_mtime = None
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
533 self._cur_block = None
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
534 self._next_block = 0
353
6b1137bdbd0d give access to block offsets via callback
Henry S. Thompson <ht@inf.ed.ac.uk>
parents: 350
diff changeset
535 self._eob_callback = eob_callback
350
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
536
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
537 def _init_read(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
538 self._crc = zlib.crc32(b"")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
539 self._stream_size = 0 # Decompressed size of unconcatenated stream
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
540
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
541 def _read_gzip_header(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
542 last_mtime = _read_gzip_header(self._fp)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
543 if last_mtime is None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
544 return False
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
545 self._last_mtime = last_mtime
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
546 return True
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
547
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
548 def read(self, size=-1):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
549 if size < 0:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
550 return self.readall()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
551 # size=0 is special because decompress(max_length=0) is not supported
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
552 if not size:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
553 return b""
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
554
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
555 # For certain input data, a single
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
556 # call to decompress() may not return
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
557 # any data. In this case, retry until we get some data or reach EOF.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
558 while True:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
559 if self._decompressor.eof:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
560 # Ending case: we've come to the end of a member in the file,
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
561 # so finish up this member, and read a new gzip header.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
562 # Check the CRC and file size, and set the flag so we read
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
563 # a new member
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
564 self._read_eof()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
565 self._new_member = True
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
566 self._decompressor = self._decomp_factory(
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
567 **self._decomp_args)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
568
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
569 if self._new_member:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
570 # If the _new_member flag is set, we have to
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
571 # jump to the next member, if there is one.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
572 self._init_read()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
573 if not self._read_gzip_header():
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
574 return b""
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
575 self._new_member = False
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
576
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
577 # Read a chunk of data from the file
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
578 if self._decompressor.needs_input:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
579 buf = self._fp.read(READ_BUFFER_SIZE)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
580 uncompress = self._decompressor.decompress(buf, size)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
581 else:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
582 uncompress = self._decompressor.decompress(b"", size)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
583
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
584 if self._decompressor.unused_data != b"":
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
585 # Prepend the already read bytes to the fileobj so they can
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
586 # be seen by _read_eof() and _read_gzip_header()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
587 self._fp.prepend(self._decompressor.unused_data)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
588
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
589 if uncompress != b"":
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
590 break
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
591 if buf == b"":
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
592 raise EOFError("Compressed file ended before the "
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
593 "end-of-stream marker was reached")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
594
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
595 self._crc = zlib.crc32(uncompress, self._crc)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
596 self._stream_size += len(uncompress)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
597 return uncompress
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
598
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
599 def _read_eof(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
600 # We've read to the end of the file
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
601 # We check that the computed CRC and size of the
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
602 # uncompressed data matches the stored values. Note that the size
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
603 # stored is the true file size mod 2**32.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
604 crc32, isize = struct.unpack("<II", _read_exact(self._fp, 8))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
605 if crc32 != self._crc:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
606 raise BadGzipFile("CRC check failed %s != %s" % (hex(crc32),
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
607 hex(self._crc)))
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
608 elif isize != (self._stream_size & 0xffffffff):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
609 raise BadGzipFile("Incorrect length of data produced")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
610
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
611 # Gzip files can be padded with zeroes and still have archives.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
612 # Consume all zero bytes and set the file position to the first
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
613 # non-zero byte. See http://www.gzip.org/#faq8
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
614 c = b"\x00"
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
615 while c == b"\x00":
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
616 c = self._fp.read(1)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
617 # At this point we know how big the compressed data was:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
618 # 2+8+[x-y]+8+(1 * nzeros), which is available via _fp.tell()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
619 if c:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
620 self._fp.prepend(c)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
621
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
622 self._cur_block = self._next_block
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
623 self._next_block = self._fp.tell()
353
6b1137bdbd0d give access to block offsets via callback
Henry S. Thompson <ht@inf.ed.ac.uk>
parents: 350
diff changeset
624 if self._eob_callback is not None:
6b1137bdbd0d give access to block offsets via callback
Henry S. Thompson <ht@inf.ed.ac.uk>
parents: 350
diff changeset
625 self._eob_callback(self._cur_block, self._next_block)
350
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
626
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
627 def _rewind(self):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
628 super()._rewind()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
629 self._new_member = True
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
630
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
631
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
632 def compress(data, compresslevel=_COMPRESS_LEVEL_BEST, *, mtime=None):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
633 """Compress data in one shot and return the compressed string.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
634
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
635 compresslevel sets the compression level in range of 0-9.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
636 mtime can be used to set the modification time. The modification time is
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
637 set to the current time by default.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
638 """
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
639 # Wbits=31 automatically includes a gzip header and trailer.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
640 gzip_data = zlib.compress(data, level=compresslevel, wbits=31)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
641 if mtime is None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
642 mtime = time.time()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
643 # Reuse gzip header created by zlib, replace mtime and OS byte for
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
644 # consistency.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
645 header = struct.pack("<4sLBB", gzip_data, int(mtime), gzip_data[8], 255)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
646 return header + gzip_data[10:]
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
647
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
648
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
649 def decompress(data):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
650 """Decompress a gzip compressed string in one shot.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
651 Return the decompressed string.
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
652 """
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
653 decompressed_members = []
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
654 while True:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
655 fp = io.BytesIO(data)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
656 if _read_gzip_header(fp) is None:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
657 return b"".join(decompressed_members)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
658 # Use a zlib raw deflate compressor
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
659 do = zlib.decompressobj(wbits=-zlib.MAX_WBITS)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
660 # Read all the data except the header
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
661 decompressed = do.decompress(data[fp.tell():])
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
662 if not do.eof or len(do.unused_data) < 8:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
663 raise EOFError("Compressed file ended before the end-of-stream "
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
664 "marker was reached")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
665 crc, length = struct.unpack("<II", do.unused_data[:8])
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
666 if crc != zlib.crc32(decompressed):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
667 raise BadGzipFile("CRC check failed")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
668 if length != (len(decompressed) & 0xffffffff):
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
669 raise BadGzipFile("Incorrect length of data produced")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
670 decompressed_members.append(decompressed)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
671 data = do.unused_data[8:].lstrip(b"\x00")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
672
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
673 def main():
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
674 from argparse import ArgumentParser
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
675 parser = ArgumentParser(description=
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
676 "A simple command line interface for the gzip module: act like gzip, "
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
677 "but do not delete the input file.")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
678 group = parser.add_mutually_exclusive_group()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
679 group.add_argument('--fast', action='store_true', help='compress faster')
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
680 group.add_argument('--best', action='store_true', help='compress better')
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
681 group.add_argument("-d", "--decompress", action="store_true",
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
682 help="act like gunzip instead of gzip")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
683
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
684 parser.add_argument("args", nargs="*", default=["-"], metavar='file')
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
685 args = parser.parse_args()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
686
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
687 compresslevel = _COMPRESS_LEVEL_TRADEOFF
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
688 if args.fast:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
689 compresslevel = _COMPRESS_LEVEL_FAST
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
690 elif args.best:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
691 compresslevel = _COMPRESS_LEVEL_BEST
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
692
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
693 for arg in args.args:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
694 if args.decompress:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
695 if arg == "-":
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
696 f = GzipFile(filename="", mode="rb", fileobj=sys.stdin.buffer)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
697 g = sys.stdout.buffer
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
698 else:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
699 if arg[-3:] != ".gz":
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
700 sys.exit(f"filename doesn't end in .gz: {arg!r}")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
701 f = open(arg, "rb")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
702 g = builtins.open(arg[:-3], "wb")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
703 else:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
704 if arg == "-":
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
705 f = sys.stdin.buffer
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
706 g = GzipFile(filename="", mode="wb", fileobj=sys.stdout.buffer,
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
707 compresslevel=compresslevel)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
708 else:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
709 f = builtins.open(arg, "rb")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
710 g = open(arg + ".gz", "wb")
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
711 while True:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
712 chunk = f.read(READ_BUFFER_SIZE)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
713 if not chunk:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
714 break
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
715 g.write(chunk)
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
716 if g is not sys.stdout.buffer:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
717 g.close()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
718 if f is not sys.stdin.buffer:
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
719 f.close()
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
720
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
721 if __name__ == '__main__':
4ead0a390a29 from python3.13 with block boundary tracking added by HST
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
diff changeset
722 main()