Skip to content

unsorted-positionals

Alphabetical order gives a reader the same landmarks in a positional run that

gives them everywhere else. Prose will not reorder the run for you, though, 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. reports the out-of-order run instead, leaving the reorder to a hand that can weigh the callers.

Two constructs carry such a run, the first being a function's positional-or-keyword parameters, free function and method alike, since 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 under a positional-binding decorator (pytest.mark.parametrize, click.argument, and the like) draws nothing, since the decorator may hand 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 is non-rewriting, so the diagnostic surfaces without touching the source.

Configuration

KeyTypeDefaultMeaning
enabledbooltrueToggles the rule on or off.

The target order puts the required names alphabetized ahead of the defaulted names alphabetized, rather than plain alphabetical throughout. Python permits nothing else, in that a required field following a defaulted one raises TypeError: non-default argument 'zebra' follows default argument 'alpha' the moment the class 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 is always behavior-preserving, and

sorts it as an auto-fix rather than reporting it here.

The Canonical Case

A module-level function whose positional-or-keyword parameters sit out of alphabetical order draws a report-only diagnostic. The rule never reorders them, because doing so would rebind every positional call site, so it points the reorder out and leaves the call where the author can weigh the callers.

def merge(target, source, fallback=None):
    return target
python

More Examples

A ClassVar drops out of the run without ending it, so zebra and apple still read as one out-of-order pair and draw a diagnostic. The report spans the run first field to last, carrying the ClassVar line along with it even though that constant is no constructor parameter.

A NamedTuple base generates the positional constructor a @dataclass decorator does, so its out-of-order field run draws the same report. Sorting display ahead of build here would leave ModelSpec("Baseline", BaselineAE) binding the type where the label belongs.

A method inside a generated-constructor class drops out of the field run rather than counting against it, so the run covers width and height alone. The method's own parameters are a positional run in their own right, leaving the class with two diagnostics that name different constructs.

A @dataclass whose annotated fields sit out of order draws a report-only diagnostic across the run. The decorator turns those fields into the constructor's positional parameters, so Window(1920, 1080) binds them in source order and a reorder would transpose every such call. The defaulted title sorts after the required pair, which is the only order Python permits.

A class-body method with out-of-order parameters draws the diagnostic a free function draws. Its callers bind by slot exactly as a free function's do, so the run reads the same way, with the self receiver dropping out rather than silencing the check.

No Change

Neither the ClassVar constant nor the KW_ONLY sentinel becomes a constructor parameter, so both drop out of the run rather than counting against it. What remains before the sentinel is alpha, beta, already in order, and the zulu, yankee pair below it binds by name, leaving the class without a diagnostic.

No Change

A generator carrying a literal kw_only=True binds every field by name, so the out-of-order run draws no diagnostic. Nothing here needs a human's read of the callers, in that

sorts these fields as an auto-fix.

No Change

A class whose header names no constructor generator binds no field by position, so the out-of-order run draws no diagnostic.

sorts these fields by name as an auto-fix instead.

No Change

A function under a decorator that binds arguments by position (click.argument here) draws no diagnostic. The decorator may hand values to the parameters by slot, so the lint treats the order as load-bearing and stays silent.

For per-line opt-outs, the Suppression chapter covers the # prose: ignore[unsorted-positionals] directive.