docstring-frame
DocsCanonicalizes a docstring's quotes and frames the opener and closer.
A docstring carries two readings inside one triple-quoted region. The description prose between the opening """ and the first section heading reads as paragraphs, where 76 characters is the comfortable line for sustained reading. Every Title-case-headed section that follows reads as a code-shaped table, where its prose lines take the budget docstring-structured-policy selects (code-line-length, 88 by default) so a section's running text runs to the same measure as the code around it, whereas its name: description entries wrap to docstring-line-length with a hanging indent at the description's start column.
The rule reads docstring-line-length for the description budget, code-line-length for the structured budget, and docstring-structured-policy to override the structured budget when a project prefers a single narrower line across the whole docstring. Code blocks inside the description (fenced or indented) are preserved verbatim, since their layout is load-bearing. Every other structured shape passes through unwrapped for the same reason, so a table keeps its columns, a doctest keeps one statement per line, and a field header keeps its type intact rather than collapsing into a paragraph no renderer reads as markup. The examples below carry one case per shape the rule recognizes. An interpreted-text role closes its name on a backtick rather than on whitespace, so a line opening with :class: or :math: reads as prose and wraps with the paragraph carrying it. The prose the rule reflows collapses every interior whitespace run to one space, leaving the word sequence the wrapper measures identical on every run, whereas a section entry's aligned head stays verbatim. A backslash ending a line of a non-raw docstring continues that line into the next, so the two source lines already carry one logical line of the value. Where the rule reflows that prose it resolves the continuation into the join it performs anyway, rather than carrying the backslash into the paragraph, where the backslash would land mid-line as the invalid escape \ and change the text help() renders. A join carrying no whitespace on either side splices before the reflow, so a URL broken across two source lines stays the single atomic token it reads as. A continuation inside a passthrough region travels with the region untouched, and a raw docstring holds no continuations at all, leaving a trailing backslash there a literal character of the value that reflows as an ordinary word. A token that reads as a URL or carries an embedded path / or - wraps as one atomic word, so an over-budget link overflows the measure intact rather than splitting between its segments. An entry's head line and every line below it from the section body indent onward that opens no entry of its own read as one paragraph, rewrapped from the head's current description column, so padding that moves the : reflows the whole description under the new column rather than leaving continuations at the column they were first written to. A line whose own shape marks it as a structure is exempt from that gathering the same way it is anywhere else in the docstring, so a doctest, a list item, or a bracketed literal sitting under an entry keeps its layout whether or not a blank line separates the two. Both sibling docstring rules settle the quoting and the framing before this rule measures anything, and the wrap itself runs after
| Key | Type | Default | Meaning |
|---|---|---|---|
enabled | bool | true | Toggles the rule on or off. |
Description and structured budgets come from the top-level Configuration keys: docstring-line-length (default 76), code-line-length (default 88), and docstring-structured-policy (defaulting to "code-line-length") drive the column targets.
Description prose wraps to docstring-line-length, with the existing paragraph structure preserved across the rewrap.
def greet():
"""
The function-level description carries the same wrap shape as the module
docstring, with each wrapped line indented to match the docstring body.
"""
return 1
A backslash ending a line inside a non-raw docstring suppresses the newline after it, so the two source lines are already one logical line of the docstring's value. The wrap resolves the continuation into the join it performs anyway rather than carrying the backslash into the reflowed text, where it would land mid-line as the invalid escape \ and change what help() renders.
A docstring whose first body line opens with a role wraps to the budget like any other paragraph. That line is a true block boundary, so the field-list test runs and rejects it on the closing backtick, leaving the overflow measured rather than passed through untouched.
A URL too long for one source line is split with a backslash and resumed flush at column zero, so the value carries no separator across the join. The wrap splices those two source lines before it measures, leaving the URL the single atomic token it reads as, where collapsing the pair as ordinary prose lines would insert a space the value never held and break the link in two.
An r prefix stops a trailing backslash from continuing the line, leaving it a literal character of the docstring's value. The wrap reflows it as an ordinary word rather than dropping it, so the guard against the invalid-escape shape a non-raw body produces never costs a raw body a character it was written to carry.
Every whitespace run between two words of reflowed prose collapses to a single space, so the two-space sentence separator some codebases keep is normalized wherever it falls. The run would otherwise survive mid-line and vanish at a wrap point, leaving the paragraph a different length each time it was measured.
A token that reads as a URL or carries an embedded path / or - wraps as a single atomic word, so an over-budget link lands on its own line and overflows the budget intact rather than splitting between its segments, keeping the value copy-pasteable.
A role the wrap lands at the start of a line stays inside the paragraph. A field list opens only at a block boundary, so a marker on a continuation line reads as the prose it is rather than freezing the rest of the paragraph against the next pass.
An Attributes: section in a class docstring wraps its entries with the same hanging-column shape a function Args: entry uses. The walker visits every body whose first statement is a string literal, so class and function docstrings reshape identically.
A docstring carrying both a description paragraph and a structured Args: section wraps each region to its own shape. The paragraph wraps at the docstring budget against the body indent, and the Args: entry wraps at the same budget with a hanging indent at the description column.
A long Args: entry that overruns its line re-wraps to the section budget with a hanging indent at the description's start column, so continuation lines sit under the description rather than at the parameter-list indent. A short sibling entry below it is left alone.
A Returns: section body wraps to the section budget, so the return-value description tracks the same horizontal room the Args: table uses rather than the narrower description budget.
A .config.toml sidecar flips docstring-structured-policy so non-entry section bodies wrap at the narrower docstring budget instead of the default structured budget. A long Note: paragraph wraps at the docstring width once the policy selects it.
A name (type): field header written without an Args: heading above it stays on one line. The parenthesized type marks the line as a header rather than prose, so no wrap splits it at a comma inside the type and lands the remainder at the column a new field name would occupy.
A docstring whose description and section bodies already fit their budgets passes through unchanged. The rule fires only when wrapping actually shortens a line, so short Args: and Returns: entries produce no edit.
List items pass through verbatim and are never re-flowed onto multiple lines, even when an item runs long. The recognized markers cover -, *, +, and numeric ordered items, matching the CommonMark set. Body text after the list resumes the description budget.
A code example introduced by a # comment keeps one statement per line. The comment opens a passthrough block that runs to the next blank line, so the statements below it stay valid Python instead of merging into a single run-on.
A doctest block passes through verbatim. A >>> prompt opens an interactive region that runs to the next blank line, so an example and its expected output never join under a reflow.
A triple-backtick fenced code block passes through verbatim no matter how wide its lines run. The fence marks the region as code rather than prose, so the wrap math leaves it untouched.
A reStructuredText grid table keeps its rows and its column widths. A +---+ corner rule and a |-delimited row each open a passthrough line, so the grid survives instead of filling into a paragraph that no renderer reads as a table.
A four-space-indented block under a description paragraph passes through verbatim because indented blocks read as code samples. Re-flowing them would damage their semantics, so the rule leaves the over-budget lines in place.
A NumPy-style section underline passes through verbatim. A line that is a run of one repeated adornment character such as -, =, or ~ flushes the open paragraph and keeps the heading's landmark instead of gluing onto the line above.
A reStructuredText field list passes through unwrapped, one field per line. Each :name: value line opens a field-list region the wrap math skips, so a run of module metadata survives instead of gluing onto its neighbor.
A reStructuredText simple table keeps its columns, even though its body rows carry no leading punctuation at all. The spaced adornment rule above them opens a passthrough block that runs to the next blank line, so the rows stay under the headings they belong to.
A Sphinx directive passes through verbatim. A .. name:: line opens a directive block, so consecutive directives stay one per line instead of merging into a paragraph a renderer would read as a single directive.
Canonicalizes a docstring's quotes and frames the opener and closer.
Expands a one-line docstring into the multi-line block shape.
Aligns the : separator across dict literals, annotated assignments, function-signature annotations, and Google-style docstring sections.
For the budget semantics, the Docstring Budgets section of the Configuration chapter covers how the description and structured budgets interact.