From 61ff8bb74c9987ed198a1bb59ebab5610c57d74d Mon Sep 17 00:00:00 2001 From: Mauricio Villegas <5780272+mauvilsa@users.noreply.github.com> Date: Fri, 14 Jul 2023 04:26:07 +0200 Subject: [PATCH] Subcommands main parser help changes: - Set notation of subcommands choices now only included in usage. - In subcommands section, now each subcommand is always shown separately, including the name, and if available aliases and help. - When default_env=True include subcommand environment variable name. --- CHANGELOG.rst | 10 +++++++++- jsonargparse/_actions.py | 5 +++-- jsonargparse/_formatters.py | 7 ++++++- jsonargparse_tests/test_subcommands.py | 15 ++++++++++++++- 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 07a48a1e..cc24e9cf 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -12,7 +12,7 @@ The semantic versioning only considers the public API as described in paths are considered internals and can change in minor and patch releases. -v4.22.2 (2023-07-??) +v4.23.0 (2023-07-??) -------------------- Fixed @@ -25,6 +25,14 @@ Fixed installed (`lightning#18125 comment `__). +Changed +^^^^^^^ +- Subcommands main parser help changes: + - Set notation of subcommands choices now only included in usage. + - In subcommands section, now each subcommand is always shown separately, + including the name, and if available aliases and help. + - When ``default_env=True`` include subcommand environment variable name. + v4.22.1 (2023-07-07) -------------------- diff --git a/jsonargparse/_actions.py b/jsonargparse/_actions.py index ebeff618..57a62690 100644 --- a/jsonargparse/_actions.py +++ b/jsonargparse/_actions.py @@ -595,10 +595,11 @@ def add_subcommand(self, name, parser, **kwargs): # create a pseudo-action to hold the choice help aliases = kwargs.pop("aliases", ()) + help_arg = None if "help" in kwargs: help_arg = kwargs.pop("help") - choice_action = self._ChoicesPseudoAction(name, aliases, help_arg) - self._choices_actions.append(choice_action) + choice_action = self._ChoicesPseudoAction(name, aliases, help_arg) + self._choices_actions.append(choice_action) # add the parser to the name-parser map self._name_parser_map[name] = parser diff --git a/jsonargparse/_formatters.py b/jsonargparse/_formatters.py index 87dc41a9..9ddc566b 100644 --- a/jsonargparse/_formatters.py +++ b/jsonargparse/_formatters.py @@ -99,7 +99,12 @@ def _format_usage(self, *args, **kwargs) -> str: def _format_action_invocation(self, action: Action) -> str: parser = parent_parser.get() - if not (parser.default_env and action.option_strings): + if isinstance(action, _ActionSubCommands): + value = "Available subcommands:" + if parser.default_env: + value = f"ENV: {get_env_var(self, action)}\n\n {value}" + return value + if action.option_strings == [] or not parser.default_env: return super()._format_action_invocation(action) extr = "" if not isinstance(action, (_ActionHelpClassPath, _ActionPrintConfig, _HelpAction)): diff --git a/jsonargparse_tests/test_subcommands.py b/jsonargparse_tests/test_subcommands.py index 3e4421cf..a5d24610 100644 --- a/jsonargparse_tests/test_subcommands.py +++ b/jsonargparse_tests/test_subcommands.py @@ -15,7 +15,7 @@ Namespace, strip_meta, ) -from jsonargparse_tests.conftest import get_parse_args_stdout +from jsonargparse_tests.conftest import get_parse_args_stdout, get_parser_help @pytest.fixture @@ -81,6 +81,13 @@ def test_subcommands_parse_args_basics(subcommands_parser): assert "a" not in cfg +def test_main_subcommands_help(subcommands_parser): + help_str = get_parser_help(subcommands_parser) + assert help_str.count("{a,b,B}") == 1 + assert "Available subcommands:" in help_str + assert "b (B)" in help_str + + def test_subcommands_parse_args_alias(subcommands_parser): cfg = subcommands_parser.parse_args(["B"]) assert cfg["subcommand"] == "B" @@ -163,6 +170,12 @@ def test_subcommands_parse_env(subcommands_parser): assert cfg["a"] == {"ap1": "ap1_env", "ao1": "ao1_env"} +def test_subcommands_help_default_env_true(subcommands_parser): + subcommands_parser.default_env = True + help_str = get_parser_help(subcommands_parser) + assert "ENV: APP_SUBCOMMAND" in help_str + + def test_subcommand_required_false(parser, subparser): subcommands = parser.add_subcommands(required=False) subcommands.add_subcommand("foo", subparser)