align-colons
AlignmentProse aligns the : separator across dict literals, Args: blocks.
A reader who already knows the codebase carries a mental map of where things live. When sibling members within a class, an enum, a dataclass, or a function call sit in arrival order, every reader builds a different map, which slows each new reader's first read.
gives everyone the same landmarks:| Surface | Order |
|---|---|
| Classes in a module | Alphabetical |
| Module-level constants | Leading and trailing bands, each by dependency tier |
| Methods in a class | Dunders, properties, private, public |
| Enum members | Alphabetical |
| Dataclass and Pydantic fields | Required before optional |
| Parameters and keyword arguments | Alphabetical |
| Imports | Canonical groups, alphabetical within each |
| Docstring entries | Alphabetical within each Title-case section |
The rule fires on siblings whose order does not carry meaning. It leaves alone every surface where ordering is load-bearing (positional-only parameters before the / separator, enum members with explicit integer or string values, tuple-unpacking targets bound to positional results).
A class or function definition also holds its place behind any sibling it names at evaluation time (a base class, a decorator, a parameter default, a non-deferred annotation, or a class-body value), since sorting it ahead of that sibling would move the name out of scope and raise NameError on import. A run whose references form a cycle stays in source order untouched.
At module scope, a constant lifts out of arrival order into a band. One whose value reaches only imports, builtins, literals, or fellow leading constants rides a leading band directly below the imports, and one that names a function or class pools into a trailing band beneath the definitions, so a module reads as its imports, its leading constants, its definitions, then the constants derived from them. Each band alphabetizes within its dependency tier, and a constant a function reads only inside its body still hoists above it, because only an eval-time reference (a right-hand side, a decorator, a default argument, a base class, a non-deferred annotation) binds the order. A constant the rule cannot place safely (a reassigned name, an unresolved reference, a line a suppression directive or a # prose: keep marker covers) pins where the author left it.
When a function's parameters reorder,
rewrites each in-module call's positional arguments to keyword form, keyed to the parameter each bound to under the original order, so the reorder never silently rebinds a caller. Calls that forward*args, unpack **, or reach the function through a reassigned name stay as they read.Pair with
to align theimport keyword across the freshly-sorted block, with to align dataclass-field annotations after the sort, and with for the blank-line discipline around class members and the single blank line between the import groups.| Key | Type | Default | Meaning |
|---|---|---|---|
enabled | bool | true | Toggle the rule on or off |
The ordering itself follows fixed per-construct conventions. Method groups follow the dunders-properties-privates-publics rhythm. Pydantic fields follow required-then-optional. Consecutive imports group into their canonical order (bare first, then external from, then local-package), sorted within each group, with the imports.first-party list under [imports] (see the configuration reference) naming the packages that lift into the local-package group alongside relative imports. Set alphabetize = { docstring-entries = false } to skip the docstring-entry reorder while keeping every AST-level surface sorted.
Classes inside a module sort alphabetically, giving every reader the same first-pass landmarks.
class Alpha:
pass
class Beta:
pass
class Gamma:
pass
The string-literal items inside __all__ alphabetize by string value. Detection keys on the target's simple name, because the dunder-list convention is what makes the list documentary, leaving ordinary list assignments untouched.
The string-literal items inside __slots__ alphabetize by string value, matching __all__. The tuple form parses identically through the rule's list-or-tuple branch.
A trailing # prose: keep comment on the opening { line preserves source order for that single dict. The unmarked sibling alphabetizes and partitions through the same machinery, so the contrast lands side by side from identical scrambled input.
A constant whose value touches only literals rides the leading band directly below the imports, hoisting above a function that reads it inside its body, because a body reference defers to call time and constrains no order.
A constant calling a function that reaches a class through a default argument pools beneath both the function and the class, since the call's eval-time surface threads CONFIG past build and the Widget its default names.
A constant naming a make it names, because evaluating its right-hand side reaches that definition at once.
Arguments /) cannot take keyword form, so they stay verbatim while the keyword-eligible suffix rewrites to name=value. Positional-only parameters never reorder, leaving the pinned prefix binding correctly.
The Args: section's name: description entries reorder alphabetically by parameter name, matching how the rule treats the function signature itself.
Async compound shapes (async def, async for, async with) recurse identically to their synchronous counterparts. Each arm's imports flow through the same compound-statement recursion, so the is_async flag changes nothing about how the body sorts.
Every bare import statement at a body's top level collapses into a single alphabetized block. Blank lines the user wrote between imports are removed, so the form reads as one paragraph regardless of source arrangement.
Configured first-party imports lift into the local-package myapp imports join relative imports as local-package, bare before from, while unrelated packages stay in the bare and external from groups.
A custom Title-case heading whose body carries name: description entries reorders alphabetically by name, the same as the canonical Google headings. The heading shape qualifies the section, not its name.
A @dataclass-decorated class has its annotated fields alphabetized by
Three pytest.mark.parametrize, hypothesis.given, and click.argument. Functions carrying any of them keep their parameter order intact.
Multi-line dict literals partition entries by rendered line count. Single-line entries sort first, then a blank divider, then multi-line entries. **unpacked items pin in source position, and the partition fires recursively at every level of nesting.
StrEnum qualifies the same way Enum and IntEnum do.
A reordered function resolved through BindingAnalysis rewrites each of its in-module call sites independently, every positional argument keyed to its original parameter.
Fields whose default arrives through Annotated[type, Field(default=...)] or Annotated[type, Field(default_factory=...)] register as optional. A structural walk finds the nested Call carrying a default or default_factory keyword, covering
Every from-import statement at a body's top level collapses into a single alphabetized block. Blank lines the user wrote between imports are removed, so the form reads as one paragraph regardless of source arrangement.
Function parameters alphabetize within two sub-groups: required (no default) before optional (has default). self and cls pin first in method lists. The
A scrambled block of bare, external from, and relative imports reorders into the canonical bare โ external from โ local-package grouping, sorting within each
Keyword arguments at call sites alphabetize within splat-bounded segments. A **kwargs splat carries no arg name and acts as a hard partition, so named kwargs never cross it. The
A class body whose statements live inside if / else arms sorts each arm under class
A three-tier dependency chain reorders within each tier without crossing tier boundaries. RADIUS is tier 0, DIAMETER is tier 1, and AREA is tier 2, so two tier-0 constants swap relative to source while staying above tier 1.
A # fmt: off block. Assigns above the block sort within their run, the
A NamedTuple body has its annotated fields alphabetized with required-then-optional. Default-bearing fields land last per Python's positional-default invariant, which the required-then-optional split already enforces.
When alphabetize reorders a function's parameters, every in-module call's positional arguments rewrite to name=value, each keyed to the parameter that argument bound to under the original order, so the call binds the same values whatever order the parameters now sit in. The keyword run lands alphabetized, leaving the rewritten call a fixed point.
Set-literal elements alphabetize because Python sets are mathematically unordered. The sort key is each element's source text, so mixed-type sets sort by representation. Star unpacks (*defaults) pin in their source slot to preserve the visual blend.
Reordering a multi-line dict keeps every entry's trailing # comment, with the separator , placed after the value and before the comment. Values carrying their own #, such as hex color strings, stay intact because the comma resolves against the value span rather than a raw # scan.
A TypedDict body has its annotated fields alphabetized. Detection runs against the class T(TypedDict) and a hand-rolled annotated class would both fire identically.
A Raises: entry whose description carries an indented code block keeps the verbatim block attached to its parent through the reorder. The block sits beneath the entry's hanging column, so the walker reads it as a continuation rather than a sibling.
Alpha names Beta as a base class, so the alphabetical sort holds Beta
ahead of Alpha instead of moving the subclass above the name it inherits,
leaving the module import-safe.
Any Call on a
Prose aligns the : separator across dict literals, Args: blocks.
Prose aligns the import and as keywords across consecutive import statements.
Prose surfaces a narrowly-used bare import that from x import โฆ would replace.
Prose normalizes