[flake8-pyi] Expand Optional[A] to A | None (PYI016) (#18572)
Some checks are pending
CI / cargo fuzz build (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run

## Summary
Under preview 🧪 I've expanded rule `PYI016` to also flag type
union duplicates containing `None` and `Optional`.

## Test Plan
Examples/tests have been added. I've made sure that the existing
examples did not change unless preview is enabled.

## Relevant Issues
* https://github.com/astral-sh/ruff/issues/18508 (discussing
introducing/extending a rule to flag `Optional[None]`)
* https://github.com/astral-sh/ruff/issues/18546 (where I discussed this
addition with @AlexWaygood)

---------

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
This commit is contained in:
Robsdedude 2025-06-27 15:43:11 +00:00 committed by GitHub
parent 96f3c8d1ab
commit 6802c4702f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 2747 additions and 25 deletions

View file

@ -1604,7 +1604,7 @@ impl<'a> SemanticModel<'a> {
let mut parent_expressions = self.current_expressions().skip(1);
match parent_expressions.next() {
// The parent expression is of the inner union is a single `typing.Union`.
// The parent expression of the inner union is a single `typing.Union`.
// Ex) `Union[Union[a, b]]`
Some(Expr::Subscript(parent)) => self.match_typing_expr(&parent.value, "Union"),
// The parent expression is of the inner union is a tuple with two or more
@ -1624,6 +1624,18 @@ impl<'a> SemanticModel<'a> {
}
}
/// Return `true` if the model is directly inside an Optional (e.g., the inner `Union` in
/// `Optional[Union[int, str]]`).
pub fn inside_optional(&self) -> bool {
let mut parent_expressions = self.current_expressions().skip(1);
matches!(
parent_expressions.next(),
// The parent expression is a single `typing.Optional`.
// Ex) `Optional[EXPR]`
Some(Expr::Subscript(parent)) if self.match_typing_expr(&parent.value, "Optional")
)
}
/// Return `true` if the model is in a nested literal expression (e.g., the inner `Literal` in
/// `Literal[Literal[int, str], float]`).
pub fn in_nested_literal(&self) -> bool {