38
38
_COMPRESS_LEVEL_BEST = isal_zlib .ISAL_BEST_COMPRESSION
39
39
_BLOCK_SIZE = 64 * 1024
40
40
41
+ BUFFER_SIZE = _compression .BUFFER_SIZE
41
42
42
43
# The open method was copied from the python source with minor adjustments.
43
44
def open (filename , mode = "rb" , compresslevel = _COMPRESS_LEVEL_TRADEOFF ,
@@ -146,9 +147,57 @@ def write(self, data):
146
147
# to do so in pure python.
147
148
class _IGzipReader (_compression .DecompressReader ):
148
149
def __init__ (self , fp ):
149
- super ().__init__ (fp , isal_zlib .decompressobj ,
150
+ super ().__init__ (gzip ._PaddedFile (fp ), isal_zlib .decompressobj ,
151
+ trailing_error = isal_zlib .IsalError ,
150
152
wbits = 16 + isal_zlib .MAX_WBITS )
151
153
154
+ # Created by mixing and matching gzip._GzipReader and
155
+ # _compression.DecompressReader
156
+ def read (self , size = - 1 ):
157
+ if size < 0 :
158
+ return self .readall ()
159
+ # size=0 is special because decompress(max_length=0) is not supported
160
+ if not size :
161
+ return b""
162
+
163
+ # For certain input data, a single
164
+ # call to decompress() may not return
165
+ # any data. In this case, retry until we get some data or reach EOF.
166
+ uncompress = b""
167
+ while True :
168
+ if self ._decompressor .eof :
169
+ buf = (self ._decompressor .unused_data or
170
+ self ._fp .read (BUFFER_SIZE ))
171
+ if not buf :
172
+ break
173
+ # Continue to next stream.
174
+ self ._decompressor = self ._decomp_factory (
175
+ ** self ._decomp_args )
176
+ try :
177
+ uncompress = self ._decompressor .decompress (buf , size )
178
+ except self ._trailing_error :
179
+ # Trailing data isn't a valid compressed stream; ignore it.
180
+ break
181
+ else :
182
+ # Read a chunk of data from the file
183
+ buf = self ._fp .read (BUFFER_SIZE )
184
+ uncompress = self ._decompressor .decompress (buf , size )
185
+ if self ._decompressor .unconsumed_tail != b"" :
186
+ self ._fp .prepend (self ._decompressor .unconsumed_tail )
187
+ elif self ._decompressor .unused_data != b"" :
188
+ # Prepend the already read bytes to the fileobj so they can
189
+ # be seen by _read_eof() and _read_gzip_header()
190
+ self ._fp .prepend (self ._decompressor .unused_data )
191
+
192
+ if uncompress != b"" :
193
+ break
194
+ if buf == b"" :
195
+ raise EOFError ("Compressed file ended before the "
196
+ "end-of-stream marker was reached" )
197
+
198
+ self ._pos += len (uncompress )
199
+ return uncompress
200
+
152
201
153
202
# Plagiarized from gzip.py from python's stdlib.
154
203
def compress (data , compresslevel = _COMPRESS_LEVEL_BEST , * , mtime = None ):
@@ -162,12 +211,19 @@ def compress(data, compresslevel=_COMPRESS_LEVEL_BEST, *, mtime=None):
162
211
return buf .getvalue ()
163
212
164
213
214
+ # Unlike stdlib, do not use the roundabout way of doing this via a file.
215
+ # def decompress(data):
216
+ # """Decompress a gzip compressed string in one shot.
217
+ # Return the decompressed string.
218
+ # """
219
+ # return isal_zlib.decompress(data, wbits=16 + isal_zlib.MAX_WBITS)
220
+
165
221
def decompress (data ):
166
222
"""Decompress a gzip compressed string in one shot.
167
223
Return the decompressed string.
168
224
"""
169
- return isal_zlib . decompress (data , wbits = 16 + isal_zlib . MAX_WBITS )
170
-
225
+ with IGzipFile ( fileobj = io . BytesIO (data )) as f :
226
+ return f . read ()
171
227
172
228
def main ():
173
229
parser = argparse .ArgumentParser ()
0 commit comments