miscased-constants
LintSurfaces a module-level constant whose name is not SCREAMING_CASE.
A SCREAMING_CASE name promises a constant, so a module-level one that is reassigned contradicts its own casing.
SCREAMING_CASE binding only when it is reassigned (an assignment_count above one or an augmented assignment recorded against the name), leaving a write-once constant silent whatever its value. The fix renames the variable to lowercase or stops reassigning it, work the lint leaves to a future migration pass that picks up its output.The rule weighs module-level SCREAMING_CASE assignments and annotated assignments, firing only on the reassigned ones. Names on the configurable allow list stay quiet. Dunder-style names (__version__, __all__) fall outside SCREAMING_CASE because they lead with an underscore. Typing constructs from the standard library (TypeVar, ParamSpec, NewType, TypeAliasType) and any binding declared inside an if TYPE_CHECKING: block also stay quiet, since both carry their own semantics distinct from runtime configuration. In-place mutation through a method call or a subscript store stays out of scope, since the binding table records those as reads. The lint is non-rewriting, so the diagnostic surfaces without touching the source.
| Key | Type | Default | Meaning |
|---|---|---|---|
enabled | bool | true | Toggles the rule on or off. |
allow | list of names | [] | Module-level names exempted from the lint. |
The allow list holds bare names, so an entry never produces a lint even when its shape would otherwise match.
A SCREAMING_CASE name reassigned at module scope breaks the immutability its casing promises, so each write surfaces the lint where a write-once constant stays silent.
RETRIES = 3
RETRIES = 5
A reassigned SCREAMING_CASE annotated assignment draws the diagnostic whether or not a value follows the annotation. The bare FLAG: bool and the valued MAX: int = 1 shapes both feed the annotated-assignment path ahead of the reassignment gate.
A name listed in [tool.prose.rules.reassigned-constants].allow passes through silently even when reassigned, so a blessed LOG_LEVEL publishes at the module root where an unlisted CACHE_DIR reassignment still draws the diagnostic.
A # fmt: off block carries the same suppression weight against lint diagnostics as against edits, so a reassigned constant inside the block escapes the rule's emission path entirely.
T is SCREAMING_CASE and the module writes it twice, so the reassignment gate alone would flag it. The TypeVar constructor read is the only thing sparing it, which is the shape the carve-out exists for.
A clean file with only an allowed __version__ dunder passes through unchanged on every pass, pinning the lint-only shape where the rule emits no edits and no diagnostic.
Chained assignment (A = B = 1), tuple unpacking (A, B = 1, 2), and attribute targets (FOO.bar = 1) all fall outside the single-target name shape the rule flags, so each line passes through silently.
The attribute-qualified typing.TYPE_CHECKING guard skips its block exactly as the bare TYPE_CHECKING name does, so a constant inside draws no diagnostic.
Dunder names such as __version__, __all__, and __author__ are module-level by convention, so the rule leaves them untouched and emits no diagnostic for any of them.
A SCREAMING_CASE name assigned exactly once is a genuine constant, so the rule stays silent whatever its value shape.
Surfaces a module-level constant whose name is not SCREAMING_CASE.
Surfaces single-use local bindings that could inline cleanly.
Surfaces comments that narrate the next line.
For per-line opt-outs, the Suppression chapter covers the # prose: ignore[reassigned-constants] directive.