unused-future-annotations
FormattingRemoves from __future__ import annotations lines that no longer carry their weight on the target Python version.
Union[X, Y] and Optional[X] come from the typing module, were the canonical union shapes for years, and still read clearly today. On Python 3.10 and later, the PEP 604 pipe-union shapes (X | Y, X | None) read more directly and consume one fewer import, which over the course of a large codebase adds up to genuinely clearer type signatures.
The rule fires only on projects whose target-version is 3.10 or higher, where the pipe-union shapes are runtime-supported. Pre-3.10 projects and projects with target-version unset stay quiet, since recommending the pipe form on those projects would mislead. The lint is non-rewriting, so the diagnostic surfaces without touching the source.
The rule fires, with Optional[X] reading as X | None in the diagnostic message.
| Key | Type | Default | Meaning |
|---|---|---|---|
enabled | bool | true | Toggles the rule on or off. |
The target-version field from the top-level Configuration gates the lint per project.
A from typing import Optional followed by Optional[X] surfaces the lint, recommending X | None.
from typing import Optional
x: Optional[int] = None
from typing import Optional as Opt binds Opt to typing.Optional, so Opt[int] resolves through the alias and flags the same as the bare name.
A legacy Optional[int] nested as the value type of dict[str, Optional[int]] is flagged on the inner expression. The enclosing subscript, rather than the statement, is passed as the parent for the parenthesized range.
Parentheses wrapping a subscript, as in (Optional[int]), are folded into the diagnostic range, so the surfaced span matches the author's mental model of the whole annotation.
The rule emits no edits, so every pass leaves the source byte-for-byte identical. A mix of legacy Optional[int] and Union[int, str] bindings alongside a modern int | None form all pass through as written.
After import typing, the annotation typing.Optional[int] resolves through the attribute chain back to typing.Optional and flags identically to the bare Optional[int] form.
Modern PEP 604 annotations written with | are never flagged. The walker inspects only Subscript shapes, so the binary BitOr expression backing int | None slips past entirely.
A typing import naming something other than Optional or Union is not flagged. The walker resolves List[int] to typing.List and falls through the suffix match's catch-all.
Removes from __future__ import annotations lines that no longer carry their weight on the target Python version.
For per-line opt-outs, the Suppression chapter covers the # prose: ignore[legacy-union-syntax] directive.