Skip to content

align-comparisons โ€‹

A multi-line boolean chain (and or or) of comparison operands reads as a small table where the operator anchors the relationship between left and right. When each operator sits at a different column the eye walks across each line individually, treating the chain as five sentences rather than one parallel structure.

gathers the operator column into a shared one, so every comparator's last character lands on the same offset and the chain reads top to bottom as a single judgment.

The rule walks each BoolOp whose operands are all Expr::Compare. The widest operand's left side fixes the shared column, with variable-width operators (==, <=, is not) right-aligning so the operator's last character sits in the shared column. A chained compare (0 < x < 100) anchors on its first operator only. A non-comparison operand, a multi-line operand, or a blank line in the gap breaks the run.

Configuration โ€‹

KeyTypeDefaultMeaning
enabledbooltrueToggle the rule on or off
max-shiftpositive int8Ceiling on per-line padding
max-shift-policy"split" | "drop""split"How to handle a group whose widest member exceeds max-shift. See the per-rule knobs for the full semantics

max-shift caps the per-line padding the alignment can introduce, and max-shift-policy resolves the fallback when a group's widest operand would push the operator column past the cap. The per-rule knobs reference covers the "split" / "drop" semantics.

The Canonical Case โ€‹

Three single-comparator == operands in a multi-line and-chain share an alignment column. The operator at each row sits one space past the widest operand's left side.

python
if (
    foo         == 1
    and bar_baz == 2
    and quux    == 3
):
    pass

More Examples โ€‹

A blank line between two qualifying operands breaks the alignment run, so the operators on either side of the gap no longer share a column.

A chained compare such as 0 < bar < 100 anchors on its first operator. The remaining operators stay in place and take no part in the column math, while the surrounding single-comparator rows align around it.

An operand whose own range spans multiple source lines breaks the run. The parenthesized (1 + 2) operand pushes its neighbors out of column, leaving the trailing rows to align among themselves.

A comment on its own line between two operands pushes them onto non-adjacent source lines, so the line-distance check breaks the run regardless of comment content. The rows below the divider still align among themselves.

A call expression on the left side qualifies for the group like any other operand. The call's display width, len(b), counts as the left-hand side that the operator column pads against.

Identity and membership operators join the same aligned group as == and <. The wider is not and not in widen the operator column, and every other operator's last character lands at the shared right edge.

== operands and < operands share one aligned group. The variable-width operators right-align, so the second = of == and the < land in the same column.

Operands across an or chain align with the same column math the rule applies to and chains. The == of each row settles one space past the widest operand's left side.

No Change

An and-chain whose == already sit one space past the widest left side is idempotent under the rule. No edit is emitted and the group passes through unchanged.