Fix: Update snapshots and code

This commit is contained in:
Chandra Kiran G 2025-11-03 15:17:44 +05:30
parent 82675083eb
commit e73b3a52b6
3 changed files with 190 additions and 35 deletions

View File

@ -4,20 +4,20 @@ use anyhow::Result;
use ruff_python_ast::name::Name; use ruff_python_ast::name::Name;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use ruff_diagnostics::{Applicability, Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_diagnostics::{Applicability, Edit, Fix};
use ruff_macros::{derive_message_formats, ViolationMetadata}; use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{ use ruff_python_ast::{
self as ast, Expr, ExprBinOp, ExprContext, ExprName, ExprSubscript, LiteralExpressionRef, self as ast, Expr, ExprBinOp, ExprContext, ExprName, ExprSubscript, LiteralExpressionRef,
Operator, Operator,
}; };
use ruff_python_semantic::analyze::typing::traverse_union;
use ruff_python_semantic::SemanticModel; use ruff_python_semantic::SemanticModel;
use ruff_python_semantic::analyze::typing::traverse_union;
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
use crate::Violation;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
use crate::fix::snippet::SourceCodeSnippet; use crate::fix::snippet::SourceCodeSnippet;
use crate::importer::ImportRequest; use crate::importer::ImportRequest;
use crate::{FixAvailability, Violation};
/// ## What it does /// ## What it does
/// Checks for redundant unions between a `Literal` and a builtin supertype of /// Checks for redundant unions between a `Literal` and a builtin supertype of
@ -141,7 +141,7 @@ pub(crate) fn redundant_literal_union<'a>(checker: &Checker, union: &'a Expr) {
return; return;
}; };
let mut diagnostics = Vec::new(); let mut diagnostics: Vec<(RedundantLiteralUnion, TextRange)> = Vec::new();
let mut non_redundant_literal_types = Vec::new(); let mut non_redundant_literal_types = Vec::new();
for typing_literal_expr in typing_literal_exprs { for typing_literal_expr in typing_literal_exprs {
@ -150,7 +150,7 @@ pub(crate) fn redundant_literal_union<'a>(checker: &Checker, union: &'a Expr) {
}; };
if builtin_types_in_union.contains(&literal_type) { if builtin_types_in_union.contains(&literal_type) {
diagnostics.push(Diagnostic::new( diagnostics.push((
RedundantLiteralUnion { RedundantLiteralUnion {
literal: SourceCodeSnippet::from_str( literal: SourceCodeSnippet::from_str(
checker.locator().slice(typing_literal_expr), checker.locator().slice(typing_literal_expr),
@ -165,8 +165,10 @@ pub(crate) fn redundant_literal_union<'a>(checker: &Checker, union: &'a Expr) {
} }
} }
if checker.settings.preview.is_disabled() { if checker.settings().preview.is_disabled() {
checker.report_diagnostics(diagnostics); for (kind, range) in diagnostics {
let _ = checker.report_diagnostic(kind, range);
}
return; return;
} }
@ -212,11 +214,13 @@ pub(crate) fn redundant_literal_union<'a>(checker: &Checker, union: &'a Expr) {
} }
LiteralExprType::NonRedundantTypes(group) => { LiteralExprType::NonRedundantTypes(group) => {
let new_literal_expr = Expr::Subscript(ast::ExprSubscript { let new_literal_expr = Expr::Subscript(ast::ExprSubscript {
node_index: Default::default(),
value: Box::new(literal_subscript.clone()), value: Box::new(literal_subscript.clone()),
range: TextRange::default(), range: TextRange::default(),
ctx: ExprContext::Load, ctx: ExprContext::Load,
slice: Box::new(if group.len() > 1 { slice: Box::new(if group.len() > 1 {
Expr::Tuple(ast::ExprTuple { Expr::Tuple(ast::ExprTuple {
node_index: Default::default(),
elts: group.into_iter().cloned().collect(), elts: group.into_iter().cloned().collect(),
range: TextRange::default(), range: TextRange::default(),
ctx: ExprContext::Load, ctx: ExprContext::Load,
@ -240,23 +244,26 @@ pub(crate) fn redundant_literal_union<'a>(checker: &Checker, union: &'a Expr) {
Applicability::Safe Applicability::Safe
}; };
for diagnostic in &mut diagnostics { for (kind, range) in diagnostics {
let mut diagnostic = checker.report_diagnostic(kind, range);
match union_kind { match union_kind {
UnionKind::PEP604 => diagnostic.try_set_optional_fix(|| { UnionKind::PEP604 => {
diagnostic.try_set_optional_fix(|| -> anyhow::Result<Option<Fix>> {
Ok(generate_pep604_fix( Ok(generate_pep604_fix(
checker, checker,
&new_exprs, &new_exprs,
union, union,
applicability, applicability,
)) ))
}), });
UnionKind::TypingUnion => diagnostic.try_set_optional_fix(|| { }
UnionKind::TypingUnion => {
diagnostic.try_set_optional_fix(|| -> anyhow::Result<Option<Fix>> {
generate_typing_union_fix(checker, &new_exprs, union, applicability) generate_typing_union_fix(checker, &new_exprs, union, applicability)
}), });
}
} }
} }
checker.report_diagnostics(diagnostics);
} }
fn generate_pep604_fix( fn generate_pep604_fix(
@ -275,6 +282,7 @@ fn generate_pep604_fix(
let new_expr = new_exprs.iter().fold(None, |acc, right| { let new_expr = new_exprs.iter().fold(None, |acc, right| {
if let Some(left) = acc { if let Some(left) = acc {
Some(Expr::BinOp(ExprBinOp { Some(Expr::BinOp(ExprBinOp {
node_index: Default::default(),
left: Box::new(left), left: Box::new(left),
op: Operator::BitOr, op: Operator::BitOr,
right: Box::new(right.clone()), right: Box::new(right.clone()),
@ -305,14 +313,17 @@ fn generate_typing_union_fix(
// Construct the expression as `Subscript[typing.Union, Tuple[expr, [expr, ...]]]` // Construct the expression as `Subscript[typing.Union, Tuple[expr, [expr, ...]]]`
let new_expr = Expr::Subscript(ExprSubscript { let new_expr = Expr::Subscript(ExprSubscript {
node_index: Default::default(),
range: TextRange::default(), range: TextRange::default(),
value: Box::new(Expr::Name(ExprName { value: Box::new(Expr::Name(ExprName {
node_index: Default::default(),
id: Name::new(binding), id: Name::new(binding),
ctx: ExprContext::Store, ctx: ExprContext::Store,
range: TextRange::default(), range: TextRange::default(),
})), })),
slice: Box::new(if new_exprs.len() > 1 { slice: Box::new(if new_exprs.len() > 1 {
Expr::Tuple(ast::ExprTuple { Expr::Tuple(ast::ExprTuple {
node_index: Default::default(),
elts: new_exprs.to_vec(), elts: new_exprs.to_vec(),
range: TextRange::default(), range: TextRange::default(),
ctx: ExprContext::Load, ctx: ExprContext::Load,

View File

@ -11,7 +11,7 @@ PYI051 `Literal["foo"]` is redundant in a union with `str`
5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str] 5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str]
6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] 6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]]
| |
= help: Replace `Literal["foo"] | str` with `str` help: Replace `Literal["foo"] | str` with `str`
PYI051 `Literal[b"bar"]` is redundant in a union with `bytes` PYI051 `Literal[b"bar"]` is redundant in a union with `bytes`
--> PYI051.py:5:37 --> PYI051.py:5:37
@ -22,7 +22,7 @@ PYI051 `Literal[b"bar"]` is redundant in a union with `bytes`
6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] 6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]]
7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] 7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int]
| |
= help: Replace `typing.Union[Literal[b"bar"], bytes]` with `bytes` help: Replace `typing.Union[Literal[b"bar"], bytes]` with `bytes`
PYI051 `Literal[b"foo"]` is redundant in a union with `bytes` PYI051 `Literal[b"foo"]` is redundant in a union with `bytes`
--> PYI051.py:5:45 --> PYI051.py:5:45
@ -33,7 +33,7 @@ PYI051 `Literal[b"foo"]` is redundant in a union with `bytes`
6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]] 6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]]
7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] 7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int]
| |
= help: Replace `typing.Union[Literal[b"foo"], bytes]` with `bytes` help: Replace `typing.Union[Literal[b"foo"], bytes]` with `bytes`
PYI051 `Literal[5]` is redundant in a union with `int` PYI051 `Literal[5]` is redundant in a union with `int`
--> PYI051.py:6:37 --> PYI051.py:6:37
@ -45,7 +45,7 @@ PYI051 `Literal[5]` is redundant in a union with `int`
7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] 7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int]
8 | E: TypeAlias = typing.Union[typing.Union[typing.Union[typing.Union[Literal["foo"], str]]]] 8 | E: TypeAlias = typing.Union[typing.Union[typing.Union[typing.Union[Literal["foo"], str]]]]
| |
= help: Replace `typing.Union[Literal[5], int]` with `int` help: Replace `typing.Union[Literal[5], int]` with `int`
PYI051 `Literal["foo"]` is redundant in a union with `str` PYI051 `Literal["foo"]` is redundant in a union with `str`
--> PYI051.py:6:67 --> PYI051.py:6:67
@ -57,7 +57,7 @@ PYI051 `Literal["foo"]` is redundant in a union with `str`
7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int] 7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int]
8 | E: TypeAlias = typing.Union[typing.Union[typing.Union[typing.Union[Literal["foo"], str]]]] 8 | E: TypeAlias = typing.Union[typing.Union[typing.Union[typing.Union[Literal["foo"], str]]]]
| |
= help: Replace `typing.Union[Literal["foo"], str]` with `str` help: Replace `typing.Union[Literal["foo"], str]` with `str`
PYI051 `Literal[b"str_bytes"]` is redundant in a union with `bytes` PYI051 `Literal[b"str_bytes"]` is redundant in a union with `bytes`
--> PYI051.py:7:37 --> PYI051.py:7:37
@ -69,7 +69,7 @@ PYI051 `Literal[b"str_bytes"]` is redundant in a union with `bytes`
8 | E: TypeAlias = typing.Union[typing.Union[typing.Union[typing.Union[Literal["foo"], str]]]] 8 | E: TypeAlias = typing.Union[typing.Union[typing.Union[typing.Union[Literal["foo"], str]]]]
9 | F: TypeAlias = typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]] 9 | F: TypeAlias = typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]]
| |
= help: Replace `typing.Union[Literal[b"str_bytes"], bytes]` with `bytes` help: Replace `typing.Union[Literal[b"str_bytes"], bytes]` with `bytes`
PYI051 `Literal[42]` is redundant in a union with `int` PYI051 `Literal[42]` is redundant in a union with `int`
--> PYI051.py:7:51 --> PYI051.py:7:51
@ -81,7 +81,7 @@ PYI051 `Literal[42]` is redundant in a union with `int`
8 | E: TypeAlias = typing.Union[typing.Union[typing.Union[typing.Union[Literal["foo"], str]]]] 8 | E: TypeAlias = typing.Union[typing.Union[typing.Union[typing.Union[Literal["foo"], str]]]]
9 | F: TypeAlias = typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]] 9 | F: TypeAlias = typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]]
| |
= help: Replace `typing.Union[Literal[42], int]` with `int` help: Replace `typing.Union[Literal[42], int]` with `int`
PYI051 `Literal["foo"]` is redundant in a union with `str` PYI051 `Literal["foo"]` is redundant in a union with `str`
--> PYI051.py:8:76 --> PYI051.py:8:76
@ -93,7 +93,7 @@ PYI051 `Literal["foo"]` is redundant in a union with `str`
9 | F: TypeAlias = typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]] 9 | F: TypeAlias = typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]]
10 | G: typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]] 10 | G: typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]]
| |
= help: Replace `typing.Union[Literal["foo"], str]` with `str` help: Replace `typing.Union[Literal["foo"], str]` with `str`
PYI051 `Literal["foo"]` is redundant in a union with `str` PYI051 `Literal["foo"]` is redundant in a union with `str`
--> PYI051.py:9:81 --> PYI051.py:9:81
@ -104,7 +104,7 @@ PYI051 `Literal["foo"]` is redundant in a union with `str`
| ^^^^^ | ^^^^^
10 | G: typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]] 10 | G: typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]]
| |
= help: Replace `typing.Union[Literal["foo"], str]` with `str` help: Replace `typing.Union[Literal["foo"], str]` with `str`
PYI051 `Literal["foo"]` is redundant in a union with `str` PYI051 `Literal["foo"]` is redundant in a union with `str`
--> PYI051.py:10:69 --> PYI051.py:10:69
@ -116,7 +116,7 @@ PYI051 `Literal["foo"]` is redundant in a union with `str`
11 | 11 |
12 | def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ... 12 | def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ...
| |
= help: Replace `typing.Union[Literal["foo"], str]` with `str` help: Replace `typing.Union[Literal["foo"], str]` with `str`
PYI051 `Literal[1J]` is redundant in a union with `complex` PYI051 `Literal[1J]` is redundant in a union with `complex`
--> PYI051.py:12:31 --> PYI051.py:12:31
@ -128,7 +128,7 @@ PYI051 `Literal[1J]` is redundant in a union with `complex`
13 | 13 |
14 | # OK 14 | # OK
| |
= help: Replace `Literal[1J] | complex` with `complex` help: Replace `Literal[1J] | complex` with `complex`
PYI051 `Literal[3.14]` is redundant in a union with `float` PYI051 `Literal[3.14]` is redundant in a union with `float`
--> PYI051.py:12:53 --> PYI051.py:12:53
@ -140,4 +140,4 @@ PYI051 `Literal[3.14]` is redundant in a union with `float`
13 | 13 |
14 | # OK 14 | # OK
| |
= help: Replace `typing.Union[Literal[3.14], float]` with `float` help: Replace `typing.Union[Literal[3.14], float]` with `float`

View File

@ -0,0 +1,144 @@
---
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
assertion_line: 137
---
PYI051 `Literal["foo"]` is redundant in a union with `str`
--> PYI051.pyi:4:18
|
2 | from typing import Literal, TypeAlias, Union
3 |
4 | A: str | Literal["foo"]
| ^^^^^
5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str]
6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]]
|
help: Replace `Literal["foo"] | str` with `str`
PYI051 `Literal[b"bar"]` is redundant in a union with `bytes`
--> PYI051.pyi:5:37
|
4 | A: str | Literal["foo"]
5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str]
| ^^^^^^
6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]]
7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int]
|
help: Replace `typing.Union[Literal[b"bar"], bytes]` with `bytes`
PYI051 `Literal[b"foo"]` is redundant in a union with `bytes`
--> PYI051.pyi:5:45
|
4 | A: str | Literal["foo"]
5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str]
| ^^^^^^
6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]]
7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int]
|
help: Replace `typing.Union[Literal[b"foo"], bytes]` with `bytes`
PYI051 `Literal[5]` is redundant in a union with `int`
--> PYI051.pyi:6:37
|
4 | A: str | Literal["foo"]
5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str]
6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]]
| ^
7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int]
8 | E: TypeAlias = typing.Union[typing.Union[typing.Union[typing.Union[Literal["foo"], str]]]]
|
help: Replace `typing.Union[Literal[5], int]` with `int`
PYI051 `Literal["foo"]` is redundant in a union with `str`
--> PYI051.pyi:6:67
|
4 | A: str | Literal["foo"]
5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str]
6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]]
| ^^^^^
7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int]
8 | E: TypeAlias = typing.Union[typing.Union[typing.Union[typing.Union[Literal["foo"], str]]]]
|
help: Replace `typing.Union[Literal["foo"], str]` with `str`
PYI051 `Literal[b"str_bytes"]` is redundant in a union with `bytes`
--> PYI051.pyi:7:37
|
5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str]
6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]]
7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int]
| ^^^^^^^^^^^^
8 | E: TypeAlias = typing.Union[typing.Union[typing.Union[typing.Union[Literal["foo"], str]]]]
9 | F: TypeAlias = typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]]
|
help: Replace `typing.Union[Literal[b"str_bytes"], bytes]` with `bytes`
PYI051 `Literal[42]` is redundant in a union with `int`
--> PYI051.pyi:7:51
|
5 | B: TypeAlias = typing.Union[Literal[b"bar", b"foo"], bytes, str]
6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]]
7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int]
| ^^
8 | E: TypeAlias = typing.Union[typing.Union[typing.Union[typing.Union[Literal["foo"], str]]]]
9 | F: TypeAlias = typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]]
|
help: Replace `typing.Union[Literal[42], int]` with `int`
PYI051 `Literal["foo"]` is redundant in a union with `str`
--> PYI051.pyi:8:76
|
6 | C: TypeAlias = typing.Union[Literal[5], int, typing.Union[Literal["foo"], str]]
7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int]
8 | E: TypeAlias = typing.Union[typing.Union[typing.Union[typing.Union[Literal["foo"], str]]]]
| ^^^^^
9 | F: TypeAlias = typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]]
10 | G: typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]]
|
help: Replace `typing.Union[Literal["foo"], str]` with `str`
PYI051 `Literal["foo"]` is redundant in a union with `str`
--> PYI051.pyi:9:81
|
7 | D: TypeAlias = typing.Union[Literal[b"str_bytes", 42], bytes, int]
8 | E: TypeAlias = typing.Union[typing.Union[typing.Union[typing.Union[Literal["foo"], str]]]]
9 | F: TypeAlias = typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]]
| ^^^^^
10 | G: typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]]
|
help: Replace `typing.Union[Literal["foo"], str]` with `str`
PYI051 `Literal["foo"]` is redundant in a union with `str`
--> PYI051.pyi:10:69
|
8 | E: TypeAlias = typing.Union[typing.Union[typing.Union[typing.Union[Literal["foo"], str]]]]
9 | F: TypeAlias = typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]]
10 | G: typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]]
| ^^^^^
11 |
12 | def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ...
|
help: Replace `typing.Union[Literal["foo"], str]` with `str`
PYI051 `Literal[1J]` is redundant in a union with `complex`
--> PYI051.pyi:12:31
|
10 | G: typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]]
11 |
12 | def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ...
| ^^
13 |
14 | # OK
|
help: Replace `Literal[1J] | complex` with `complex`
PYI051 `Literal[3.14]` is redundant in a union with `float`
--> PYI051.pyi:12:53
|
10 | G: typing.Union[str, typing.Union[typing.Union[typing.Union[Literal["foo"], int]]]]
11 |
12 | def func(x: complex | Literal[1J], y: Union[Literal[3.14], float]): ...
| ^^^^
13 |
14 | # OK
|
help: Replace `typing.Union[Literal[3.14], float]` with `float`