# HG changeset patch
# User Raphaël Gomès <rgomes@octobus.net>
# Date 1678888394 -3600
#      Wed Mar 15 14:53:14 2023 +0100
# Node ID d82a0b5b58a88623d796a92236c4cae61433628c
# Parent  8e4c05833113d9f6fe4ec45d976f8edfc54a827c
bin: rewrite `env-desc` with `click`

This is much simpler and more powerful than rolling it by hand.

diff --git a/python-libs/poulpe/bin/env-desc b/python-libs/poulpe/bin/env-desc
--- a/python-libs/poulpe/bin/env-desc
+++ b/python-libs/poulpe/bin/env-desc
@@ -1,47 +1,84 @@
 #!/usr/bin/env python3
-#
-# Small utility to manipulate environment description
-import os
+# XXX rename to something other than `env-desc` and try to define
+#     where to define and where to expose those primitives.
 import sys
 
-ACTION_SHOW = 'show'
-ACTION_SET = 'set'
-ACTION_GET = 'get'
-ACTION_DEL = 'del'
-ALL_ACTIONS = {
-    ACTION_SHOW,
-    ACTION_SET,
-    ACTION_GET,
-    ACTION_DEL,
-}
-
+import click
 import poulpe
 
 err = poulpe.err
 
 
+@click.group(no_args_is_help=True)
+def env_desc():
+    """Low-level utility to manipulate Poulpe description trees.
+
+    Poulpe description trees are common to data-envs, bin-envs and benchmarks."""
+
+
+@env_desc.command(no_args_is_help=True)
+@click.argument("path")
 def show(path):
+    """Display the contents of the description tree.
+
+    \b
+    ARGS:
+        <PATH> is the path to the binary environment directory"""
     data = poulpe.get_data(path)
     if data is None:
         err(f'missing file: "{path}"')
-        return 3
+        sys.exit(3)
     poulpe.show(data)
 
 
+@env_desc.command("get", no_args_is_help=True)
+@click.argument("path")
+@click.argument("key")
 def get_value(path, key):
+    """Display the value of a key from the description tree.
+
+    \b
+    ARGS:
+        <PATH> is the path of the environment
+        <KEY> is the path to the variable
+    """
     data = poulpe.get_data(path)
     if data is None:
         err(f'missing file: "{path}"')
-        return 3
+        sys.exit(3)
     value = poulpe.get_one_value(data, key)
     if value is None:
-        return 1
-    else:
-        print(value)
-        return 0
+        sys.exit(1)
+    print(value)
 
 
-def set_value(path, key, value):
+@env_desc.command("set", no_args_is_help=True)
+@click.argument("path")
+@click.argument("key")
+@click.argument("value")
+@click.option(
+    "--type",
+    "typ",
+    type=click.Choice(["int", "bool", "string"]),
+    default="string",
+    help="Which type the value should be interpreted as",
+)
+def set_value(path, key, value, typ):
+    """Set a key of the description tree to a new value.
+
+    \b
+    ARGS:
+        <PATH> is the path of the environment
+        <KEY> is the path to the variable
+        <VALUE> is the value to be set
+    """
+    if typ == "int":
+        value = int(value)
+    elif typ == "bool":
+        value = bool(value)
+    else:
+        assert typ == "string", typ
+
     data = poulpe.get_data(path)
     if data is None:
         err(f'creating new file: "{path}"')
@@ -50,10 +87,18 @@
     value = poulpe.set_one_value(data, key, value)
 
     poulpe.write_data(path, data)
-    return 0
 
 
+@env_desc.command("del", no_args_is_help=True)
+@click.argument("path")
+@click.argument("key")
 def del_value(path, key):
+    """Remove a key from the description tree.
+    \b
+    ARGS:
+        <PATH> is the path of the environment
+        <KEY> is the path to the variable to delete
+    """
     data = poulpe.get_data(path)
     if data is None:
         err(f'creating new file: "{path}"')
@@ -62,55 +107,7 @@
     poulpe.del_one_value(data, key)
 
     poulpe.write_data(path, data)
-    return 0
 
 
 if __name__ == "__main__":
-    if len(sys.argv) < 3:
-        t = os.path.split(sys.argv[0])[-1]
-        err(f"{t}: small utility to manipulate environment description")
-        err("")
-        err(f"  $ {t} show PATH - Display description content")
-        err(f"  $ {t} get PATH key - Display key value")
-        err(f"  $ {t} set PATH key value - Set key value")
-        err(f"  $ {t} del PATH key - Remove key")
-        sys.exit(2)
-    action = sys.argv[1]
-    path = sys.argv[2]
-    key = value = None
-
-    if action not in ALL_ACTIONS:
-        err(f"unknown action: {action}")
-        err("(use one of: %s)" % ', '.join(sorted(ALL_ACTIONS)))
-        sys.exit(2)
-
-    if action != ACTION_SHOW:
-        if len(sys.argv) < 4:
-            err("missing key")
-            sys.exit(2)
-        key = sys.argv[3]
-        if action == ACTION_SET:
-            if path == '--bool':
-                sys.argv.pop(2)
-                path = sys.argv[2]
-                key = sys.argv[3]
-                sys.argv[4] = bool(sys.argv[4])
-            elif path == '--int':
-                sys.argv.pop(2)
-                path = sys.argv[2]
-                key = sys.argv[3]
-                sys.argv[4] = int(sys.argv[4])
-            if len(sys.argv) < 5:
-                err("missing value")
-                sys.exit(2)
-            value = sys.argv[4]
-
-    if action == ACTION_SHOW:
-        ret = show(path)
-    elif action == ACTION_GET:
-        ret = get_value(path, key)
-    elif action == ACTION_SET:
-        ret = set_value(path, key, value)
-    elif action == ACTION_DEL:
-        ret = del_value(path, key)
-sys.exit(ret)
+    env_desc()
diff --git a/suites/hg/setup-data/setup-01-graph.sh b/suites/hg/setup-data/setup-01-graph.sh
--- a/suites/hg/setup-data/setup-01-graph.sh
+++ b/suites/hg/setup-data/setup-01-graph.sh
@@ -19,4 +19,4 @@
 token="special-token-sdljlajslgjasljdlkasjlgjsjga-match-me"
 
 nb_revs=`hg log --template "${token}\n" -R $repo | grep $token | wc -l`
-poulpe env-desc set --int "$desc" data-env-vars.mercurial.repo.graph.visible-revision-count $nb_revs
+poulpe env-desc set --type int "$desc" data-env-vars.mercurial.repo.graph.visible-revision-count $nb_revs
diff --git a/tests/test-env-desc.t b/tests/test-env-desc.t
--- a/tests/test-env-desc.t
+++ b/tests/test-env-desc.t
@@ -7,54 +7,73 @@
 no args
 
   $ poulpe env-desc
-  env-desc: small utility to manipulate environment description
+  Usage: env-desc [OPTIONS] COMMAND [ARGS]...
+  
+    Low-level utility to manipulate Poulpe description trees.
+  
+    Poulpe description trees are common to data-envs, bin-envs and benchmarks.
   
-    $ env-desc show PATH - Display description content
-    $ env-desc get PATH key - Display key value
-    $ env-desc set PATH key value - Set key value
-    $ env-desc del PATH key - Remove key
-  [2]
+  Options:
+    --help  Show this message and exit.
+  
+  Commands:
+    del   Remove a key from the description tree.
+    get   Display the value of a key from the description tree.
+    set   Set a key of the description tree to a new value.
+    show  Display the contents of the description tree.
 
 too few args
 
   $ poulpe env-desc foo
-  env-desc: small utility to manipulate environment description
+  Usage: env-desc [OPTIONS] COMMAND [ARGS]...
+  Try 'env-desc --help' for help.
   
-    $ env-desc show PATH - Display description content
-    $ env-desc get PATH key - Display key value
-    $ env-desc set PATH key value - Set key value
-    $ env-desc del PATH key - Remove key
+  Error: No such command 'foo'.
   [2]
 
 bad action
 
   $ poulpe env-desc foo bar
-  unknown action: foo
-  (use one of: del, get, set, show)
+  Usage: env-desc [OPTIONS] COMMAND [ARGS]...
+  Try 'env-desc --help' for help.
+  
+  Error: No such command 'foo'.
   [2]
 
 missing GET key
 
   $ poulpe env-desc get no-file
-  missing key
+  Usage: env-desc get [OPTIONS] PATH KEY
+  Try 'env-desc get --help' for help.
+  
+  Error: Missing argument 'KEY'.
   [2]
 
 missing SET key
 
   $ poulpe env-desc set no-file
-  missing key
+  Usage: env-desc set [OPTIONS] PATH KEY VALUE
+  Try 'env-desc set --help' for help.
+  
+  Error: Missing argument 'KEY'.
   [2]
 
 missing SET value
 
   $ poulpe env-desc set no-file key
-  missing value
+  Usage: env-desc set [OPTIONS] PATH KEY VALUE
+  Try 'env-desc set --help' for help.
+  
+  Error: Missing argument 'VALUE'.
   [2]
 
 missing DEL key
 
   $ poulpe env-desc del no-file
-  missing key
+  Usage: env-desc del [OPTIONS] PATH KEY
+  Try 'env-desc del --help' for help.
+  
+  Error: Missing argument 'KEY'.
   [2]
 
 Missing file when reading
diff --git a/tests/test-run-variants.t b/tests/test-run-variants.t
--- a/tests/test-run-variants.t
+++ b/tests/test-run-variants.t
@@ -75,7 +75,7 @@
   $ poulpe env-desc set black-tiny-bad.pbd simple-command.accept-failure "1"
   $ poulpe env-desc set black-tiny-bad.pbd simple-command.variables.file DATA-VARS:black.check.tiny.bad
   $ poulpe env-desc set black-tiny-bad.pbd simple-command.cwd .
-  $ poulpe env-desc set --bool black-tiny-bad.pbd simple-command.variants.dimensions.string-normalization.yes.default 1
+  $ poulpe env-desc set --type bool black-tiny-bad.pbd simple-command.variants.dimensions.string-normalization.yes.default 1
   $ poulpe env-desc set black-tiny-bad.pbd simple-command.variants.dimensions.string-normalization.no.extend-command " --skip-string-normalization"
 
   $ poulpe env-desc show black-tiny-bad.pbd