diff --git a/b2/_internal/arg_parser.py b/b2/_internal/arg_parser.py index 89cb046a..52a27245 100644 --- a/b2/_internal/arg_parser.py +++ b/b2/_internal/arg_parser.py @@ -97,13 +97,10 @@ def __init__( :param for_docs: is this parser used for generating docs :param custom_deprecated: is this command deprecated? """ - self._raw_description = None - self._description = None + self._raw_description: str | None = None + self._description: str | None = None self._for_docs = for_docs self.deprecated = custom_deprecated - self._short_description = self._make_short_description( - kwargs.get('usage', ''), kwargs.get('description', '') - ) kwargs.setdefault('formatter_class', B2RawTextHelpFormatter) super().__init__(*args, **kwargs) @@ -139,17 +136,13 @@ def _encode_description(self, value: str): # TODO-REMOVE-BY: When rst2ansi is updated or replaced return textwrap.dedent(value) - def _make_short_description(self, usage: str, raw_description: str) -> str: - if usage: - return usage - - if not raw_description: + def _get_short_description(self) -> str: + if not self._raw_description: return '' - - for line in raw_description.splitlines(): - if line.strip(): - return self._encode_description(line.strip()) - + for line in str(self._raw_description).splitlines(): + cleaned_line = line.strip() + if cleaned_line: + return self._encode_description(cleaned_line) return '' def error(self, message): @@ -217,11 +210,15 @@ def _hide_duplicated_action_choices(self, action): action.choices = original_choices def format_usage(self, use_short_description: bool = False, col_length: int = 16): - if not use_short_description or not self._short_description: + if not use_short_description: + return super().format_usage() + + short_description = self._get_short_description() + if not short_description: return super().format_usage() formatter = self._get_formatter() - formatter.add_text(f'{self.prog:{col_length + 2}} {self._short_description}') + formatter.add_text(f'{self.prog:{col_length + 2}} {short_description}') return formatter.format_help() diff --git a/changelog.d/+arg_parse_help_eager.fixed.md b/changelog.d/+arg_parse_help_eager.fixed.md new file mode 100644 index 00000000..77c23b68 --- /dev/null +++ b/changelog.d/+arg_parse_help_eager.fixed.md @@ -0,0 +1 @@ +Avoid eager calculation of command help during parser construction. \ No newline at end of file diff --git a/changelog.d/+autocomplete-integration-flaky.infrastructure.md b/changelog.d/+autocomplete-integration-flaky.infrastructure.md new file mode 100644 index 00000000..0441bcb5 --- /dev/null +++ b/changelog.d/+autocomplete-integration-flaky.infrastructure.md @@ -0,0 +1 @@ +Fix flaky autocomplete integration test. \ No newline at end of file diff --git a/test/integration/test_autocomplete.py b/test/integration/test_autocomplete.py index a48cfd93..8a9dcddb 100644 --- a/test/integration/test_autocomplete.py +++ b/test/integration/test_autocomplete.py @@ -14,6 +14,7 @@ import pytest from test.helpers import patched_spawn, skip_on_windows +from test.integration.conftest import GENERAL_BUCKET_NAME_PREFIX TIMEOUT = 120 # CI can be slow at times when parallelization is extreme @@ -100,7 +101,11 @@ def test_autocomplete_b2__download_file__b2uri( pytest.skip('Not supported on Docker') shell.send(f'{cli_version} file download \t\t') shell.expect_exact('b2://', timeout=TIMEOUT) - shell.send('b2://\t\t') + + prefix_len = len(GENERAL_BUCKET_NAME_PREFIX) + 4 + prefix = bucket_name[:prefix_len] + shell.send(f'b2://{prefix}\t\t') shell.expect_exact(bucket_name, timeout=TIMEOUT) + shell.send(f'{bucket_name}/\t\t') shell.expect_exact(file_name, timeout=TIMEOUT)