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

Julien Palard webhook-mailer at python.org
Sat Nov 3 11:24:27 EDT 2018


https://github.com/python/cpython/commit/3e28eed9ec2249bb11ad0db4629271b7ce9b7918
commit: 3e28eed9ec2249bb11ad0db4629271b7ce9b7918
branch: master
author: Stéphane Wirtel <stephane at wirtel.be>
committer: Julien Palard <julien at palard.fr>
date: 2018-11-03T16:24:23+01:00
summary:

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

files:
A Misc/NEWS.d/next/Library/2018-10-13-07-46-50.bpo-34969.Mfnhjb.rst
M Doc/library/gzip.rst
M Lib/gzip.py
M Lib/test/test_gzip.py

diff --git a/Doc/library/gzip.rst b/Doc/library/gzip.rst
index b52dd1a11aa9..a93f37743854 100644
--- a/Doc/library/gzip.rst
+++ b/Doc/library/gzip.rst
@@ -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
 
diff --git a/Lib/gzip.py b/Lib/gzip.py
index a34d01ae36e1..151ff1405b16 100644
--- a/Lib/gzip.py
+++ b/Lib/gzip.py
@@ -17,7 +17,12 @@
 
 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 @@ def _rewind(self):
         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")
diff --git a/Lib/test/test_gzip.py b/Lib/test/test_gzip.py
index b072ce4682c0..1e8b41f07b3e 100644
--- a/Lib/test/test_gzip.py
+++ b/Lib/test/test_gzip.py
@@ -12,7 +12,7 @@
 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 @@ def test_compress_infile_outfile(self):
         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)
diff --git a/Misc/NEWS.d/next/Library/2018-10-13-07-46-50.bpo-34969.Mfnhjb.rst b/Misc/NEWS.d/next/Library/2018-10-13-07-46-50.bpo-34969.Mfnhjb.rst
new file mode 100644
index 000000000000..e3b713261406
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2018-10-13-07-46-50.bpo-34969.Mfnhjb.rst
@@ -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).



More information about the Python-checkins mailing list