changeset 142:71747e45b52c

Prepare for using subcommands in "treesum.py". This is to prepare for verification and filtering/parsing digest files.
author Franz Glasner <fzglas.hg@dom66.de>
date Fri, 03 Jan 2025 15:49:57 +0100
parents fdc456832ba6
children 492975912cad
files cutils/treesum.py
diffstat 1 files changed, 100 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/cutils/treesum.py	Fri Jan 03 01:33:01 2025 +0100
+++ b/cutils/treesum.py	Fri Jan 03 15:49:57 2025 +0100
@@ -29,60 +29,95 @@
 
 
 def main(argv=None):
-    aparser = argparse.ArgumentParser(
-        description="Generate checksums for directory trees",
+
+    def _populate_generate_arguments(gp):
+        """Use to populate command aliases.
+
+        This is because :class:`argparse.ArgumentParser` does not
+        support them for all supported Python versions.
+
+        """
+        gp.add_argument(
+            "--algorithm", "-a", action="store", type=util.argv2algo,
+            help="1 (aka sha1), 224, 256, 384, 512, "
+                 "3 (alias for sha3-512), 3-224, 3-256, 3-384, 3-512, "
+                 "blake2b, blake2b-256 (default), blake2s, "
+                 "blake2 (alias for blake2b), "
+                 "blake2-256 (alias for blake2b-256), "
+                 "md5")
+        gp.add_argument(
+            "--append-output", action="store_true", dest="append_output",
+            help="Append to the output file instead of overwriting it.")
+        gp.add_argument(
+            "--base64", action="store_true",
+            help="Output checksums in base64 notation, not hexadecimal "
+                 "(OpenBSD).")
+        gp.add_argument(
+            "--comment", action="append", default=[],
+            help="Put given comment COMMENT into the output as \"COMMENT\". "
+                 "Can be given more than once.")
+        gp.add_argument(
+            "--follow-directory-symlinks", "-l", action="store_true",
+            dest="follow_directory_symlinks",
+            help="Follow symbolic links to directories when walking a "
+                 "directory tree. Note that this is different from using "
+                 "\"--logical\" or \"--physical\" for arguments given "
+                 "directly on the command line")
+        gp.add_argument(
+            "--logical", "-L", dest="logical", action="store_true",
+            default=None,
+            help="Follow symbolic links given on command line arguments."
+                 " Note that this is a different setting as to follow symbolic"
+                 " links to directories when traversing a directory tree.")
+        gp.add_argument(
+            "--mmap", action="store_true", dest="mmap", default=None,
+            help="Use mmap if available. Default is to determine "
+                 "automatically from the filesize.")
+        gp.add_argument(
+            "--no-mmap", action="store_false", dest="mmap", default=None,
+            help="Dont use mmap.")
+        gp.add_argument(
+            "--output", "-o", action="store", metavar="OUTPUT",
+            help="Put the checksum into given file. "
+                 "If not given or if it is given as `-' then stdout is used.")
+        gp.add_argument(
+            "--physical", "-P", dest="logical", action="store_false",
+            default=None,
+            help="Do not follow symbolic links given on comment line "
+                 "arguments. This is the default.")
+        gp.add_argument(
+            "directories", nargs="*", metavar="DIRECTORY")
+
+    parser = argparse.ArgumentParser(
+        description="Generate and verify checksums for directory trees.",
         fromfile_prefix_chars='@')
-    aparser.add_argument(
-        "--algorithm", "-a", action="store", type=util.argv2algo,
-        help="1 (aka sha1), 224, 256, 384, 512, "
-             "3 (alias for sha3-512), 3-224, 3-256, 3-384, 3-512, "
-             "blake2b, blake2b-256 (default), blake2s, "
-             "blake2 (alias for blake2b), blake2-256 (alias for blake2b-256), "
-             "md5")
-    aparser.add_argument(
-        "--append-output", action="store_true", dest="append_output",
-        help="Append to the output file instead of overwriting it.")
-    aparser.add_argument(
-        "--base64", action="store_true",
-        help="Output checksums in base64 notation, not hexadecimal (OpenBSD).")
-    aparser.add_argument(
-        "--comment", action="append", default=[],
-        help="Put given comment COMMENT into the output as \"COMMENT\"."
-             " Can be given more than once.")
-    aparser.add_argument(
-        "--follow-directory-symlinks", "-l", action="store_true",
-        dest="follow_directory_symlinks",
-        help="Follow symbolic links to directories when walking a directory"
-             " tree. Note that this is different from using \"--logical\" or"
-             " \"--physical\" for arguments given directly on the command"
-             " line")
-    aparser.add_argument(
-        "--logical", "-L", dest="logical", action="store_true", default=None,
-        help="Follow symbolic links given on command line arguments."
-             " Note that this is a different setting as to follow symbolic"
-             " links to directories when traversing a directory tree.")
-    aparser.add_argument(
-        "--mmap", action="store_true", dest="mmap", default=None,
-        help="Use mmap if available. Default is to determine automatically "
-             "from the filesize.")
-    aparser.add_argument(
-        "--no-mmap", action="store_false", dest="mmap", default=None,
-        help="Dont use mmap.")
-    aparser.add_argument(
-        "--output", "-o", action="store", metavar="OUTPUT",
-        help="Put the checksum into given file. If not given of if it is given"
-             " as `-' then stdout is used.")
-    aparser.add_argument(
-        "--physical", "-P", dest="logical", action="store_false", default=None,
-        help="Do not follow symbolic links given on comment line arguments."
-             " This is the default.")
-    aparser.add_argument(
-        "--version", "-v", action="version",
+
+    # Global options for all sub-commands
+    parser.add_argument(
+        "-v", "--version", action="version",
         version="%s (rv:%s)" % (__version__, __revision__))
-    aparser.add_argument(
-        "directories", nargs="*", metavar="DIRECTORY")
+
+    subparsers = parser.add_subparsers(
+        dest="subcommand",
+        description="This tool uses subcommands. "
+                    "To see detailed help for a specific subcommand use "
+                    "the -h/--help option after the subcommand name. "
+                    "A short list of valid commands are listed below:")
 
-    opts = aparser.parse_args(args=argv)
+    genparser = subparsers.add_parser(
+        "generate",
+        help="Generate checksums for directory trees",
+        description="Generate checksums for directory trees")
+    _populate_generate_arguments(genparser)
+    # And an alias for "generate"
+    genparser2 = subparsers.add_parser(
+        "gen",
+        help="Alias for \"generate\"",
+        description="Generate checksums for directory trees. "
+                    "This is an alias to \"generate\".")
+    _populate_generate_arguments(genparser2)
+
+    opts = parser.parse_args(args=argv)
 
     if not opts.algorithm:
         opts.algorithm = util.argv2algo("blake2b-256")
@@ -90,15 +125,15 @@
     return treesum(opts)
 
 
-def gen_opts(directories=[],
-             algorithm="BLAKE2b-256",
-             append_output=False,
-             base64=False,
-             comment=[],
-             follow_directory_symlinks=False,
-             logical=None,
-             mmap=None,
-             output=None):
+def gen_generate_opts(directories=[],
+                      algorithm="BLAKE2b-256",
+                      append_output=False,
+                      base64=False,
+                      comment=[],
+                      follow_directory_symlinks=False,
+                      logical=None,
+                      mmap=None,
+                      output=None):
     opts = argparse.Namespace(
         directories=directories,
         algorithm=(util.algotag2algotype(algorithm),
@@ -115,7 +150,11 @@
 
 def treesum(opts):
     # XXX TBD: opts.check and opts.checklist (as in shasum.py)
-    return generate_treesum(opts)
+    if opts.subcommand in ("generate", "gen"):
+        return generate_treesum(opts)
+    else:
+        raise RuntimeError(
+            "command `{}' not yet handled".format(opts.subcommand))
 
 
 def generate_treesum(opts):