alphabetize-siblings
OrderingSorts sibling entries whose order carries no meaning, covering import names, dict keys, class-body members, keyword arguments, and docstring entries.
group-imports moves each import in a contiguous run into its canonical section, a from __future__ import ahead of everything, then the bare import statements, the external from … import … statements, and the local-package imports last:
| Section | Members |
|---|---|
__future__ | from __future__ import annotations |
| Bare | import os, import numpy as np |
External from | from collections import Counter |
| Local-package | relative imports and any package on the first-party list |
The rule moves imports into their sections and leaves the order within each to alphabetize-siblings, so the two agree on the grouping through one shared classifier. A run already in section order passes through with no edit.
An absolute from __future__ import … takes the leading section on its own, because Python rejects a module that places the statement below any other code, so the section is a compiler requirement rather than a legibility preference. A relative from .__future__ import … and a bare import __future__ name ordinary modules and classify as any other import does.
A from import is local when it is relative (from . import x, from ..pkg import y) or its module's root package appears on the first-party list. A bare import is local when the root package of any name it binds is first-party. Every other bare import stays bare, every other from import is external, and a statement that is no import at all stays where it sits and ends the run.
A recognized section marker (a hand-drawn banner like # --- Typing --- or a ## hash heading) divides a run into independent sections, so an author who grouped imports under a divider keeps that grouping and no import crosses the marker into the section above it. space-statements owns the single blank line between one canonical section and the next, reflow-imports runs afterward and splits a comma-joined statement so each module sits on its own line in its section, and align-imports reads the grouped result and aligns the import keyword within each section.
| Key | Type | Default | Meaning |
|---|---|---|---|
enabled | bool | true | Turns the rule on or off. |
group-imports is a single on/off toggle, and left on it moves every import run into the canonical sections. Turned off with group-imports = false, the imports read as one flat block and alphabetize-siblings sorts them together rather than within sections. The imports.first-party list under [imports] (see the configuration reference) names the packages that join the local-package section alongside relative imports.
A scrambled run mixes bare, external from, and local imports, with myapp named in first-party. group-imports partitions the run into bare, external from, and local sections in that order, so import sys and import os lead, from typing import Any and from collections import Counter follow, and from myapp import app and from . import shared close the run.
Within a section the statements keep their source order, so sys stays ahead of os, because sorting belongs to alphabetize-siblings and the blank line between sections to space-statements.
import sys
import os
from typing import Any
from collections import Counter
from myapp import app
from . import shared
The # --- Local --- comment sits between import sys and from . import shared. Each side of the banner partitions on its own and no import crosses it, so import sys moves above from collections import Counter in the upper section, and import os moves above from . import shared in the lower one rather than joining import sys.
Under if TYPE_CHECKING:, from collections import abc sits above import sys. group-imports moves the bare import sys above the from import in place, both lines keeping the arm's indent, because the rule reads the body of a compound statement the same way it reads the module.
The body of load opens with from collections import Counter above import sys. group-imports moves the bare import sys above the from import in place, both lines keeping the function-body indent, because the rule reads every nested body the same way it reads the module.
With myapp named in first-party, the run already reads bare imports, then the external from collections import Counter, then the first-party from myapp import app. group-imports emits no edit, because every statement already sits in its section and the rule rewrites only when a statement has to move.
import sys, os and import myapp.core, abc each name two modules in one statement, with myapp in first-party. reflow-imports splits each into one module per line ahead of group-imports and alphabetize-siblings, so every split-off module reaches its own group and its sorted position, and myapp.core ends up in the local section rather than beside the stdlib abc it was joined to.
Bare, external from, and local imports sit scrambled together, with myapp named in first-party. group-imports partitions them into bare, external, and local sections, alphabetize-siblings sorts the names within each section, space-statements writes one blank line between sections, and align-imports pads the import keyword into a column within each section.
Sorts sibling entries whose order carries no meaning, covering import names, dict keys, class-body members, keyword arguments, and docstring entries.
Pads the space before the import keyword across consecutive from imports, or before as across consecutive aliased imports, so the keywords share one column.
Splits a from … import … that overflows import-line-length into repeated-prefix statements, breaks a comma-joined import a, b into one statement per module, and merges repeated from statements of one module into one line.
Sets the blank-line count between module-level definitions, class members, import groups, and the __main__ guard to PEP 8's canonical values.
Reports an unaliased bare import reached through at most max-attributes distinct attributes, which a from x import … would replace.