Commit 3e28eed9 authored by Stéphane Wirtel's avatar Stéphane Wirtel Committed by Julien Palard

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

parent fe62d877
......@@ -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
If *file* is not specified, read from :attr:`sys.stdin`.
$ python -m gzip file
.. cmdoption:: --fast
If *file* is not specified, read from :attr:`sys.stdin`.
Indicates the fastest compression method (less compression).
.. cmdoption:: -d, --decompress
.. cmdoption:: --best
Decompress the given file
Indicates the slowest compression method (best compression).
.. code-block:: shell-session
.. cmdoption:: -d, --decompress
$ python -m gzip -d file.gz
Decompress the given file.
.. cmdoption:: -h, --help
......
......@@ -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")
......
......@@ -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)
......
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).
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment