bpo-34969: Add --fast, --best on the gzip CLI (GH-9833)

This commit is contained in:
Stéphane Wirtel 2018-11-03 16:24:23 +01:00 committed by Julien Palard
parent fe62d877e3
commit 3e28eed9ec
4 changed files with 65 additions and 16 deletions

View File

@ -222,25 +222,26 @@ Once executed the :mod:`gzip` module keeps the input file(s).
.. versionchanged:: 3.8
Add a new command line interface with a usage.
By default, when you will execute the CLI, the default compression level is 6.
Command line options
^^^^^^^^^^^^^^^^^^^^
.. cmdoption:: file
.. code-block:: shell-session
$ python -m gzip file
If *file* is not specified, read from :attr:`sys.stdin`.
.. cmdoption:: --fast
Indicates the fastest compression method (less compression).
.. cmdoption:: --best
Indicates the slowest compression method (best compression).
.. cmdoption:: -d, --decompress
Decompress the given file
.. code-block:: shell-session
$ python -m gzip -d file.gz
Decompress the given file.
.. cmdoption:: -h, --help

View File

@ -17,7 +17,12 @@ FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16
READ, WRITE = 1, 2
def open(filename, mode="rb", compresslevel=9,
_COMPRESS_LEVEL_FAST = 1
_COMPRESS_LEVEL_TRADEOFF = 6
_COMPRESS_LEVEL_BEST = 9
def open(filename, mode="rb", compresslevel=_COMPRESS_LEVEL_BEST,
encoding=None, errors=None, newline=None):
"""Open a gzip-compressed file in binary or text mode.
@ -121,7 +126,7 @@ class GzipFile(_compression.BaseStream):
myfileobj = None
def __init__(self, filename=None, mode=None,
compresslevel=9, fileobj=None, mtime=None):
compresslevel=_COMPRESS_LEVEL_BEST, fileobj=None, mtime=None):
"""Constructor for the GzipFile class.
At least one of fileobj and filename must be given a
@ -515,7 +520,7 @@ class _GzipReader(_compression.DecompressReader):
super()._rewind()
self._new_member = True
def compress(data, compresslevel=9):
def compress(data, compresslevel=_COMPRESS_LEVEL_BEST):
"""Compress data in one shot and return the compressed string.
Optional argument is the compression level, in range of 0-9.
"""
@ -537,10 +542,21 @@ def main():
parser = ArgumentParser(description=
"A simple command line interface for the gzip module: act like gzip, "
"but do not delete the input file.")
parser.add_argument("-d", "--decompress", action="store_true",
group = parser.add_mutually_exclusive_group()
group.add_argument('--fast', action='store_true', help='compress faster')
group.add_argument('--best', action='store_true', help='compress better')
group.add_argument("-d", "--decompress", action="store_true",
help="act like gunzip instead of gzip")
parser.add_argument("args", nargs="*", default=["-"], metavar='file')
args = parser.parse_args()
compresslevel = _COMPRESS_LEVEL_TRADEOFF
if args.fast:
compresslevel = _COMPRESS_LEVEL_FAST
elif args.best:
compresslevel = _COMPRESS_LEVEL_BEST
for arg in args.args:
if args.decompress:
if arg == "-":
@ -555,7 +571,8 @@ def main():
else:
if arg == "-":
f = sys.stdin.buffer
g = GzipFile(filename="", mode="wb", fileobj=sys.stdout.buffer)
g = GzipFile(filename="", mode="wb", fileobj=sys.stdout.buffer,
compresslevel=compresslevel)
else:
f = builtins.open(arg, "rb")
g = open(arg + ".gz", "wb")

View File

@ -12,7 +12,7 @@ import unittest
from subprocess import PIPE, Popen
from test import support
from test.support import _4G, bigmemtest
from test.support.script_helper import assert_python_ok
from test.support.script_helper import assert_python_ok, assert_python_failure
gzip = support.import_module('gzip')
@ -746,10 +746,38 @@ class TestCommandLine(unittest.TestCase):
rc, out, err = assert_python_ok('-m', 'gzip', local_testgzip)
self.assertTrue(os.path.exists(gzipname))
self.assertEqual(rc, 0)
self.assertEqual(out, b'')
self.assertEqual(err, b'')
@create_and_remove_directory(TEMPDIR)
def test_compress_infile_outfile(self):
for compress_level in ('--fast', '--best'):
with self.subTest(compress_level=compress_level):
local_testgzip = os.path.join(TEMPDIR, 'testgzip')
gzipname = local_testgzip + '.gz'
self.assertFalse(os.path.exists(gzipname))
with open(local_testgzip, 'wb') as fp:
fp.write(self.data)
rc, out, err = assert_python_ok('-m', 'gzip', compress_level, local_testgzip)
self.assertTrue(os.path.exists(gzipname))
self.assertEqual(out, b'')
self.assertEqual(err, b'')
os.remove(gzipname)
self.assertFalse(os.path.exists(gzipname))
def test_compress_fast_best_are_exclusive(self):
rc, out, err = assert_python_failure('-m', 'gzip', '--fast', '--best')
self.assertIn(b"error: argument --best: not allowed with argument --fast", err)
self.assertEqual(out, b'')
def test_decompress_cannot_have_flags_compression(self):
rc, out, err = assert_python_failure('-m', 'gzip', '--fast', '-d')
self.assertIn(b'error: argument -d/--decompress: not allowed with argument --fast', err)
self.assertEqual(out, b'')
def test_main(verbose=None):
support.run_unittest(TestGzip, TestOpen, TestCommandLine)

View File

@ -0,0 +1,3 @@
gzip: Add --fast, --best on the gzip CLI, these parameters will be used for the
fast compression method (quick) or the best method compress (slower, but smaller
file). Also, change the default compression level to 6 (tradeoff).