mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-28 23:38:00 +00:00
[flake8-pyi]: More autofixes for redundant-none-literal (PYI061) (#14872)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
This commit is contained in:
parent
68e8496260
commit
e5cb4d6388
3 changed files with 204 additions and 35 deletions
|
|
@ -1,15 +1,14 @@
|
||||||
use ruff_diagnostics::{Applicability, Diagnostic, Edit, Fix, FixAvailability, Violation};
|
use ruff_diagnostics::{Applicability, Diagnostic, Edit, Fix, FixAvailability, Violation};
|
||||||
use ruff_macros::{derive_message_formats, ViolationMetadata};
|
use ruff_macros::{derive_message_formats, ViolationMetadata};
|
||||||
use ruff_python_ast::{Expr, ExprBinOp, ExprNoneLiteral, ExprSubscript, Operator};
|
use ruff_python_ast::{
|
||||||
use ruff_python_semantic::{
|
self as ast, Expr, ExprBinOp, ExprContext, ExprNoneLiteral, ExprSubscript, Operator,
|
||||||
analyze::typing::{traverse_literal, traverse_union},
|
|
||||||
SemanticModel,
|
|
||||||
};
|
};
|
||||||
use ruff_text_size::Ranged;
|
use ruff_python_semantic::analyze::typing::{traverse_literal, traverse_union};
|
||||||
|
use ruff_text_size::{Ranged, TextRange};
|
||||||
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::{checkers::ast::Checker, settings::types::PythonVersion};
|
||||||
|
|
||||||
/// ## What it does
|
/// ## What it does
|
||||||
/// Checks for redundant `Literal[None]` annotations.
|
/// Checks for redundant `Literal[None]` annotations.
|
||||||
|
|
@ -34,9 +33,14 @@ use crate::checkers::ast::Checker;
|
||||||
/// Literal[1, 2, 3, "foo", 5] | None
|
/// Literal[1, 2, 3, "foo", 5] | None
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ## Fix safety
|
/// ## Fix safety and availability
|
||||||
/// This rule's fix is marked as safe unless the literal contains comments.
|
/// This rule's fix is marked as safe unless the literal contains comments.
|
||||||
///
|
///
|
||||||
|
/// There is currently no fix available if there are other elements in the `Literal` slice aside
|
||||||
|
/// from `None` and [`target-version`] is set to Python 3.9 or lower, as the fix always uses the
|
||||||
|
/// `|` syntax to create unions rather than `typing.Union`, and the `|` syntax for unions was added
|
||||||
|
/// in Python 3.10.
|
||||||
|
///
|
||||||
/// ## References
|
/// ## References
|
||||||
/// - [Typing documentation: Legal parameters for `Literal` at type check time](https://typing.readthedocs.io/en/latest/spec/literal.html#legal-parameters-for-literal-at-type-check-time)
|
/// - [Typing documentation: Legal parameters for `Literal` at type check time](https://typing.readthedocs.io/en/latest/spec/literal.html#legal-parameters-for-literal-at-type-check-time)
|
||||||
#[derive(ViolationMetadata)]
|
#[derive(ViolationMetadata)]
|
||||||
|
|
@ -65,35 +69,44 @@ impl Violation for RedundantNoneLiteral {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RUF037
|
/// PYI061
|
||||||
pub(crate) fn redundant_none_literal<'a>(checker: &mut Checker, literal_expr: &'a Expr) {
|
pub(crate) fn redundant_none_literal<'a>(checker: &mut Checker, literal_expr: &'a Expr) {
|
||||||
if !checker.semantic().seen_typing() {
|
let semantic = checker.semantic();
|
||||||
|
|
||||||
|
if !semantic.seen_typing() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut none_exprs: SmallVec<[&ExprNoneLiteral; 1]> = SmallVec::new();
|
let Expr::Subscript(ast::ExprSubscript {
|
||||||
let mut other_literal_elements_seen = false;
|
value: literal_subscript,
|
||||||
|
..
|
||||||
|
}) = literal_expr
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
let mut find_none = |expr: &'a Expr, _parent: &'a Expr| {
|
let mut none_exprs: SmallVec<[&ExprNoneLiteral; 1]> = SmallVec::new();
|
||||||
|
let mut literal_elements = vec![];
|
||||||
|
|
||||||
|
let mut partition_literal_elements = |expr: &'a Expr, _parent: &'a Expr| {
|
||||||
if let Expr::NoneLiteral(none_expr) = expr {
|
if let Expr::NoneLiteral(none_expr) = expr {
|
||||||
none_exprs.push(none_expr);
|
none_exprs.push(none_expr);
|
||||||
} else {
|
} else {
|
||||||
other_literal_elements_seen = true;
|
literal_elements.push(expr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
traverse_literal(&mut find_none, checker.semantic(), literal_expr);
|
traverse_literal(&mut partition_literal_elements, semantic, literal_expr);
|
||||||
|
|
||||||
if none_exprs.is_empty() {
|
if none_exprs.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide a [`Fix`] when the complete `Literal` can be replaced. Applying the fix
|
let other_literal_elements_seen = !literal_elements.is_empty();
|
||||||
// can leave an unused import to be fixed by the `unused-import` rule.
|
|
||||||
let fix = if other_literal_elements_seen {
|
// N.B. Applying the fix can leave an unused import to be fixed by the `unused-import` rule.
|
||||||
None
|
let fix =
|
||||||
} else {
|
create_fix_edit(checker, literal_expr, literal_subscript, literal_elements).map(|edit| {
|
||||||
create_fix_edit(checker.semantic(), literal_expr).map(|edit| {
|
|
||||||
Fix::applicable_edit(
|
Fix::applicable_edit(
|
||||||
edit,
|
edit,
|
||||||
if checker.comment_ranges().intersects(literal_expr.range()) {
|
if checker.comment_ranges().intersects(literal_expr.range()) {
|
||||||
|
|
@ -102,8 +115,7 @@ pub(crate) fn redundant_none_literal<'a>(checker: &mut Checker, literal_expr: &'
|
||||||
Applicability::Safe
|
Applicability::Safe
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
});
|
||||||
};
|
|
||||||
|
|
||||||
for none_expr in none_exprs {
|
for none_expr in none_exprs {
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic = Diagnostic::new(
|
||||||
|
|
@ -128,7 +140,14 @@ pub(crate) fn redundant_none_literal<'a>(checker: &mut Checker, literal_expr: &'
|
||||||
/// See <https://github.com/astral-sh/ruff/issues/14567>.
|
/// See <https://github.com/astral-sh/ruff/issues/14567>.
|
||||||
///
|
///
|
||||||
/// [`typing.Union`]: https://docs.python.org/3/library/typing.html#typing.Union
|
/// [`typing.Union`]: https://docs.python.org/3/library/typing.html#typing.Union
|
||||||
fn create_fix_edit(semantic: &SemanticModel, literal_expr: &Expr) -> Option<Edit> {
|
fn create_fix_edit(
|
||||||
|
checker: &Checker,
|
||||||
|
literal_expr: &Expr,
|
||||||
|
literal_subscript: &Expr,
|
||||||
|
literal_elements: Vec<&Expr>,
|
||||||
|
) -> Option<Edit> {
|
||||||
|
let semantic = checker.semantic();
|
||||||
|
|
||||||
let enclosing_pep604_union = semantic
|
let enclosing_pep604_union = semantic
|
||||||
.current_expressions()
|
.current_expressions()
|
||||||
.skip(1)
|
.skip(1)
|
||||||
|
|
@ -143,8 +162,9 @@ fn create_fix_edit(semantic: &SemanticModel, literal_expr: &Expr) -> Option<Edit
|
||||||
})
|
})
|
||||||
.last();
|
.last();
|
||||||
|
|
||||||
let mut is_fixable = true;
|
|
||||||
if let Some(enclosing_pep604_union) = enclosing_pep604_union {
|
if let Some(enclosing_pep604_union) = enclosing_pep604_union {
|
||||||
|
let mut is_fixable = true;
|
||||||
|
|
||||||
traverse_union(
|
traverse_union(
|
||||||
&mut |expr, _| {
|
&mut |expr, _| {
|
||||||
if matches!(expr, Expr::NoneLiteral(_)) {
|
if matches!(expr, Expr::NoneLiteral(_)) {
|
||||||
|
|
@ -163,7 +183,46 @@ fn create_fix_edit(semantic: &SemanticModel, literal_expr: &Expr) -> Option<Edit
|
||||||
semantic,
|
semantic,
|
||||||
enclosing_pep604_union,
|
enclosing_pep604_union,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if !is_fixable {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is_fixable.then(|| Edit::range_replacement("None".to_string(), literal_expr.range()))
|
if literal_elements.is_empty() {
|
||||||
|
return Some(Edit::range_replacement(
|
||||||
|
"None".to_string(),
|
||||||
|
literal_expr.range(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if checker.settings.target_version < PythonVersion::Py310 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let bin_or = Expr::BinOp(ExprBinOp {
|
||||||
|
range: TextRange::default(),
|
||||||
|
left: Box::new(Expr::Subscript(ast::ExprSubscript {
|
||||||
|
value: Box::new(literal_subscript.clone()),
|
||||||
|
range: TextRange::default(),
|
||||||
|
ctx: ExprContext::Load,
|
||||||
|
slice: Box::new(if literal_elements.len() > 1 {
|
||||||
|
Expr::Tuple(ast::ExprTuple {
|
||||||
|
elts: literal_elements.into_iter().cloned().collect(),
|
||||||
|
range: TextRange::default(),
|
||||||
|
ctx: ExprContext::Load,
|
||||||
|
parenthesized: true,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
literal_elements[0].clone()
|
||||||
|
}),
|
||||||
|
})),
|
||||||
|
op: ruff_python_ast::Operator::BitOr,
|
||||||
|
right: Box::new(Expr::NoneLiteral(ExprNoneLiteral {
|
||||||
|
range: TextRange::default(),
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
||||||
|
let content = checker.generator().expr(&bin_or);
|
||||||
|
Some(Edit::range_replacement(content, literal_expr.range()))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
|
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
|
||||||
|
snapshot_kind: text
|
||||||
---
|
---
|
||||||
PYI061.py:4:25: PYI061 [*] `Literal[None]` can be replaced with `None`
|
PYI061.py:4:25: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
|
||||||
|
|
@ -55,7 +56,7 @@ PYI061.py:12:24: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
14 14 |
|
14 14 |
|
||||||
15 15 |
|
15 15 |
|
||||||
|
|
||||||
PYI061.py:16:30: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
PYI061.py:16:30: PYI061 [*] `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
|
||||||
16 | def func4(arg1: Literal[int, None, float]):
|
16 | def func4(arg1: Literal[int, None, float]):
|
||||||
| ^^^^ PYI061
|
| ^^^^ PYI061
|
||||||
|
|
@ -63,6 +64,16 @@ PYI061.py:16:30: PYI061 `Literal[None, ...]` can be replaced with `Literal[...]
|
||||||
|
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
= help: Replace with `Literal[...] | None`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
13 13 | ...
|
||||||
|
14 14 |
|
||||||
|
15 15 |
|
||||||
|
16 |-def func4(arg1: Literal[int, None, float]):
|
||||||
|
16 |+def func4(arg1: Literal[int, float] | None):
|
||||||
|
17 17 | ...
|
||||||
|
18 18 |
|
||||||
|
19 19 |
|
||||||
|
|
||||||
PYI061.py:20:25: PYI061 [*] `Literal[None]` can be replaced with `None`
|
PYI061.py:20:25: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
|
||||||
20 | def func5(arg1: Literal[None, None]):
|
20 | def func5(arg1: Literal[None, None]):
|
||||||
|
|
@ -99,7 +110,7 @@ PYI061.py:20:31: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
22 22 |
|
22 22 |
|
||||||
23 23 |
|
23 23 |
|
||||||
|
|
||||||
PYI061.py:26:5: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
PYI061.py:26:5: PYI061 [*] `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
|
||||||
24 | def func6(arg1: Literal[
|
24 | def func6(arg1: Literal[
|
||||||
25 | "hello",
|
25 | "hello",
|
||||||
|
|
@ -110,6 +121,20 @@ PYI061.py:26:5: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] |
|
||||||
|
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
= help: Replace with `Literal[...] | None`
|
||||||
|
|
||||||
|
ℹ Unsafe fix
|
||||||
|
21 21 | ...
|
||||||
|
22 22 |
|
||||||
|
23 23 |
|
||||||
|
24 |-def func6(arg1: Literal[
|
||||||
|
25 |- "hello",
|
||||||
|
26 |- None # Comment 1
|
||||||
|
27 |- , "world"
|
||||||
|
28 |- ]):
|
||||||
|
24 |+def func6(arg1: Literal["hello", "world"] | None):
|
||||||
|
29 25 | ...
|
||||||
|
30 26 |
|
||||||
|
31 27 |
|
||||||
|
|
||||||
PYI061.py:33:5: PYI061 [*] `Literal[None]` can be replaced with `None`
|
PYI061.py:33:5: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
|
||||||
32 | def func7(arg1: Literal[
|
32 | def func7(arg1: Literal[
|
||||||
|
|
@ -177,7 +202,7 @@ PYI061.py:52:9: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
54 54 |
|
54 54 |
|
||||||
55 55 | ###
|
55 55 | ###
|
||||||
|
|
||||||
PYI061.py:53:15: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
PYI061.py:53:15: PYI061 [*] `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
|
||||||
51 | # From flake8-pyi
|
51 | # From flake8-pyi
|
||||||
52 | Literal[None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
52 | Literal[None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
|
@ -188,6 +213,16 @@ PYI061.py:53:15: PYI061 `Literal[None, ...]` can be replaced with `Literal[...]
|
||||||
|
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
= help: Replace with `Literal[...] | None`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
50 50 |
|
||||||
|
51 51 | # From flake8-pyi
|
||||||
|
52 52 | Literal[None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
53 |-Literal[True, None] # Y061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
||||||
|
53 |+Literal[True] | None # Y061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
||||||
|
54 54 |
|
||||||
|
55 55 | ###
|
||||||
|
56 56 | # The following rules here are slightly subtle,
|
||||||
|
|
||||||
PYI061.py:62:9: PYI061 [*] `Literal[None]` can be replaced with `None`
|
PYI061.py:62:9: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
|
||||||
60 | # If Y061 and Y062 both apply, but all the duplicate members are None,
|
60 | # If Y061 and Y062 both apply, but all the duplicate members are None,
|
||||||
|
|
@ -228,7 +263,7 @@ PYI061.py:62:15: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
64 64 |
|
64 64 |
|
||||||
65 65 | # ... but if Y061 and Y062 both apply
|
65 65 | # ... but if Y061 and Y062 both apply
|
||||||
|
|
||||||
PYI061.py:63:12: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
PYI061.py:63:12: PYI061 [*] `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
|
||||||
61 | # only emit Y061...
|
61 | # only emit Y061...
|
||||||
62 | Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
62 | Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
|
@ -239,7 +274,17 @@ PYI061.py:63:12: PYI061 `Literal[None, ...]` can be replaced with `Literal[...]
|
||||||
|
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
= help: Replace with `Literal[...] | None`
|
||||||
|
|
||||||
PYI061.py:63:25: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
ℹ Safe fix
|
||||||
|
60 60 | # If Y061 and Y062 both apply, but all the duplicate members are None,
|
||||||
|
61 61 | # only emit Y061...
|
||||||
|
62 62 | Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
63 |-Literal[1, None, "foo", None] # Y061 None inside "Literal[]" expression. Replace with "Literal[1, 'foo'] | None"
|
||||||
|
63 |+Literal[1, "foo"] | None # Y061 None inside "Literal[]" expression. Replace with "Literal[1, 'foo'] | None"
|
||||||
|
64 64 |
|
||||||
|
65 65 | # ... but if Y061 and Y062 both apply
|
||||||
|
66 66 | # and there are no None members in the Literal[] slice,
|
||||||
|
|
||||||
|
PYI061.py:63:25: PYI061 [*] `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
|
||||||
61 | # only emit Y061...
|
61 | # only emit Y061...
|
||||||
62 | Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
62 | Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
|
@ -250,7 +295,17 @@ PYI061.py:63:25: PYI061 `Literal[None, ...]` can be replaced with `Literal[...]
|
||||||
|
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
= help: Replace with `Literal[...] | None`
|
||||||
|
|
||||||
PYI061.py:68:9: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
ℹ Safe fix
|
||||||
|
60 60 | # If Y061 and Y062 both apply, but all the duplicate members are None,
|
||||||
|
61 61 | # only emit Y061...
|
||||||
|
62 62 | Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
63 |-Literal[1, None, "foo", None] # Y061 None inside "Literal[]" expression. Replace with "Literal[1, 'foo'] | None"
|
||||||
|
63 |+Literal[1, "foo"] | None # Y061 None inside "Literal[]" expression. Replace with "Literal[1, 'foo'] | None"
|
||||||
|
64 64 |
|
||||||
|
65 65 | # ... but if Y061 and Y062 both apply
|
||||||
|
66 66 | # and there are no None members in the Literal[] slice,
|
||||||
|
|
||||||
|
PYI061.py:68:9: PYI061 [*] `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
|
||||||
66 | # and there are no None members in the Literal[] slice,
|
66 | # and there are no None members in the Literal[] slice,
|
||||||
67 | # only emit Y062:
|
67 | # only emit Y062:
|
||||||
|
|
@ -259,7 +314,17 @@ PYI061.py:68:9: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] |
|
||||||
|
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
= help: Replace with `Literal[...] | None`
|
||||||
|
|
||||||
PYI061.py:68:21: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
ℹ Safe fix
|
||||||
|
65 65 | # ... but if Y061 and Y062 both apply
|
||||||
|
66 66 | # and there are no None members in the Literal[] slice,
|
||||||
|
67 67 | # only emit Y062:
|
||||||
|
68 |-Literal[None, True, None, True] # Y062 Duplicate "Literal[]" member "True"
|
||||||
|
68 |+Literal[True, True] | None # Y062 Duplicate "Literal[]" member "True"
|
||||||
|
69 69 |
|
||||||
|
70 70 |
|
||||||
|
71 71 | # Regression tests for https://github.com/astral-sh/ruff/issues/14567
|
||||||
|
|
||||||
|
PYI061.py:68:21: PYI061 [*] `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
|
||||||
66 | # and there are no None members in the Literal[] slice,
|
66 | # and there are no None members in the Literal[] slice,
|
||||||
67 | # only emit Y062:
|
67 | # only emit Y062:
|
||||||
|
|
@ -268,6 +333,16 @@ PYI061.py:68:21: PYI061 `Literal[None, ...]` can be replaced with `Literal[...]
|
||||||
|
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
= help: Replace with `Literal[...] | None`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
65 65 | # ... but if Y061 and Y062 both apply
|
||||||
|
66 66 | # and there are no None members in the Literal[] slice,
|
||||||
|
67 67 | # only emit Y062:
|
||||||
|
68 |-Literal[None, True, None, True] # Y062 Duplicate "Literal[]" member "True"
|
||||||
|
68 |+Literal[True, True] | None # Y062 Duplicate "Literal[]" member "True"
|
||||||
|
69 69 |
|
||||||
|
70 70 |
|
||||||
|
71 71 | # Regression tests for https://github.com/astral-sh/ruff/issues/14567
|
||||||
|
|
||||||
PYI061.py:72:12: PYI061 `Literal[None]` can be replaced with `None`
|
PYI061.py:72:12: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
|
||||||
71 | # Regression tests for https://github.com/astral-sh/ruff/issues/14567
|
71 | # Regression tests for https://github.com/astral-sh/ruff/issues/14567
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
|
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
|
||||||
|
snapshot_kind: text
|
||||||
---
|
---
|
||||||
PYI061.pyi:4:25: PYI061 [*] `Literal[None]` can be replaced with `None`
|
PYI061.pyi:4:25: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
|
||||||
|
|
@ -52,13 +53,23 @@ PYI061.pyi:10:24: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
12 12 |
|
12 12 |
|
||||||
13 13 | def func4(arg1: Literal[int, None, float]): ...
|
13 13 | def func4(arg1: Literal[int, None, float]): ...
|
||||||
|
|
||||||
PYI061.pyi:13:30: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
PYI061.pyi:13:30: PYI061 [*] `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
|
||||||
13 | def func4(arg1: Literal[int, None, float]): ...
|
13 | def func4(arg1: Literal[int, None, float]): ...
|
||||||
| ^^^^ PYI061
|
| ^^^^ PYI061
|
||||||
|
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
= help: Replace with `Literal[...] | None`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
10 10 | def func3() -> Literal[None]: ...
|
||||||
|
11 11 |
|
||||||
|
12 12 |
|
||||||
|
13 |-def func4(arg1: Literal[int, None, float]): ...
|
||||||
|
13 |+def func4(arg1: Literal[int, float] | None): ...
|
||||||
|
14 14 |
|
||||||
|
15 15 |
|
||||||
|
16 16 | def func5(arg1: Literal[None, None]): ...
|
||||||
|
|
||||||
PYI061.pyi:16:25: PYI061 [*] `Literal[None]` can be replaced with `None`
|
PYI061.pyi:16:25: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
|
||||||
16 | def func5(arg1: Literal[None, None]): ...
|
16 | def func5(arg1: Literal[None, None]): ...
|
||||||
|
|
@ -93,7 +104,7 @@ PYI061.pyi:16:31: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
18 18 |
|
18 18 |
|
||||||
19 19 | def func6(arg1: Literal[
|
19 19 | def func6(arg1: Literal[
|
||||||
|
|
||||||
PYI061.pyi:21:5: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
PYI061.pyi:21:5: PYI061 [*] `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
|
||||||
19 | def func6(arg1: Literal[
|
19 | def func6(arg1: Literal[
|
||||||
20 | "hello",
|
20 | "hello",
|
||||||
|
|
@ -104,6 +115,20 @@ PYI061.pyi:21:5: PYI061 `Literal[None, ...]` can be replaced with `Literal[...]
|
||||||
|
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
= help: Replace with `Literal[...] | None`
|
||||||
|
|
||||||
|
ℹ Unsafe fix
|
||||||
|
16 16 | def func5(arg1: Literal[None, None]): ...
|
||||||
|
17 17 |
|
||||||
|
18 18 |
|
||||||
|
19 |-def func6(arg1: Literal[
|
||||||
|
20 |- "hello",
|
||||||
|
21 |- None # Comment 1
|
||||||
|
22 |- , "world"
|
||||||
|
23 |-]): ...
|
||||||
|
19 |+def func6(arg1: Literal["hello", "world"] | None): ...
|
||||||
|
24 20 |
|
||||||
|
25 21 |
|
||||||
|
26 22 | def func7(arg1: Literal[
|
||||||
|
|
||||||
PYI061.pyi:27:5: PYI061 [*] `Literal[None]` can be replaced with `None`
|
PYI061.pyi:27:5: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
|
||||||
26 | def func7(arg1: Literal[
|
26 | def func7(arg1: Literal[
|
||||||
|
|
@ -168,7 +193,7 @@ PYI061.pyi:42:9: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
44 44 |
|
44 44 |
|
||||||
45 45 |
|
45 45 |
|
||||||
|
|
||||||
PYI061.pyi:43:15: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
PYI061.pyi:43:15: PYI061 [*] `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
|
||||||
41 | # From flake8-pyi
|
41 | # From flake8-pyi
|
||||||
42 | Literal[None] # PYI061 None inside "Literal[]" expression. Replace with "None"
|
42 | Literal[None] # PYI061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
|
@ -177,6 +202,16 @@ PYI061.pyi:43:15: PYI061 `Literal[None, ...]` can be replaced with `Literal[...]
|
||||||
|
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
= help: Replace with `Literal[...] | None`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
40 40 |
|
||||||
|
41 41 | # From flake8-pyi
|
||||||
|
42 42 | Literal[None] # PYI061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
43 |-Literal[True, None] # PYI061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
||||||
|
43 |+Literal[True] | None # PYI061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
||||||
|
44 44 |
|
||||||
|
45 45 |
|
||||||
|
46 46 | # Regression tests for https://github.com/astral-sh/ruff/issues/14567
|
||||||
|
|
||||||
PYI061.pyi:47:12: PYI061 `Literal[None]` can be replaced with `None`
|
PYI061.pyi:47:12: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
|
||||||
46 | # Regression tests for https://github.com/astral-sh/ruff/issues/14567
|
46 | # Regression tests for https://github.com/astral-sh/ruff/issues/14567
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue