collection-layout
FormattingProse splits list, tuple, dict, and set literals into one-entry-per-line layout once they overflow their width, or a dict crosses an entry-count cap.
A trailing comma on the last entry of a multi-line collection adds a small visual hiccup at every block boundary without earning its keep. Each entry already has its own line, so a new entry adds a new line of its own, which leaves the trailing comma on the previous last entry with no diff-stability win to bring.
removes the trailing comma from any bracketed container that carries one, and it leaves tuples alone because Python uses the trailing comma to disambiguate single-element tuples from parenthesized expressions.The rule walks every bracketed container (dictionaries, lists, sets, function signatures, function calls, class bases, parenthesized argument lists) and strips the comma after the last entry when one is present. Whether the container spans one line or many doesn't affect the strip itself, since single-line atomic collections happen not to carry trailing commas in idiomatic Python and the rule rarely fires on them. Pair with
for the multi-line expansion that brings the trailing comma into reach in the first place.| Key | Type | Default | Meaning |
|---|---|---|---|
enabled | bool | true | Toggle the rule on or off |
The strip is unconditional within the contexts named above, so the rule carries enabled as its only knob. Tuple literals are exempt by construction because Python uses the trailing comma to disambiguate single-element tuples from parenthesized expressions, leaving no project-level switch to flip on the tuple carve-out.
A multi-line dict literal loses its trailing comma after the strip.
config = {
"linkage": "ward",
"metric": "euclidean",
"n_clusters": None,
"threshold": 0.7
}
A multi-line class base list shares the same argument shape as a call, so the , after the final base is stripped. The backward scan from before the closing ) lands on that comma, treating bases exactly as it treats call arguments.
A multi-line call whose argument list covers (...) loses the , after its last argument. The backward scan from before the closing ) finds that comma and deletes it, so the call reads without a dangling separator.
A multi-line function signature whose parameter list covers (...) loses the , after its last parameter. The backward scan from before the closing ) lands on that comma, treating the signature like any other argument list.
A multi-line list literal spanning [...] drops the , after its last element. The backward scan from before the closing ] lands on that comma, applying the identical path that strips dict values.
An outer call wrapping an inner dict and an inner list each carry a trailing ,. Every container emits its own separate deletion edit, and the edits do not interact across nesting levels.
Each argument carries its own parenthesized expression, so an inner ) sits between the expression and the trailing ,. The scan reads from the call's outer ) and reaches the comma directly, never needing to step over the inner paren.
A container that already ends without a trailing , round-trips untouched. The backward scan reaches the last element rather than a comma and emits no edit, so clean source is left exactly as written.
Prose splits list, tuple, dict, and set literals into one-entry-per-line layout once they overflow their width, or a dict crosses an entry-count cap.
Prose aligns the : separator across dict literals, Args: blocks.
For per-line opt-outs (projects that prefer the trailing comma for diff stability even on multi-line forms), Suppression covers the # fmt: off / # fmt: on block markers.