From fa1c3d946e447f62f2ba7e9adf79d7e9d17a7766 Mon Sep 17 00:00:00 2001 From: Bibek Date: Sat, 9 May 2026 21:12:24 -0400 Subject: [PATCH] Fix HelpFormatter.write_usage dropping prefix when args is empty --- src/click/formatting.py | 19 ++++++++++++------- tests/test_formatting.py | 8 ++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/click/formatting.py b/src/click/formatting.py index de2ca47117..f5da95d52f 100644 --- a/src/click/formatting.py +++ b/src/click/formatting.py @@ -161,14 +161,19 @@ def write_usage(self, prog: str, args: str = "", prefix: str | None = None) -> N if text_width >= (term_len(usage_prefix) + 20): # The arguments will fit to the right of the prefix. indent = " " * term_len(usage_prefix) - self.write( - wrap_text( - args, - text_width, - initial_indent=usage_prefix, - subsequent_indent=indent, + if args: + self.write( + wrap_text( + args, + text_width, + initial_indent=usage_prefix, + subsequent_indent=indent, + ) ) - ) + else: + # No args, but still need to write the "Usage: prog" prefix. + # rstrip removes the trailing space added when building usage_prefix. + self.write(usage_prefix.rstrip()) else: # The prefix is too long, put the arguments on the next line. self.write(usage_prefix) diff --git a/tests/test_formatting.py b/tests/test_formatting.py index c74b53a3df..8e001f4672 100644 --- a/tests/test_formatting.py +++ b/tests/test_formatting.py @@ -433,3 +433,11 @@ def test_help_formatter_write_text(): actual = formatter.getvalue() expected = " Lorem ipsum dolor sit amet,\n consectetur adipiscing elit\n" assert actual == expected + + +def test_write_usage_no_args(): + """Regression test for issue #3360: write_usage with empty args + should still emit the 'Usage: prog' prefix, not an empty line.""" + f = click.HelpFormatter() + f.write_usage("program") + assert f.getvalue() == "Usage: program\n"