Repository navigation
docs: add a rule for writing multi-line text in Python - #125
Conversation
Text written as one string literal per line, each ending in \n, hides the text behind quotes and escapes. The new section makes one triple-quoted block through textwrap.dedent the form for text of three or more lines, gives its two endings, and says review is what enforces it. Each new-form example was run under python3 against the text the section states for it, and ruff format --isolated --diff left it unchanged.
A dedented block changes the text in four cases, or is not the right tool for it: a line ending in spaces, a first line that is indented or blank, one long line wrapped across literals, and an f-string whose inserted value can hold a newline. Each is listed with its reason so a reviewer can tell an exception from a miss. Checked under python3: the f-string case comes back with its indent intact, and .strip() removes an indented first line's indent.
A comparison needs two things the source rule does not: the block bound to a name first, because ruff format rewraps the inline assert, and the strip kept to the expected side, so a stray newline in the result still fails. The testing doc gains a section saying so and pointing at the code doc's rule, which links back. The example was run under python3 against the same text written as adjacent literals, and ruff format --isolated --diff left it unchanged; the inline form was rewrapped as the section describes.
The stage's two reviews found the rule's wording short of what it meant in several places: - .strip() was shown but never stated as the default ending, and what it and .lstrip() remove was understated. - The .lstrip() example was two lines, under the rule's own threshold. It is now three. - "Quotes and an escape on every line" is untrue of a joined list. - The f-string case fails only for a value that spans lines, not one that merely ends in a newline. - The testing section stated its two rules twice, said "bind" where "assign" is plainer, and gave its example's text only by pointing at the other file. Also says what shorter text does, and why the quotes sit on their own lines. Every example was pulled from the docs and re-run.
Review findingsThree rounds, newest last. Each finding was reproduced before it was acted on. First reviewTwo fresh reviews read the stage, one against the repo's conventions and one against R1-R8. Each finding was reproduced before it was acted on. All fixes are in the commit for step 1.4. Fixed in this stage
Left as it is
Second reviewAfter the section in Fixed in this stage (step 1.7)
Left as it is
Findings on the Third reviewAfter the testing section was cut at the gate (step 1.6) and the second review's fixes (step 1.7). The first two rounds were run against the default branch's conventions by mistake; this one read the stage against the conventions of the branch that defines how a change is built. The requirements review found R1-R8 met, every claim the sections make about Python and Fixed in this stage (step 1.8)
Left as it is
Issues to fileNone. |
The reviewer asked at the stage's gate for a more concise section. It drops from 418 words to 293: the worked example of the old form goes, since the sentence naming it is enough; the two forms not to use become two bullets; and each of the four cases keeps its reason in one short sentence. Nothing R1-R4 require was removed, and both examples were re-run against their stated text.
|
At the gate: the reviewer asked whether |
The reviewer pointed out at the stage's gate that the code doc's rule already covers tests, so the testing doc need not repeat it. The section loses its example and its restatement of the form, and keeps the pointer and the two rules only a comparison needs: assign the block before the assertion, and strip the expected side only. It stays as a section because someone writing tests is sent to the testing doc, and those two rules appear nowhere else.
|
At the gate: the reviewer asked whether |
A second review of the shortened section found places where the cut left a sentence unclear: - "ending in .strip()" had nothing to attach to. - The two forms not to use sat as bare "Not ..." bullets under a sentence about a value, splitting the rule from its .lstrip() variant. They are one sentence after both examples now. - The wrapped-line case said adjacent literals stay as adjacent literals, having lost "not multi-line text". - The trailing-spaces case no longer said where the spaces are stripped. The four cases take the "lead - reason" form the file's other bullets use, and "or a blank line" goes: such text already ends in a newline.
This comment has been minimized.
This comment has been minimized.
A review of the sections as cut found one claim that was wrong and three sentences a reader had to work at: - ruff format pushes only the opening quotes deeper when it rewraps the inline assert. The closing quotes are inside the string and stay level with the text. - "The block" was used without being introduced. The rule sentence now names it. - The inspect.cleandoc sentence never said not to use it. - In the f-string case, "its" and "the lines" could each be read two ways.
|
At the gate: the reviewer approved the stage as it stands after step 1.8. Decided here: both sections stay as cut - no written-out example of the old form, no example in the testing section - and the brief's R3 and R5 were reworded to match what was built, with a comment on the change's issue. |
The Python code conventions now say how to write text of three or more lines: one triple-quoted block through
textwrap.dedent, ending in.strip(), or in.lstrip()where the text must end in a newline. They name four cases that stay as adjacent literals, and say review is what enforces the rule. The Python testing conventions gain a short section for expected text that points at the rule and adds the two things only a comparison needs: assign the block to a name first, and strip the expected side only.This is the one stage of Write multi-line text as dedented triple-quoted strings, and delivers R1-R8. Nothing is left unbuilt.
Changed from the plan
.lstrip()example has three lines of usage text, not the two the build notes gave it: at two it fell under the rule's own threshold.Yours to overturn
dedentoverinspect.cleandocis one sentence in the section, in place of an ADR.Try it
Paste the
_USAGEblock from the new Multi-line text section intopython3afterimport textwrap, then runprint(repr(_USAGE)). A good result is'usage: prog [-h] FILE\n FILE the file to read\n -h show this help\n'.The agent did this for both examples in the section, pulled from the doc as committed, and
ruff format --isolated --diffleft each one unchanged.Closes #124
Closes #111