diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 429e533e..a88cb63b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -23,9 +23,11 @@ Added Fixed ^^^^^ - Parameter resolving falling back to assumptions resolver for optional - ``Union`` types. + ``Union`` types (`#498 `__). - Nested parameters failing to parse from command line when value includes - space. + space (`#499 `__). +- ``format_usage()`` not working (`#501 + `__). v4.28.0 (2024-04-17) diff --git a/jsonargparse/_common.py b/jsonargparse/_common.py index 9a5b2b05..36d558e2 100644 --- a/jsonargparse/_common.py +++ b/jsonargparse/_common.py @@ -51,7 +51,7 @@ def __call__(self, class_type: Type[ClassType], *args, **kwargs) -> ClassType: InstantiatorsDictType = Dict[Tuple[type, bool], InstantiatorCallable] -parent_parser: ContextVar["ArgumentParser"] = ContextVar("parent_parser") +parent_parser: ContextVar[Optional["ArgumentParser"]] = ContextVar("parent_parser", default=None) parser_capture: ContextVar[bool] = ContextVar("parser_capture", default=False) defaults_cache: ContextVar[Optional[Namespace]] = ContextVar("defaults_cache", default=None) lenient_check: ContextVar[Union[bool, str]] = ContextVar("lenient_check", default=False) diff --git a/jsonargparse/_formatters.py b/jsonargparse/_formatters.py index 408e0749..6b86aa5e 100644 --- a/jsonargparse/_formatters.py +++ b/jsonargparse/_formatters.py @@ -88,17 +88,19 @@ def _get_help_string(self, action: Action) -> str: def _format_usage(self, *args, **kwargs) -> str: usage = super()._format_usage(*args, **kwargs) parser = parent_parser.get() - for key in parser.required_args: - try: - default = parser.get_default(key) - except KeyError: - default = None - if default is None and f"[--{key} " in usage: - usage = re.sub(f"\\[(--{key} [^\\]]+)]", r"\1", usage, count=1) + if parser: + for key in parser.required_args: + try: + default = parser.get_default(key) + except KeyError: + default = None + if default is None and f"[--{key} " in usage: + usage = re.sub(f"\\[(--{key} [^\\]]+)]", r"\1", usage, count=1) return usage def _format_action_invocation(self, action: Action) -> str: parser = parent_parser.get() + assert parser is not None if isinstance(action, _ActionSubCommands): value = "Available subcommands:" if parser.default_env: @@ -263,6 +265,7 @@ def get_env_var( parser = parent_parser.get() else: parser = parser_or_formatter + assert parser is not None env_var = "" if isinstance(parser.env_prefix, str): env_var = parser.env_prefix.replace("-", "_") + "_" diff --git a/jsonargparse/_loaders_dumpers.py b/jsonargparse/_loaders_dumpers.py index c22e5509..8d7ff057 100644 --- a/jsonargparse/_loaders_dumpers.py +++ b/jsonargparse/_loaders_dumpers.py @@ -96,7 +96,9 @@ def jsonnet_load(stream, path="", ext_vars=None): def get_load_value_mode() -> str: mode = load_value_mode.get() if mode is None: - mode = parent_parser.get().parser_mode + parser = parent_parser.get() + assert parser is not None + mode = parser.parser_mode return mode diff --git a/jsonargparse_tests/test_formatters.py b/jsonargparse_tests/test_formatters.py index 26960d82..c6f175e6 100644 --- a/jsonargparse_tests/test_formatters.py +++ b/jsonargparse_tests/test_formatters.py @@ -1,7 +1,9 @@ from __future__ import annotations +import os from pathlib import Path from typing import Tuple +from unittest.mock import patch import pytest @@ -129,3 +131,9 @@ def test_help_default_config_files_with_required(tmp_path, parser): help_str = get_parser_help(parser) assert "req description" in help_str assert "from yaml" in help_str + + +def test_format_usage(parser): + parser.add_argument("--v1") + with patch.dict(os.environ, {"COLUMNS": "200"}): + assert parser.format_usage() == "usage: app [-h] [--v1 V1]\n"