bpo-39389: gzip: fix compression level metadata (GH-18077)

As described in RFC 1952, section 2.3.1, the XFL (eXtra FLags) byte of a
gzip member header should indicate whether the DEFLATE algorithm was
tuned for speed or compression ratio. Prior to this patch, archives
emitted by the `gzip` module always indicated maximum compression.
This commit is contained in:
William Chargin 2020-01-21 03:25:24 -08:00 committed by Serhiy Storchaka
parent 85ead4fc62
commit eab3b3f1c6
3 changed files with 31 additions and 3 deletions

View file

@ -209,7 +209,7 @@ class GzipFile(_compression.BaseStream):
self.fileobj = fileobj
if self.mode == WRITE:
self._write_gzip_header()
self._write_gzip_header(compresslevel)
@property
def filename(self):
@ -236,7 +236,7 @@ class GzipFile(_compression.BaseStream):
self.bufsize = 0
self.offset = 0 # Current file offset for seek(), tell(), etc
def _write_gzip_header(self):
def _write_gzip_header(self, compresslevel):
self.fileobj.write(b'\037\213') # magic header
self.fileobj.write(b'\010') # compression method
try:
@ -257,7 +257,13 @@ class GzipFile(_compression.BaseStream):
if mtime is None:
mtime = time.time()
write32u(self.fileobj, int(mtime))
self.fileobj.write(b'\002')
if compresslevel == _COMPRESS_LEVEL_BEST:
xfl = b'\002'
elif compresslevel == _COMPRESS_LEVEL_FAST:
xfl = b'\004'
else:
xfl = b'\000'
self.fileobj.write(xfl)
self.fileobj.write(b'\377')
if fname:
self.fileobj.write(fname + b'\000')