alphabetize-siblings
OrderingSorts sibling entries whose order carries no meaning, covering import names, dict keys, class-body members, keyword arguments, and docstring entries.
bare-imports reports a bare import os that a from os import environ would serve better, because the module reads only a few names off the namespace and never uses the module object itself. The rule fires on an unaliased import reached through at least one and at most max-attributes distinct attributes (default 4), however many times each attribute repeats, and a from import then names each symbol in use directly. The finding recommends the explicit from package import name rewrite and leaves the rewrite itself to a later migration pass that reads the lint output. A namespace reached through many distinct attributes keeps its bare form, because the prefix then organizes a wide set of names a from import would scatter, and an aliased import is exempt while exempt-aliased stays on.
The rule counts the distinct attributes read off each imported namespace at module scope, and an attribute read inside a function or class body still resolves to the module-level binding and counts. A namespace used as the bare object (passed to a call, bound to another name) cannot collapse into a from import, so it passes whatever its attribute count, and an import inside a function sits outside the module scope the rule measures. An entry on the allow list keeps its bare form. When a migration pass acts on the lint output, the other import rules finish the job, in that alphabetize-siblings sorts the resulting block, align-imports pads the import keyword to one column, and space-statements sets the blank lines between groups. The lint never rewrites, so the diagnostic is reported and the source stays as written.
| Key | Type | Default | Meaning |
|---|---|---|---|
enabled | bool | true | Turns the rule on or off. |
allow | list of names | [] | Modules whose bare import form is kept whatever their attribute count. |
exempt-aliased | bool | true | Exempts every aliased bare import (import x as y) from the rule. |
max-attributes | positive int | 4 | The number of distinct attributes at or below which an unaliased bare import is reported. |
Two facets exempt an import from the report, whereas the third sets how wide a namespace the rule still reaches.
allow allow names the packages to leave alone, so allow = ["numpy"] keeps import numpy bare however many attributes the module reads off it. A dotted submodule inherits its parent's entry, so a numpy entry covers numpy.linalg too.
exempt-aliased exempt-aliased keeps an aliased import out of the report, since the np in import numpy as np is the namespace name the author chose. Setting it to false measures an aliased import on the same attribute count as a bare one, which suits a project where every import is to name its symbols.
max-attributes max-attributes sets the widest namespace the rule still reports, defaulting to 4, so an import reached through more distinct attributes than that keeps its bare form. Lowering it leaves only the narrowest imports reported, and raising it reaches wider ones.
import os is reached only through os.environ, one distinct attribute however many times it repeats, and import torch is reached through five distinct attributes. The os import is reported and the torch import is not, because a from os import environ rewrite would cover every use of os, whereas torch fans out past the default max-attributes of 4, where the bare namespace keeps a wide set of names organized.
import os
import torch
os.environ["HOME"]
os.environ["PATH"]
torch.tensor(torch.zeros(3))
torch.nn.Linear(8, 8)
torch.optim.Adam
torch.cuda.is_available()
import os is reached only through os.getcwd, so bare-imports reports the import. The source text passes through exactly as written, because a lint diagnostic is a report rather than a rewrite, and the rule emits no fix.
import numpy and import torch are each reached through a single attribute, and the case runs with allow = ["numpy"]. Only torch is reported, because a package on the allow list keeps its bare form as one the project keeps on purpose.
import os is reached through five distinct attributes, os.getcwd through os.path, one past the default max-attributes of 4, and the case runs with max-attributes = 6. The import line is reported, because the higher limit takes in the five-attribute fan-out that the default leaves unreported.
import os sits between # fmt: off and # fmt: on, and os.getcwd is its only attribute use, the narrow use the lint reports. No diagnostic is reported, because a suppressed block covers lint diagnostics as well as rewrites, so the finding at the import line is dropped.
import os as o binds the module under an alias the author chose. No diagnostic is reported, whatever the attribute count, because exempt-aliased is on by default and an alias is the author's chosen namespace handle rather than a leftover bare import.
register(os) passes the module object itself, and os.getcwd is the only attribute use of the import. No diagnostic is reported, because a namespace used as the bare object cannot collapse into a from os import ... rewrite, since the caller needs the module rather than a symbol from it.
import os is reached through five distinct attributes, os.getcwd through os.path, one past the default max-attributes of 4. No diagnostic is reported, because a from os import ... rewrite would have to name all five symbols, and at that width the bare namespace import is the more legible form.
import sys, import os, and import json arrive out of order, and each module is used once below through a single attribute, os.getcwd(), sys.argv, and json.loads. alphabetize-siblings sorts the statements so json leads, and bare-imports reports all three, each finding landing on the import's row in the sorted output, so json is reported on row 1 and sys on row 3.
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.
Sets the blank-line count between module-level definitions, class members, import groups, and the __main__ guard to PEP 8's canonical values.
For per-line opt-outs, the Suppression chapter covers the # prose: ignore[bare-imports] directive.