config: preserve indentation and blank lines in help texts - #15032
Merged
RonnyPfannschmidt merged 2 commits intoSep 15, 2026
Merged
Conversation
87423d3 (pytest-dev#6817) made help texts keep their explicit line breaks by splitting on newlines and wrapping each line separately. Its commit message already named the cost: This might also result in unexpected changes (hard wrapping), when line endings where used unintentionally, e.g. with: help=""" some long help text """ The `line.strip()` it used to contain that is too blunt: it cannot tell source indentation from structure, so it also flattens the indentation that carries meaning. A wrapped list item became indistinguishable from a new item, and a blank line disappeared entirely because `textwrap.wrap("")` returns no lines. Use `textwrap.dedent` instead, which removes exactly the common source indentation that the 2020 commit was worried about while keeping what is relative to it. Each line then wraps with its own indent, continuation lines of a list item hang under the item's text, and blank lines survive. Reuse the result for ini options too. `showhelp()` had a second, simpler wrapping implementation that passed the whole help text to `textwrap.wrap`, so newlines degraded to plain whitespace and the structure was lost altogether -- visible in pytest's own `parametrize_long_str_id_strategy`: parametrize_long_str_id_strategy (string): strategy for long str/bytes parameter values in auto-generated ids - short (default): values over 100 chars fall back to argname+index - sha256: replace value which now renders as the list it was written as. Co-Authored-By: Claude Opus 5 (1M context) via Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) via Claude Code <noreply@anthropic.com>
nicoddemus
approved these changes
Sep 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Supersedes #15021, which fixes a narrower symptom on top of a base that is
itself wrong.
Background
87423d3 (#6817, @blueyed) taught the help formatter to keep explicit line
breaks, so that a help text can be written as a list instead of being reflowed
into one blob. It did that by splitting on newlines and wrapping each line
separately. That commit's own message names the cost:
The
line.strip()in_split_linesis what holds that back. It works, but itcannot distinguish source indentation from indentation that carries meaning, so
it flattens both:
A wrapped item is now indistinguishable from a new one. Blank lines vanish too,
since
textwrap.wrap("")returns no lines — that is the symptom #15021 reports.The other half
There are two independent wrapping implementations.
helpconfig.showhelp()passes the whole help text to
textwrap.wrap, so newlines degrade to ordinarywhitespace and the structure is lost completely. pytest's own ini option:
Core has exactly one CLI option (
--assert) and one ini option (that one) withnewlines in their help, so this path is where the only currently visible
breakage is.
This change
textwrap.dedentis the right tool for whatstrip()was reaching for: itremoves exactly the common source indentation, and keeps what is relative to it.
Each line then wraps carrying its own indent, and a list item's continuation
lines hang under the item's text. Both call sites share one
_split_help_text,so the ini path stops rotting separately.
Details worth a reviewer's eye:
the opening quotes, so it contributes no common prefix and plain
dedentonthe whole text would find
""and do nothing.the text from the option it documents.
_format_actionstrips trailing whitespace, because argparse pads a blankhelp line out to the help column.
break_on_hyphens=Falsematches whatshowhelpalready passed, and stopsauto-generatedsplitting mid-word.On reusing something instead
Checked, none fit:
textwraphas onlyTextWrapper, which is single-paragraph byconstruction:
initial_indent/subsequent_indentare two fixed strings forthe whole call. argparse's
RawTextHelpFormatterpreserves structure but doesnot wrap at all.
wrap_text(preserve_paragraphs=True)sounds right and is not. Itre-flows paragraph interiors, so pytest's bullet list collapses into exactly
the run-on above; its
\bescape disables wrapping outright, so items justoverflow the terminal.
Textgets the model right, but gives continuation lines no indent(so it does not fix the actual bug), and is a large dependency for help
formatting.
Checklist
changelogdirectory.Co-authored-bycommit trailer.