alphabetize-siblings
OrderingSorts sibling entries whose order carries no meaning, covering import names, dict keys, class-body members, keyword arguments, and docstring entries.
unsorted-positionals reports a run of positionally-bound names that sits out of alphabetical order and leaves the reorder to a hand that can check the callers. Alphabetical order gives a reader the same landmarks in a positional run that alphabetize-siblings gives everywhere else, yet Prose never reorders the run, because each name's slot is part of the call contract. Every positional call binds by slot, and a single-file formatter cannot see the callers in other modules, in frameworks, or behind dynamic dispatch, so moving a name would silently rebind them.
Two constructs carry such a run, and the first is a function's positional-or-keyword parameters, free function and method alike, because a method's callers bind by slot exactly as a free function's do. The second is the annotated field run of a class whose header generates a positional constructor, where a NamedTuple base or a @dataclass decorator turns the fields into that constructor's parameters and a call like Window(1920, 1080) binds them in source order.
A function whose decorator is a call carrying positional arguments (pytest.mark.parametrize(...), click.argument(...), and the like) draws no report, because the decorator may bind values to the parameters by slot. A name that binds no positional slot drops from the run rather than silencing it, covering the self and cls receivers, the positional-only parameters before the /, a ClassVar declaration, and the dataclasses.KW_ONLY sentinel. 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. |
The target order puts the required names in alphabetical order ahead of the defaulted names in alphabetical order, rather than plain alphabetical order throughout, because Python permits nothing else. A required field after a defaulted one raises TypeError: non-default argument 'zebra' follows default argument 'alpha' the moment the dataclass is created.
The keyword-only block past the * is a separate matter, along with the fields below a KW_ONLY sentinel and those of a kw_only=True generator. Each binds by name at every call site, so reordering it always preserves behavior, and alphabetize-siblings sorts it as an auto-fix rather than reporting it here.
merge(target, source, fallback=None) lists its parameters out of alphabetical order. The lint reports the run and leaves the source as written, because reordering would rebind every call site that passes arguments by position, so the fix is left to a reader who can check the callers.
def merge(target, source, fallback=None):
return target
Palette is a @dataclass declaring zebra, then DEFAULT: ClassVar[str], then apple. The lint reports one run spanning zebra through apple, because the ClassVar binds no constructor parameter and drops out of the run without ending it, so zebra and apple still read as one out-of-order pair and the reported span carries the DEFAULT line between them.
ModelSpec(NamedTuple) declares display then build, and the lint reports the field run, because a NamedTuple base generates the same positional constructor a @dataclass decorator does, so moving build ahead of display would leave a call like ModelSpec("Baseline", BaselineAE) binding the type where the label belongs.
Report is a @dataclass declaring width then height, and its render method takes target, source. The lint reports two runs, one on the fields and one on the method's parameter list, because the fields feed the generated constructor as one positional run that the method ends rather than joins, and the method's own parameters form a second run that is also out of order.
Window is a @dataclass declaring width, then height, then title: str = "untitled". The lint reports the field run and leaves it in place, because @dataclass turns the annotated fields into the generated constructor's positional parameters, so a reorder would transpose the values at every call like Window(1920, 1080). The order the lint checks against places the required height and width ahead of the defaulted title, since Python permits no required field after a defaulted one.
Catalog.update(self, target, source) lists target before source. The lint reports the run exactly as it would for a free function, because a method's callers bind by slot the same way, and the self receiver drops out of the run rather than silencing it.
Session is a @dataclass declaring REGISTRY: ClassVar[dict], then alpha and beta, then a _: KW_ONLY sentinel, then zulu and yankee. The lint reports nothing, because neither the ClassVar nor the sentinel binds a constructor parameter, so both drop out of the run rather than counting against it, alpha, beta before the sentinel is already in order, and zulu, yankee below it binds by name.
Request is a @dataclass(kw_only=True) declaring timeout, then method, then body out of alphabetical order. The lint reports nothing, because a keyword-only generator binds every field by name at each call site, so no reader needs to check the callers, and sorting such fields is alphabetize-siblings's auto-fix rather than this lint's.
run(target, source) sits under @click.argument("path"), a decorator called with a positional argument, and lists its parameters out of alphabetical order. The lint reports nothing, because such a decorator may bind values to the parameters by slot, so a reorder would change which value each parameter receives.
Endpoint is a plain class declaring timeout then method. The lint reports nothing, because the header names no constructor generator, so no field binds by position, and sorting such fields by name is alphabetize-siblings's auto-fix rather than this lint's.
Sorts sibling entries whose order carries no meaning, covering import names, dict keys, class-body members, keyword arguments, and docstring entries.
For per-line opt-outs, the Suppression chapter covers the # prose: ignore[unsorted-positionals] directive.