diff --git a/CHANGELOG.rst b/CHANGELOG.rst index df6a09f7..e9e2b306 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -11,6 +11,14 @@ The semantic versioning only considers the public API as described in :ref:`api-ref`. Components not mentioned in :ref:`api-ref` or different import paths are considered internals and can change in minor and patch releases. +v4.42.1 (unreleased) +-------------------- + +Fixed +^^^^^ +- Prevent extra environment variables in helptext when default_env=True, for + version actions and subcommands(`#787 + `__). v4.42.0 (2025-10-14) -------------------- diff --git a/jsonargparse/_formatters.py b/jsonargparse/_formatters.py index bf117ae9..343628ac 100644 --- a/jsonargparse/_formatters.py +++ b/jsonargparse/_formatters.py @@ -8,6 +8,8 @@ Action, HelpFormatter, _HelpAction, + _SubParsersAction, + _VersionAction, ) from io import StringIO from string import Template @@ -249,8 +251,11 @@ def _format_action_invocation(self, action: Action) -> str: return value if not parser.default_env: return super()._format_action_invocation(action) + # Subcommand choices (individual subcommands in the list) don't get ARG: prefix or ENV: line + if isinstance(action, _SubParsersAction._ChoicesPseudoAction): + return super()._format_action_invocation(action) extr = "" - if not isinstance(action, (_ActionHelpClassPath, _ActionPrintConfig, ShtabAction, _HelpAction)): + if not isinstance(action, (_ActionHelpClassPath, _ActionPrintConfig, ShtabAction, _HelpAction, _VersionAction)): extr += "\n ENV: " + get_env_var(self, action) return "ARG: " + super()._format_action_invocation(action) + extr diff --git a/jsonargparse_tests/test_formatters.py b/jsonargparse_tests/test_formatters.py index 458a2587..0effd0f0 100644 --- a/jsonargparse_tests/test_formatters.py +++ b/jsonargparse_tests/test_formatters.py @@ -22,6 +22,14 @@ def test_help_basics(parser): assert "APP_HELP" not in help_str +def test_help_action_version(parser): + parser.add_argument("--version", action="version", version="1.0.0") + help_str = get_parser_help(parser) + assert "ARG: --version" in help_str + assert "APP_VERSION" not in help_str + assert "show program's version number and exit" in help_str + + def test_help_action_config_file(parser): parser.add_argument("-c", "--cfg", help="Config in yaml/json.", action="config") help_str = get_parser_help(parser) @@ -140,6 +148,25 @@ def test_help_default_config_files_with_required(tmp_path, parser): assert "from config" in help_str +def test_help_subcommands_with_default_env(parser): + subcommands = parser.add_subcommands() + subparser1 = ArgumentParser() + subparser2 = ArgumentParser() + subcommands.add_subcommand("greet", subparser1, help="Greet someone") + subcommands.add_subcommand("farewell", subparser2, help="Say goodbye") + help_str = get_parser_help(parser) + # Individual subcommands should NOT have ARG: prefix or ENV: lines + assert "ARG: greet" not in help_str + assert "ARG: farewell" not in help_str + assert "ENV: APP_GREET" not in help_str + assert "ENV: APP_FAREWELL" not in help_str + # But the subcommand names and help should still be present + assert "greet" in help_str + assert "Greet someone" in help_str + assert "farewell" in help_str + assert "Say goodbye" in help_str + + def test_format_usage(parser): parser.add_argument("--v1") with patch.dict(os.environ, {"COLUMNS": "200"}):