Python¶
Files ending in .py are formatted by the Python pack
(rainbow_fmt.languages.python, grammar
tree-sitter-python).
The defaults follow PEP 8 and Black's main rules; byte-identical Black
output is not a goal, and where users differ there is an option.
import os
def connect(host,port = 5432,*,timeout=None) :
result=open_connection(host_name_argument, port_number_argument, timeout_value)
return result
becomes
import os
def connect(host, port=5432, *, timeout=None):
result = open_connection(
host_name_argument, port_number_argument, timeout_value
)
return result
What changes and what does not¶
The pack changes layout only. Strings (prefixes, quotes, escapes, f-string contents, the lines of multi-line strings and docstrings), numbers and comment texts are printed as written, and parentheses are never added or removed.
- Indentation comes from the tree (
core.indent_style,core.indent_size);elif,else,except,finallyandcaseare aligned with their statement. - Spacing within a line: one space around binary, comparison, boolean
and assignment operators,
->,:=, and after commas and colons; none inside brackets, before the(/[of calls and subscripts, around., after unary operators and*/**unpacking, or around the=of keyword arguments and unannotated defaults (def f(a: int = 1, b=2)).**hugs simple operands (x**2, butx ** f(y)). Slice colons get spaces only when an operand is complex, and not on an omitted side (a[1:2],a[x + 1 :]). - Brackets (calls, parameters, collections, subscripts, parenthesized
expressions and imports,
with (…), type parameters, patterns) are printed flat if they fit. Otherwise a collection (list, set, dict, tuple, parenthesized import list) goes one item per line; the other brackets first try their items on one indented line:
result = some_function_name(
argument_number_one, argument_number_two, argument_3
)
data = {
"key": [1, 2, 3],
"other": {"nested": True, "list": [4, 5, 6]},
"more": 1,
}
One item per line gets a trailing comma (shared.trailing_comma, whose
default is "multiline" for Python). The last bracket of a line breaks
first (x = a.query(y).filter( …).
- Inside brackets, an item that still does not fit breaks at the
operators of its lowest-precedence level (all at once; or before
and), before the for/if of a comprehension, before the if/else
of a conditional expression, and between the parts of an implicit
string concatenation. Outside brackets nothing breaks, so a long line
without brackets stays long.
- Blank lines: none at the start of the file or of a block; around
definitions see definition_blank_lines.
- Comments: a comment after code stays on its line, after
inline_comment_spaces spaces; a comment on its own line is indented to
its block (the tree decides: a comment before else at the if level
belongs to the if). A comment inside brackets stays with its item
(after the comma) and forces the brackets to break.
- One-liners and semicolons are kept (if x: pass, a = 1; b = 2),
with normalized spacing.
- Inline directives (# rainbow: off, # fmt: off, # fmt: skip,
# rainbow: set …) keep statements as written or change options for one
statement (configuration.md).
- Backslash continuations: a statement with one (for a compound
statement, its header up to the colon) is printed as written, apart from
the indentation of its first line.
Options¶
| Key | Values | Default |
|---|---|---|
language.python.bracket_wrap |
"magic_trailing_comma": a trailing comma in the source keeps the items one per line (not the comma of a 1-tuple or a subscript); "fit": trailing commas do not force a break and are removed when a list is joined; "preserve": a line break between two items keeps them one per line, a line break only after the opening bracket keeps the brackets broken |
"magic_trailing_comma" |
language.python.binary_operator_break |
"before" or "after" the operators of a broken expression (PEP 8 recommends before) |
"before" |
language.python.definition_blank_lines |
"enforce": exactly top_level_blank_lines around top-level def/class (comments directly above belong to the definition) and nested_blank_lines around nested ones; "cap": those counts are maxima; "preserve": at most core.max_blank_lines |
"enforce" |
language.python.top_level_blank_lines |
integer >= 0; also the maximum between other top-level statements | 2 |
language.python.nested_blank_lines |
integer >= 0 | 1 |
language.python.inline_comment_spaces |
integer >= 1 | 2 |
language.python.statement_blank_lines |
"preserve": as written; "separate": in a function body, a blank line before and after a for/while loop, after an if statement, and before an if that follows another if or a loop (never removed: at most max_blank_lines; comment lines directly above a statement move with it) |
"preserve" |
language.python.docstrings |
"preserve": as written; "aligned": the summary on the opening line, the closing """ on a line of its own, the lines after the summary aligned three columns in (under its first letter), keeping their relative indentation |
"preserve" |
language.python.bracket_hug |
true: a list, tuple or set whose items are all non-empty dicts hugs them ([{ … }, { … }]) when it does not fit on one line |
false |
shared.trailing_comma |
"never", "multiline" |
"multiline" for Python |
With bracket_wrap = "magic_trailing_comma" and trailing_comma =
"never", no commas are added, but a trailing comma in the source is kept:
it is what keeps the list broken. Inside blocks, blank lines between
statements other than definitions are limited by core.max_blank_lines.
Limitations¶
- No
.pyistubs yet, no quote or number normalization, no comment normalization (#xstays), no docstring re-indentation. - Parentheses are never added, so
return, assignment right-hand sides andifconditions without brackets are not broken (Black adds parentheses to break them). - Black breaks the parameters rather than a subscript in a return annotation; rainbow-fmt breaks the last bracket.
- The grammar (tree-sitter-python 0.25) does not parse PEP 696 type
parameter defaults (
class C[T = int], Python 3.13); such files are reported as syntax errors and left unchanged.