From 82f377c547e1867d073f02bb8f476214d07e245b Mon Sep 17 00:00:00 2001 From: Kevin Deldycke Date: Sat, 23 May 2026 15:52:07 +0200 Subject: [PATCH] Fix deprecated label formatting --- CHANGES.rst | 2 ++ src/click/core.py | 5 +++-- tests/test_commands.py | 16 ++++++++++++++++ tests/test_options.py | 14 ++++++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index f63e68be80..2044927fcb 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -9,6 +9,8 @@ Unreleased tabs in option help text are now escaped, keeping the original completion format while still supporting multi-line help. :issue:`3502` :issue:`3043` :pr:`3504` :pr:`3508` +- Deprecated commands and options with empty or missing help text no longer + render a stray leading space before the ``(DEPRECATED)`` label. :pr:`3509` Version 8.4.1 diff --git a/src/click/core.py b/src/click/core.py index bc04f64266..f104fee747 100644 --- a/src/click/core.py +++ b/src/click/core.py @@ -1189,7 +1189,8 @@ def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None: text = "" if self.deprecated: - text = f"{_(text)} {_format_deprecated_label(self.deprecated)}" + label = _format_deprecated_label(self.deprecated) + text = f"{_(text)} {label}" if text else label if text: formatter.write_paragraph() @@ -2826,7 +2827,7 @@ def __init__( if deprecated: label = _format_deprecated_label(deprecated) - help = f"{help} {label}" if help is not None else label + help = f"{help} {label}" if help else label self.prompt = prompt_text self.confirmation_prompt = confirmation_prompt diff --git a/tests/test_commands.py b/tests/test_commands.py index ddce905bf7..c3f0020d37 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -491,6 +491,22 @@ def cli(): assert deprecated in result.output +@pytest.mark.parametrize("deprecated", [True, "USE OTHER COMMAND INSTEAD"]) +@pytest.mark.parametrize("doc", ["", None]) +def test_deprecated_empty_help_no_leading_space(runner, doc, deprecated): + """A command with empty or missing help text must render the deprecation + label at the normal indentation, without a stray leading space. + """ + + @click.command(deprecated=deprecated, help=doc) + def cli(): + pass + + out = runner.invoke(cli, ["--help"]).output + assert "\n (DEPRECATED" in out + assert "\n (DEPRECATED" not in out + + @pytest.mark.parametrize("deprecated", [True, "USE OTHER COMMAND INSTEAD"]) def test_deprecated_in_invocation(runner, deprecated): @click.command(deprecated=deprecated) diff --git a/tests/test_options.py b/tests/test_options.py index 44cb58f6df..1b93e136e3 100644 --- a/tests/test_options.py +++ b/tests/test_options.py @@ -58,6 +58,20 @@ def cmd(foo): assert deprecated in result.output +@pytest.mark.parametrize( + ("deprecated", "expected"), + [(True, "(DEPRECATED)"), ("USE B INSTEAD", "(DEPRECATED: USE B INSTEAD)")], +) +@pytest.mark.parametrize("help_text", ["", None]) +def test_deprecated_empty_help_no_leading_space(help_text, deprecated, expected): + """An option with empty or missing help text must not gain a stray leading + space before the deprecation label. + """ + opt = click.Option(["--foo"], help=help_text, deprecated=deprecated) + ctx = click.Context(click.Command("cli")) + assert opt.get_help_record(ctx)[1] == expected + + @pytest.mark.parametrize("deprecated", [True, "USE B INSTEAD"]) def test_deprecated_warning(runner, deprecated): @click.command()