[Frontend] Only show the summary line of config docstrings in `--help` (#57357)
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Harry Mellor committed
Sep 17, 2026 at 13:53 UTC
0ef8366ba39fc38b88c60b17ee2ddf05aa8a7596
2 files changed
+35
-7
tests/utils_/test_argparse_utils.py
+17
@@ -524,3 +524,20 @@ def test_flat_product():
524
(3, 4, "a", 5, 6),
525
(3, 4, "b", 5, 6),
526
]
527
+
528
+
529
+def test_group_description_is_summary_only():
530
+ """Group descriptions are config docstrings, too long for the terminal."""
531
+ parser = FlexibleArgumentParser()
532
+ group = parser.add_argument_group(
533
+ title="MyConfig",
534
+ description="Summary line.\n\nDetails which only belong in the docs.",
535
+ )
536
+ group.add_argument("--my-arg")
537
+
538
+ assert "Summary line." in parser.format_help()
539
+ assert "only belong in the docs" not in parser.format_help()
540
+
541
+ parser._search_keyword = "myconfig"
542
+ assert "Summary line." in parser.format_help()
543
+ assert "only belong in the docs" not in parser.format_help()
vllm/utils/argparse_utils.py
+18
-7
@@ -93,6 +93,11 @@ def human_readable_int_or_auto(value: str) -> int:
93
return human_readable_int(value)
94
95
96
+def summary_line(description: str | None) -> str:
97
+ """Return the first paragraph of a config docstring as a single line."""
98
+ return " ".join((description or "").split("\n\n", 1)[0].split())
99
+
100
+
101
class SortedHelpFormatter(ArgumentDefaultsHelpFormatter, RawDescriptionHelpFormatter):
102
"""SortedHelpFormatter that sorts arguments by their option strings."""
103
@@ -203,7 +208,7 @@ class FlexibleArgumentParser(ArgumentParser):
208
for group in self._action_groups:
209
if group.title and group.title.lower() == search_keyword:
210
formatter.start_section(group.title)
206
- formatter.add_text(group.description)
211
+ formatter.add_text(summary_line(group.description))
212
formatter.add_arguments(group._group_actions)
213
formatter.end_section()
214
formatter.add_text(self._json_tip)
@@ -242,12 +247,18 @@ class FlexibleArgumentParser(ArgumentParser):
247
# positionals, optionals and user-defined groups
248
formatter.start_section("Config Groups")
249
config_groups = ""
245
- for group in self._action_groups:
246
- if not group._group_actions:
247
- continue
248
- title = group.title
249
- description = group.description or ""
250
- config_groups += f"{title: <24}{description}\n"
250
+ groups = [g for g in self._action_groups if g._group_actions]
251
+ titles = [g.title or "" for g in groups]
252
+ title_width = max((len(title) for title in titles), default=0) + 1
253
+ width = max(formatter._width - formatter._current_indent, title_width + 20)
254
+ for title, group in zip(titles, groups):
255
+ lines = textwrap.wrap(
256
+ summary_line(group.description),
257
+ width,
258
+ initial_indent=f"{title: <{title_width}}",
259
+ subsequent_indent=" " * title_width,
260
+ )
261
+ config_groups += ("\n".join(lines) or title) + "\n"
262
formatter.add_text(config_groups)
263
formatter.end_section()
264