align-colons
Pads the space before : so consecutive dict entries, annotated assignments, signature annotations, and docstring entries share one column, with a docstring entry's parenthesized type in a column of its own.
reflow-collections expands a multi-entry collection literal across lines once its single-line form overflows code-line-length, and leaves a literal that fits on its row. It reaches dict, list, set, and tuple literals, a tuple only where it carries its parentheses.
Inside the expanded form, a non-atomic entry (a function call, a nested collection, a computed expression) takes a row of its own, whereas a run of atomic entries (ints, floats, strings, single-name identifiers) packs across as few rows as fit, each row taking at most max-atomics entries within the budget. A non-atomic entry in the middle of such a run splits it into two runs packed on their own.
The rule runs the inverse move too, rejoining a construct broken somewhere other than an entry boundary, and the rejoin reaches a multi-line subscript, a collection used as a dict key, and a comprehension broken across its for and if clauses. A subscript and a comprehension only ever rejoin and never expand the way a literal does, so one too wide to fit, or one carrying a comment or a multi-line string, keeps its breaks. A construct that would overflow once joined keeps its break, as does one whose nested call is already written one argument per line, carries a comment, or passes max-args. A collection inside an f-string replacement field is left as written whatever its width, and a literal inside a % template or a str.format() call that prefer-fstring converts on the row it lands on never expands, since the conversion places it in a replacement field.
A literal the author already laid out as a bracketed column, its opening bracket ending a line and its closing bracket opening one, is the exception to the rejoin, because its breaks already sit at entry boundaries. keep-multiline-literals, on by default, keeps that column along with the : alignment align-colons pads, and holding one needs two or more entries. A construct enclosing a kept literal has no one-line form either, so it keeps its break as well, whereas any other break rejoins.
A member the expansion keeps as written rather than laying out moves whole into the expanded form, its continuation rows shifted to the column the entries sit at, so a kept call or subscript reads under its siblings. A member whose rows align under its own opening bracket keeps the whole construct as written instead, and one running through a multi-line string keeps the string's own columns. A literal nested inside a member that moves whole, whether as a kept call's argument, an operand inside a generator, or the list a subscript indexes, still takes the layout it would take as an entry of its own, measured at the row where it lands.
A dict expands once it has more than max-dict-entries entries whatever its width, and every collection enclosing it expands with it. A collection expands the same way when it holds a call that the count trigger of reflow-calls explodes, since that call leaves the collection no one-row form to keep.
Every width the rule reads counts the separator closing an entry's row at the position alphabetize-siblings leaves it in, on the rejoin as well as the expansion. An entry the sort moves last sheds the comma it carries and one the sort moves up gains one before either is measured, so the layout the rule picks stays put once the sort is written. Each construct is then measured at the column it settles at:
:, which is the width a rejoin writes it back at.type statement is measured at the column align-equals pads its row to, so a collection value whose row would cross the budget at that column expands in the same pass, under the same comparison as item 5 and only where the padding stays within the max-shift of align-equals.| Key | Type | Default | Meaning |
|---|---|---|---|
enabled | bool | true | Turns the rule on or off. |
explode | bool | true | Explodes a collection that overflows the line budget or exceeds its entry cap to one entry per line. false turns every explosion off, leaving the count cap with no effect. |
keep-multiline-literals | bool | true | Keeps a literal the author wrote as a bracketed column of two or more entries, one per line. false joins one back onto a single line where it fits the budget, and any other multi-line layout rejoins either way. |
max-atomics | positive int | false | 8 | Caps how many atomic entries, meaning ints, floats, strings, and single names, one packed row of an expanded collection carries. false removes the cap and packs each row by width alone. |
max-dict-entries | positive int | false | 3 | Expands a dict once its entry count exceeds the cap, whatever its width. false disables the count trigger. |
wrap-dict-entries | bool | true | Breaks an over-wide key: value at its : and hangs the value beneath. false leaves the oversized entry on one line. |
Each move sits behind its own facet, whereas the rejoin has none.
explode explode gates the expansion itself, covering the count trigger as well as the width one. At false every expansion stops and the count cap has nothing left to act on, whereas the rejoin runs either way.
keep-multiline-literals keep-multiline-literals keeps a literal the author wrote as a bracketed column of two or more entries, re-expanding it to the canonical layout rather than joining it back. Setting it to false joins one onto a single line wherever it fits the budget, and any other multi-line layout rejoins either way.
max-atomics max-atomics caps how many atomic entries one packed row of an expanded collection carries, defaulting to 8, and false removes the cap so each row packs by width alone.
max-dict-entries max-dict-entries expands a dict once its entry count passes the cap, whatever its width, so a four-entry dict expands at the default 3 even when it fits the line. The cap reads dicts alone, which is why a short tuple inside a call's argument list, like numpy.zeros((3, 4)), stays inline, whereas at false the width trigger becomes the only one a dict meets.
wrap-dict-entries wrap-dict-entries breaks an over-wide key: value at its : and hangs the value one indent step in, row by row rather than across the whole literal, a layout only a dict takes. Setting it to false leaves the oversized entry on one line.
short_dict has three entries, long_dict has seven on one line, single_entry_dict is one entry broken across rows, and held_dict is three entries written one per line. long_dict expands to one entry per line and reads as a column of key: value pairs, because it passes max-dict-entries, whereas short_dict stays inline, held_dict keeps its column because keep-multiline-literals is on by default, and single_entry_dict rejoins onto one line because a one-entry dict has no column to keep.
short_dict = {"alpha": 1, "beta": 2, "gamma": 3}
long_dict = {
"alpha": 1,
"beta": 2,
"gamma": 3,
"delta": 4,
"epsilon": 5,
"zeta": 6,
"eta": 7
}
single_entry_dict = {"default_action": "noop"}
held_dict = {
"alpha": 1,
"beta": 2,
"gamma": 3
}
bare and parens each list seven names, one without parentheses and one with, and both lines run past the budget. bare is left as written and parens expands into packed rows, because a tuple without parentheses has no bracket pair to break inside, whereas a parenthesized tuple expands the same way a list does.
The "gamma" list crosses the budget, so the rule expands it inside CONFIG and writes the dict's other entries back around it. The blank line written above **DEFAULTS stays in place, because the rule reads an unpacking's row from its ** rather than from the value that follows it.
The tuple key (alpha, beta) in mapping and the subscript key registry[lookup_index] in keyed are each broken across rows, and the tuple key in overflow is too wide to rejoin. The keys in mapping and keyed rejoin onto one row, so each reads as one member the alignment and ordering rules can place in a run, whereas the key in overflow expands to one element per row because its joined form would pass the budget.
mixed_atomics lists literals, names, attribute chains such as pkg.CONST, and unary operands such as ~mask, all of which count as atomic, whereas split_by_call puts the call lookup() between two runs of strings. mixed_atomics packs as one run across two rows, and in split_by_call the call takes a row of its own with the strings before and after it packed as two separate runs, because a non-atomic entry splits the run around it.
selected subscripts a four-entry dict with [chosen_key] on one line. The dict expands to one entry per line and }[chosen_key] closes it on the last row, because the dict passes max-dict-entries, and the enclosing subscript reads the expanded dict as a break it cannot rejoin, so the construct reaches one layout rather than alternating between expanded and rejoined on each run.
over_threshold has four entries and fits its line, under_threshold has three, and already_expanded has four written one per line. over_threshold expands to one entry per line, because it passes the default max-dict-entries, whereas under_threshold sits at the cap and stays inline, and already_expanded keeps the layout it has.
held_list is written as a bracketed column, its opening [ ending a row and its closing ] opening one, the registry subscript is broken inside its brackets, and the tuple key in repaired_collection_key is a bracketed column of its own. held_list keeps its column and packs onto one row, and the subscript and the tuple key rejoin onto one line, whatever keep-multiline-literals is set to, because a subscript and a dict key whose joined form fits always rejoin, and only a literal's own entry boundaries make a column the author built.
nested lists alpha, a helper call already written across rows, and zeta in a list that already spans rows. The list expands one entry per row, and the call moves whole with its beta and gamma rows re-indented one step under helper(, because a member already laid out across rows is kept rather than laid out again, and its continuation rows shift to the column the entries sit at.
code-line-length = 50 is set, and the yield inside walk carries two tuples, the first past the budget and the second written under a continuation column. The first tuple expands to one component per row and the second packs beside the first's closing ), because a literal following an expanded one on the same line is measured where that expansion leaves it, on the closer's row at the statement's indent, rather than under the continuation column the source wrote.
class_name, trailing_bracket_shares_its_line, soft_wrapped_set, soft_wrapped_spread, and soft_wrapped_single are each broken with an opening bracket sharing a row with an entry or a closing bracket trailing one, whereas tuple_key_column puts both brackets on rows of their own. The five rejoin onto one line, the one-element tuple keeping the trailing , that makes it a tuple, and tuple_key_column keeps its column, because a break that sits on no entry boundary is a wrap rather than a column the author built, and only the trailing , after "second": 2 is dropped as the kept column is written in the canonical layout.
small_matrix fits its line, and tall_matrix lists five inner lists past the budget. tall_matrix expands one inner list per line and each inner list such as [100, 200, 300] stays inline, because each inner list fits at its own column, so the matrix reads one row per line rather than one cell per line.
code-line-length = 40 is set, and queued_record_ids and pending_batch_key would share a row at exactly forty columns if they packed together. All three entries end up one per line, because resolve(key) is a call and takes a row of its own, so the row above it has to close with a ,, and that comma counts toward the budget and takes the row to forty-one columns.
code-line-length = 40 is set, and the tuple key in lookup runs past it with the value (1, 2) and a trailing comment after it. The key expands to one component per row and the value stays on the closing row beside the :, because the value is measured from the column the : sits at on the key's last row rather than from the key's rows read as one line, which leaves room for (1, 2).
config, mixed, and multiple_hung_rows each carry an entry whose key: value row runs past the budget, and nested_value_passes_through carries an over-wide nested dict under "limits". Each over-wide entry breaks at its : and hangs its value one indent step in, because a dict entry that overflows breaks row by row rather than across the whole literal, so "alpha" and "beta" stay on one row, mixed hangs a row between fitting siblings, multiple_hung_rows hangs two rows in one dict, and the "limits" value expands as a nested dict rather than hanging.
short_list fits its line, long_list lists seven city strings past the budget, and held_list is five integers written one per line. long_list expands and its seven strings pack onto one row inside the brackets, because atomic items pack across as few rows as fit under code-line-length and max-atomics, whereas short_list stays inline and held_list keeps its column and packs onto one row as 2, 3, 5, 7, 11 rather than rejoining.
atomics lists ten integers and nonatomics lists six calls, each in a parenthesized tuple past the budget. atomics packs its integers across two balanced rows and nonatomics puts one call per row, because a parenthesized tuple takes the same layout as a list, with atomic entries packing across as few rows as fit under code-line-length and max-atomics and a non-atomic entry taking a row of its own.
list_comp, dict_comp, set_comp, and gen_exp are each broken across rows, and each joined form fits the budget. All four rejoin onto one line, because a comprehension is one expression rather than a run of entries, so the rule only ever rejoins one and never expands it, and one too wide to fit would keep its breaks.
cascade, tiered_dict, shallow_dict_in_dict, and walks_through_singleton each nest a collection inside another on one over-wide line, and outer_holds_with_inner and outer_pinned_inner_holds each carry an inner list written across rows. Every nested collection expands or stays inline on its own width at its own column, rather than following whatever the outermost one does.
In cascade the outer list expands and its over-wide first dict expands with it while {"name": "bob", "role": "user"} stays inline, in tiered_dict the four-entry inner dict under "primary_database" expands on its own count and width while "cache": {"ttl": 60} fits, and walks_through_singleton keeps its [{ tight while the six-entry dict inside it expands. The inner list of outer_holds_with_inner keeps its column and packs onto one row inside an outer list that keeps its own column, whereas outer_pinned_inner_holds keeps the same inner column under an outer list its long strings already keep past the budget.
code-line-length = 30 is set, and checksums lists two seven-digit and two twelve-digit integers on one line. The list expands and its last row packs both twelve-digit integers at exactly thirty columns, because no entry follows that row, so it carries no trailing , and none is counted, whereas counting one would have taken the row one column over and split the pair.
keep-multiline-literals = false is set, fitting_joins is written one item per line with a joined form that fits, and overflowing_explodes runs past the budget on one line. fitting_joins rejoins onto one line as [10, 20, 30] and overflowing_explodes still expands into packed rows, because the facet releases only the kept column, leaving the width trigger under explode in force.
wrap-dict-entries = false is set, and the config dict runs past the budget on one line with an entry keyed extremely_long_key_name_that_pushes_its_row_past_the_budget that passes the budget even on a row of its own. The dict expands one entry per line and the over-wide entry stays on one row rather than breaking at its :, because the facet turns off only the hang, leaving the width and count triggers in force.
The list [alpha, beta, gamma] sits inside a replacement field of the f-string passed to ValueError, on a row past the budget. The list is left as written, because the rule never rewrites inside an f-string's replacement field, so no line break is ever written into the string.
The dict inside the f-string in ROWS carries four entries, one past max-dict-entries, the count that normally expands a dict and every collection enclosing it. Neither the dict nor the ROWS list expands, because a collection inside a replacement field is outside the rule's reach, so its count never fires the trigger for the list around it.
one_element is a one-element tuple past the budget with its trailing ,, and grouping is a parenthesized sum past the budget. Both are left as written, because breaking a single element across rows gains nothing, and a parenthesized expression is not a tuple, so the rule does not reach it whatever its ( ) spelling.
canonical_inline fits on its line, canonical_multi_line already sits one entry per line with a joined form that would overflow, and canonical_hung_entry already hangs its over-wide entry's value on the row after the :. All three pass through with no edit and nothing is reported, because each already sits in the layout the rule would write.
explode = false is set, and the config dict runs past the budget on one line because of its extremely_long_key_name_that_pushes_its_row_past_the_budget entry. The whole dict stays on its line, because the hang that breaks an over-wide entry at its : is part of the expansion the facet turns off.
explode = false is set, overflowing_list runs past the budget, over_count_dict has five entries, and already_multiline is written across rows. All three are left as written, because the facet turns off both the width trigger and the count trigger, and the already multi-line list keeps its column under keep-multiline-literals.
The "alpha" and "beta" arms of dispatch each return a long inline dict, and the wildcard arm returns None. Each dict explodes to one entry per line, its keys sort so "comment_text" leads, and the : of each entry pads into one column within its arm, while align-match-case joins the wildcard's return None onto its case _: line.
CASES already holds its keys in order, and the "restore-of-both-in-a-cluster" row crosses the code-line-length of 80 with or without its padding, so reflow-collections breaks its tuple open across three rows. The entry keeps its place in the run it shares with "restore-of-the-working-tree" and "shallow-abbreviated-depth", padded to their column with no blank line after it, because alphabetize-siblings reorders nothing here and so keeps the blank lines the source writes rather than setting one on either side of each entry spanning rows.
A one-line configure call carries a four-entry dict in its settings keyword. reflow-collections explodes the dict, reflow-calls re-indents it to the keyword column, alphabetize-siblings sorts the keywords and the dict entries, and align-equals and align-colons pad the = and : columns. The dict entries sit one indent step past the keyword column, with the closing } back at the keyword column.
deque([(start, 0)]), {start} assigns a call and a one-item set on one row that crosses the 50-column budget. reflow-collections never breaks a one-item set, so the row's tail counts at its full width rather than only up to its {. deque( explodes with its list argument packed on a row of its own, where it fits, rather than the inner tuple exploding under a column the explode would then have moved.
The list in the cccc keyword of g crosses the 40-column budget, and its first member is the call fn(100, 1000). reflow-collections explodes the list, and reflow-calls leaves fn(100, 1000) on one line, because exploding it would measure against a tail the explode is about to remove, so the call is measured where its entry ends up and fits there.
The # prose: skip[reflow-calls] comment holds HANDLERS from reflow-calls, so reflow-collections leaves the dispatch call on one row rather than exploding it into the column "variable" sets. "cache" and "pr" align on the narrower column their own keys set, and "variable" stands unpadded beneath them.
The dispatch call would cross the budget padded out to the column "variable" sets, yet with reflow-calls off reflow-collections leaves the call on one row, because exploding a call belongs to reflow-calls. "cache" and "pr" align on the narrower column their own keys set, and "variable" stands unpadded beneath them.
At a 52-column budget, stacking the expression statement fetch(...).order_by(name).all() inside f sets the receiver fetch( on a row at indent 8, so the argument list reflow-calls explodes lands at indent 12, where the f-string prefer-fstring writes for "%s:%s" % (gamma.get(key).strip().lower(), delta) ends three columns past the budget. stack-method-chains measures the receiver's template from the indent the stack moves it to rather than the one the statement sits at, so the template stays as written and its three-link inner chain breaks under the count trigger in the same pass.
At a 50-column budget, stacking fetch(...).order_by(name).all() inside a parenthesis pair sets the receiver fetch( on a row at indent 4, so the argument list reflow-calls explodes lands at indent 8, where the f-string prefer-fstring writes for "%s:%s" % (gamma.get(key).strip().lower(), delta) ends one column past the budget. stack-method-chains reads whether a template inside the receiver converts from the reflow-calls walk over the receiver where the stack lands it, so the template stays as written and its three-link inner chain breaks under the count trigger in the same pass.
At a 36-column budget, stacking fetch(...).order_by(name).all() explodes fetch( at indent 8, and reflow-collections expands the operand tuple of "%s=%s" % (field.name.strip().lower(), value) at indent 12, where the 26-column field.name.strip().lower() runs two columns past the budget. stack-method-chains measures a chain inside the tuple from the row the tuple's expansion lands it on, so the chain breaks under the width trigger in the same pass rather than on the next.
At a 50-column budget, stacking query.filter(...).order_by(name).all() sets query.filter( on a row at indent 4, so the argument list reflow-calls explodes lands at indent 8, where the f-string prefer-fstring writes for "%s:%s" % (gamma.get(key).strip().lower(), delta) ends one column past the budget. stack-method-chains reads whether a template inside a link converts from the reflow-calls walk over that link's arguments where the stack lands them, so the template stays as written and its three-link inner chain breaks under the count trigger in the same pass.
The tuple on the left of the = breaks before its closing parenthesis, which the source indents under the tuple's first element. reflow-collections moves that closer to the indent of the row its opener sits on, the statement's own indent. reflow-calls then explodes the type(self).prepare_context(...) call after the closer with its arguments hanging from the statement's indent, because the call is measured from that row rather than from the continuation row the source wrote.
One key of _hash_action carries a stranded space before its closing parenthesis, (False, False, False, True ), and strip-stranded-padding removes it. align-colons pads the run onto one : column, because it measures each row at the width it has once that removal is written, whereas the padded width would have read as a breach of the 40-column budget and the run would have skipped its column over a breach that never happens.
The trailing comment on "cache" keeps MUTATIONS as written, since reflow-collections lays out no literal a comment sits inside. The "pr" set therefore never expands, so "pr" stays unpadded, because padding it to the column of either neighbor would carry its row past the budget. With "pr" out of the run, "cache" and "variable" each stand alone, and every : stays flush against its key.
The dispatch call fits the budget beside "pr", but padding "pr" out to the column "variable" sets would carry the call three columns past it. reflow-collections measures the call at that padded column and explodes it one argument per row, its closing ) on a row of its own at the entry's indent, so "pr" joins the : column align-colons pads "cache" and "variable" out to.
CONFIG is written as one overlong line with its keys out of order. The dict explodes to one entry per row, the keys sort, and every : pads into one column one space past the widest key, "beta_extended", so even the short "zeta" row takes the full padding to reach that column.
At a 32-column budget, the f-string prefer-fstring writes for "%(name)s: %(value)s" % {...} runs past the budget, so reflow-collections expands the dict. reflow-collections reads the ( of describe( as a bracket a layout rule can break, since the rewrite around it reaches past the dict it lays out, so align-colons pads "name" and describe( explodes in the same pass.
tagdefs writes two spaces after each key's :, and alphabetize-siblings moves "stderr" ahead of "stdout", the comment above "stdout" moving with it. The "stdout" value, last after the sort, stays on one row at exactly the 40-column budget, because reflow-collections measures a value from the plain ": " past its key rather than from the two spaces the source wrote, and the row is written back at that width, whereas the "stderr" value explodes.
__all__ lists six entries on one overlong line, three short names interleaved with three thirty-character ones. alphabetize-siblings sorts them so the short names lead, and reflow-collections packs them onto rows within the 88-column budget. The packing measures the widths the sort leaves, not the widths as written, which is why "cc" shares a row with the first long name rather than joining the two short entries above it, and the six entries settle onto three rows of two with no row widening afterward.
Two tuples sit on one row that crosses the 88-column budget, one inside isinstance(...) and one after in. The tuple inside isinstance comes first, so the overflow goes to that call, and the rest of the row counts at its full width rather than only up to the second tuple's (. isinstance( explodes with toklist and (type(None), basestring, list) each on a row of their own, and (None, "", []) stays on one row, where it already fits, the tuple inside isinstance staying packed as well.
The dict passed to self.call_exception_handler lists 'message', 'exception', and 'loop', each with a trailing comma, and the sort moves 'message' last. alphabetize-siblings settles which entry ends the dict, so reflow-collections measures each entry with the separator that order leaves after it, and the 'message' entry, last after the sort, drops its comma, fits its row within the 79-column budget, and the layout settles once the sort is written.
c's row reaches 79 columns on one line, inside the 80-column budget where it stands, but 90 padded out to the column bbbbbbbbbbbb sets. reflow-collections expands the list so its opening row joins that column, because expanding it leaves the three rows in one column, whereas keeping it on one row would leave c unpadded beneath the other two.
The comprehension on a's row is wrapped by hand, and reflow-collections rejoins it onto one row that reaches 77 columns, inside the 80-column budget. Padded to the column positionals sets, the row would reach 87 columns, but the one bracket a layout rule breaks on it, [PARSER, REMAINDER], sits inside the comprehension rather than opening the value. No layout rule breaks the row open to join that column, so it stays at its own column and settles in one pass.
band-constants seats CHECK_DELAY above _openers, and the column align-equals pads each row to is read in that order. Padded to the column CHECK_DELAY sets, the _openers row would reach 42 columns, past the 40-column budget, so reflow-collections expands the dict in the same pass and its opening row joins that column.
Padded to the column "aaaaaaaaaaaaaaaa" sets, the "cc" row would cross the budget, so with every value on one row X splits into two columns, "aaaaaaaaaaaaaaaa" and "bbbbbbbb" in one and "cc" and "dd" in the other. reflow-collections explodes the configure call because that leaves the dict in one column rather than two, even though no row stands alone either way.
self.loggerMap is assigned a dict with spaces just inside its braces, and m a dict with no space after any :. strip-stranded-padding removes the spaces from the first and writes a space after each : in the second, and reflow-collections measures each literal at the width those edits leave, so the first stays on its row and only the second, now past the 40-column budget, explodes.
args's list rejoins onto one row at the width its two f-strings take together, and each call alone would still leave that row past the 79-column budget. prefer-fstring measures each rewrite with every other rewrite on its row in place, so both calls convert in the pass that joins the list, where holding each call to the budget alone would leave the joined row too wide for either.
The first element of the set s is written across two lines as (1, and 2). alphabetize-siblings sorts each element by the text it has once joined onto one row, not by the broken text in the source, so (1, 2) sorts after the long tuple.
Sorting puts the long tuple first, which gives it a trailing comma, and measuring it with that comma takes it one column past the 40-column budget, so it explodes rather than staying on one row.
At a 50-column budget, the value "%s:%s" % (type(exc), exc) runs "faultString"'s entry past the budget, whereas the f-string prefer-fstring writes for it fits. reflow-collections measures the value at the width of f"{type(exc)}:{exc}", so the entry stays on one row and a second pass finds nothing left to join.
The % tuple in the TypeError call crosses the 60-column budget, with type(other).__qualname__ as its first element and two closing parentheses stacked at the end of its last row. reflow-collections explodes the tuple to one element per row with its ) on a row of its own, and reflow-calls moves the TypeError closer onto its own row as well. The type(other).__qualname__ call stays on one line, because the explode moves self.__class__.__qualname__ and the two closers off its row, and type(other).__qualname__, alone fits the budget.
d is a dict with # prose: keep at the end of its line, written with "b" before "a" and too wide for the 40-column budget. reflow-collections explodes the dict, which moves the marker onto the closing } line, and the marker still keeps the dict out of alphabetize-siblings, so "b" stays ahead of "a" and the entries keep their order and their separators, because the marker applies from the line of either the { or the }.
_FORMATS lists FMT_BINARY and FMT_XML in the order alphabetize-siblings leaves them, so the last entry gains no separator, and align-colons pads FMT_XML onto a : column that puts its row exactly at the 45-column budget. The column stays, because reflow-collections measures that row at exactly the budget rather than past it, and the padding is not stripped back.
At a 71-column budget, the f-string prefer-fstring writes for "%s %s" % ([alpha_value, beta_value, gamma_value], describe(first)) reaches the budget exactly. reflow-collections leaves a literal on its row where the reflow-calls walk leaves the template around it for prefer-fstring, so the conversion is the one edit reported and the list stays joined inside the f-string.
non_adjacent.append( (la, lb, 0) ) carries a space after append( and a space before its closing ), and the row crosses the 40-column budget by exactly those two spaces. strip-stranded-padding removes both, and reflow-collections measures the tuple at the width that removal leaves, so the tuple stays on its row, the first space narrowing the column the tuple starts at and the second narrowing the text trailing it.
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf)) passes two calls joined by +, and the row crosses the 40-column budget. _flatten( explodes directly, because reflow-calls measures it with the + self._options( that trails it on the same row counted in, whereas measuring the call alone would have left the row for reflow-collections to break at the tuple first and the call would then have exploded on a later pass anyway.
ENDPOINTS is already aligned, the reviewers entry padded out to the column the attempts key sets, when the one-row comments entry is added beneath it. reflow-collections measures the opening row of reviewers at the canonical ": " rather than with the padding it already holds, so that row stays in the run, and the comments list, whose row would cross the budget at the column, expands so comments joins it. The dict comes out the same as it would from input carrying no padding at all.
MUTATIONS sits on one row far past the budget, so reflow-collections writes one entry per row. Each value is measured at the column align-colons shifts it to once those rows align, so the "pr" set, which fits beside its own key but not at that column, expands in the same pass that writes the rows.
PRIMARY overflows its line with values written in the older Optional and Union forms, and target-version = "3.10" allows the | syntax. modernize-annotations rewrites each value to | form first, so every rule downstream measures the shorter text, and the dict then explodes, its keys sort so "delta_long" moves ahead of "gamma", and align-colons pads the : column against the rewritten widths. With nothing left reading either name, from typing import Optional, Union is removed.
d opens with { # note and lists "zz" before "a": 1, "b": 2 packed on one row. The comment on the { row keeps reflow-collections from splitting that row, and a packed row is never reordered, so the dict keeps its source order under alphabetize-siblings. The "zz" entry is measured with the comma it carries as written rather than one a sort would have moved, its value is too wide for the 40-column budget, so that value explodes while "a": 1, "b": 2 stay packed on their shared row.
s is a set packed across three rows with # note at the end of the first. The comment inside the set keeps its order fixed under alphabetize-siblings, so no element moves, and reflow-collections measures each element with the comma it carries as written rather than the one a sort would have left. The one element too wide for the 40-column budget explodes onto rows of its own, and the packed rows around it keep their commas and their places.
The key ( "pp", "qq" ) is 14 columns as written and 12 once strip-stranded-padding drops the spaces inside its parentheses. reflow-collections measures each value at the column that settled width sets, the same column align-colons pads every key out to, so the "pr" set fits the budget there and stays on one row. Measured at the column the written width would set, two columns further right, the set would cross the budget and expand.
x's list carries bracket padding strip-stranded-padding removes, and with that padding gone and "%s" % ( alpha, ) converted, the row takes exactly the 19-column budget. prefer-fstring measures the row with the padding already cleared, as the layout rules forecast it, so the template converts in the pass that keeps the list on one row.
dirlist.extend([ ... ]) writes a space just inside each bracket of its list, and strip-stranded-padding reports both. reflow-collections explodes the list, rebuilding the bracket interior and carrying that padding away before the strip is written, and the first member call ends up alone on a row inside the exploded list with no padding ahead of it. The _os.path.expanduser(...) call is measured from that row and explodes, because at that column it crosses the 60-column budget, rather than being measured from the row the source wrote.
( type(exc), exc ) carries padding strip-stranded-padding removes, and the f-string prefer-fstring writes replaces that tuple whole. At a 46-column budget the one-row entry reads one column over with each space counted once, so the value hangs after :, where counting the padding twice would rejoin a row the conversion then leaves too wide to take.
total is assigned a % template whose tuple arrives exploded, first and second each on their own line. reflow-collections condenses the tuple onto one line first, and prefer-fstring then measures the conversion against the budget and rewrites "%s and %s" % (first, second) to `f"{first} and {second}", each member inline in the template.
specs is assigned a tuple whose last element is tuple(_mapdict_values(statemap)), on a row past the 40-column budget. reflow-calls leaves a literal that reflow-collections is about to explode unwalked, so reflow-collections explodes the outer tuple and lays out the tuple( and _mapdict_values( calls inside it against the rows the explode leaves. Both calls explode at the column they end up at, because at that deeper column neither fits the budget.
The % tuple in warning ends with a self.userCfg[configType].Get(...) call, and exploding the tuple moves that final item four columns right, past the 79-column budget. reflow-collections reshapes the reflow-calls layout of that call against the row it ends up on, so the call explodes in the same run as the move, rather than on a later pass.
Inside ensure_running, the cmd %= (...) statement spans two rows between fds_to_pass and main_kws["authkey_r"] above it and exe and args below. align-equals builds its runs the same way when it reserves as when it aligns, so the multi-row statement closes the run above it, and exe and args pad onto a narrow column of their own rather than the wider one fds_to_pass and main_kws["authkey_r"] set. reflow-collections reads that same run boundary and joins the tuple within the 80-column budget, rather than exploding it from a column the aligner never uses.
handler_map's return annotation crosses the 50-column budget, and the only collection literal on that row is the [Values, list[str]] list inside Callable. reflow-collections explodes that literal, and reflow-signatures keeps self inline, because it reads the opening row as ending at the literal's bracket rather than exploding a lone parameter to recover width the explode is about to give back.
y is a four-element set on one line past the 30-column budget. reflow-collections packs the rows at the widths alphabetize-siblings leaves in each slot, not the widths the source wrote, so the rows fill the budget as densely as a list's would and the sort is written without widening any row.
The # prose: skip[align-colons] comment holds MUTATIONS from align-colons, so no : column forms for reflow-collections to measure a value against. The "pr" set stays on one row once the dict expands, because it fits the budget beside its own key, and every : stays flush against its key.
table carries # prose: skip[alphabetize-siblings] on its closing line, listing "bb" before "aa". reflow-collections ordinarily measures each entry with the comma the sort is about to write, and the skip directive turns the sort off, and with it the measurement against the sorted order, so every entry is measured with the comma it already carries, and "bb" counts a trailing comma and breaks after its : rather than being measured as the last entry.
foo({"alpha": 1, "beta": 2, "gamma": 3, "delta": 4}) passes one dict as its only argument. reflow-collections explodes the dict to one entry per row, and the call explodes around the dict, its ( and { on separate rows and its } and ) on separate rows, because an argument that spans rows explodes the call whatever the argument count and however short the one-line form. Inside, alphabetize-siblings sorts the keys so "delta" moves ahead of "gamma", and align-colons pads each : into one column.
The rows of "pr" and "qq" would both cross the budget at the column "variable" sets. Wherever alphabetize-siblings reorders a dict, it sets a blank line on either side of each entry spanning rows once two do, which would leave each expanded entry alone in a run of its own, and a dict already in order like this one holds to the same limit so the layout a reorder leaves stays put on the next run. reflow-collections therefore expands neither, and the two sets stay on their rows, aligned as a pair on the narrower column their own keys set, with "cache" above and "variable" below left unpadded.
alphabetize-siblings rewrites MUTATIONS in sorted order and drops the blank line above "pr", so "pr", "variable", and "xy" share one run. reflow-collections measures the "pr" set at the column "variable" sets in that run and expands it, whereas the blank line as written would have kept "pr" in a narrower run beside "xy", where the set fits on one row.
alphabetize-siblings sorts MUTATIONS, and the "cache" list already spans rows. Expanding the "pr" set as well would leave two entries spanning rows, and a sort that reorders a dict sets a blank line on either side of each once two do, which would put each expanded entry in a run of its own. reflow-collections therefore expands nothing, and since padding "pr" out to the column "cache" sets would carry its row past the budget, every row is left unpadded.
"pr" is the last entry as written, so it carries no comma, and its row lands exactly on the budget at the column "variable" sets. alphabetize-siblings moves it ahead of "variable", where it gains a comma that carries the row one column past the budget. reflow-collections reads the order and the comma the sort leaves, so it expands the "pr" set in the same pass rather than leaving align-colons a row it cannot pad.
At an 80-column budget, args's comprehension written across two rows overflows one row while its element calls "{}={!r}".format(name, value), whereas the f-string fits. reflow-collections measures the call at the width of f"{name}={value!r}" and rejoins the comprehension in the same pass that converts it.
The **SHARED unpacking stays transparent to the : run, so "cache", "pr", and "variable" share one column, whereas the blank line above "a" starts a run of its own. reflow-collections measures each value at the column align-colons shifts it to within its own run, so the "pr" set expands because its row crosses the budget at the column "variable" sets, while "a" and "bb" align on a narrower column beneath the blank line.
At a 50-column budget, the f-string prefer-fstring writes for "%s -> %s" % (alias, name) fits its row once the comprehension's (alias, name) target breaks open. The reflow-calls walk reads the operand tuple that rewrite replaces as holding its row, so it measures the template through the target's ( and leaves it for prefer-fstring, and reflow-collections expands the target rather than the operand, which lets the template convert in the same pass.
At a 38-column budget, "faultString"'s value wrap("%s" % (f(x),)) holds a template prefer-fstring rewrites as f"{f(x)}" inside the call, so the rewrite covers the argument rather than the whole value. reflow-collections hangs a value beneath its key only where a rewrite covers that value whole, so the entry stays beside "faultString": and wrap( explodes around the f-string, which a second pass leaves unchanged.
configure(...) carries a coords keyword whose tuple of three calls is too wide for one line. reflow-collections explodes the tuple and reflow-calls re-indents its elements under the keyword, alphabetize-siblings sorts more, name, and other, and align-equals pads each = into one column. coords keeps its source position, because its tuple calls functions such as compute_alpha_coordinate() and an entry whose value runs code is never moved, and the tuple's elements sit one indent step deeper than the keyword rows with its ) back at the keyword column, as a list or dict argument would.
With strip-stranded-padding off, the padding inside .format( type(exc), exc ) stays in the source and the row carrying it runs past the 73-column budget. reflow-calls measures the str.format() call at the width of the f-string prefer-fstring rewrites it as, whose row reaches the budget exactly, and leaves type(exc) unwalked, so type(exc) keeps its row and the call converts in one pass.
With strip-stranded-padding off, the padding inside ( type(exc), exc ) stays in the source and the row carrying it runs past the 79-column budget. reflow-calls measures the % template at the width of the f-string prefer-fstring rewrites it as rather than at its padded text, and leaves type(exc) unwalked, so the call keeps its row and the template converts in one pass.
At a 68-column budget, the f-string prefer-fstring writes for "%s:%s" % ( type(exc), exc ) still runs the row results.append( opens past the budget, so the call explodes and its dict lands on a row of its own. reflow-calls measures the template again from the column the dict lands at, where the f-string fits, and leaves type(exc) unwalked, so the template converts on that row in the same pass.
Padded to the column "bbbbbbbb" sets, the "a" row would cross the budget, so with every value on one row "a" stands unpadded above a column "bbbbbbbb", "cccccccccccccccccccc", and "ddddddddddddd" share. Expanding the list still leaves the dict in two columns, because "cccccccccccccccccccc" is 19 columns wider than "a", past the max-shift limit of 16. No row stands alone once the list expands, so reflow-collections expands it, "a" aligns with "bbbbbbbb", and the two wider keys align beneath them.
"python_version" would cross the budget padded to the column "platform_python_implementation" sets, and reflow-collections could explode its ".".join( call to join that column. Expanding it would still leave one row unpadded, because "sys_platform" is 18 columns narrower than "platform_python_implementation", past the max-shift limit of 16, just as "platform_python_implementation" stands unpadded while every value stays on one row. The call therefore stays on one row, and "python_version" and "sys_platform" align as a pair beneath the unpadded row.
The "pr" set in MUTATIONS fits the budget beside its own key, but padding the : of "pr" out to the column "variable" sets would carry the set six columns past it. reflow-collections measures the set at that padded column and expands it, so "pr" joins the column align-colons pads every other key out to rather than standing unpadded and splitting the run in two.
Pads the space before : so consecutive dict entries, annotated assignments, signature annotations, and docstring entries share one column, with a docstring entry's parenthesized type in a column of its own.
Pads the space before = so consecutive assignments, annotated parameter defaults, and an exploded call's keyword arguments share one column.
Sorts sibling entries whose order carries no meaning, covering import names, dict keys, class-body members, keyword arguments, and docstring entries.
Writes a function signature either on one line or one parameter per line, expanding it once it overflows code-line-length, passes max-params, or carries a parameter spanning rows.
Removes the trailing comma from a collection, signature, call, class base list, or type-parameter list, leaving tuples alone.