mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 22:01:18 +00:00
[flake8-pyi
] Improve autofix safety for redundant-none-literal
(PYI061) (#14583)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
parent
e8fce20736
commit
c606bf014e
5 changed files with 505 additions and 137 deletions
|
@ -1,4 +1,4 @@
|
||||||
from typing import Literal
|
from typing import Literal, Union
|
||||||
|
|
||||||
|
|
||||||
def func1(arg1: Literal[None]):
|
def func1(arg1: Literal[None]):
|
||||||
|
@ -35,6 +35,14 @@ def func7(arg1: Literal[
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
def func8(arg1: Literal[None] | None):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
def func9(arg1: Union[Literal[None], None]):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
# OK
|
# OK
|
||||||
def good_func(arg1: Literal[int] | None):
|
def good_func(arg1: Literal[int] | None):
|
||||||
...
|
...
|
||||||
|
@ -58,3 +66,16 @@ Literal[1, None, "foo", None] # Y061 None inside "Literal[]" expression. Replac
|
||||||
# and there are no None members in the Literal[] slice,
|
# and there are no None members in the Literal[] slice,
|
||||||
# only emit Y062:
|
# only emit Y062:
|
||||||
Literal[None, True, None, True] # Y062 Duplicate "Literal[]" member "True"
|
Literal[None, True, None, True] # Y062 Duplicate "Literal[]" member "True"
|
||||||
|
|
||||||
|
|
||||||
|
# Regression tests for https://github.com/astral-sh/ruff/issues/14567
|
||||||
|
x: Literal[None] | None
|
||||||
|
y: None | Literal[None]
|
||||||
|
z: Union[Literal[None], None]
|
||||||
|
|
||||||
|
a: int | Literal[None] | None
|
||||||
|
b: None | Literal[None] | None
|
||||||
|
c: (None | Literal[None]) | None
|
||||||
|
d: None | (Literal[None] | None)
|
||||||
|
e: None | ((None | Literal[None]) | None) | None
|
||||||
|
f: Literal[None] | Literal[None]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Literal
|
from typing import Literal, Union
|
||||||
|
|
||||||
|
|
||||||
def func1(arg1: Literal[None]): ...
|
def func1(arg1: Literal[None]): ...
|
||||||
|
@ -28,6 +28,12 @@ def func7(arg1: Literal[
|
||||||
]): ...
|
]): ...
|
||||||
|
|
||||||
|
|
||||||
|
def func8(arg1: Literal[None] | None):...
|
||||||
|
|
||||||
|
|
||||||
|
def func9(arg1: Union[Literal[None], None]): ...
|
||||||
|
|
||||||
|
|
||||||
# OK
|
# OK
|
||||||
def good_func(arg1: Literal[int] | None): ...
|
def good_func(arg1: Literal[int] | None): ...
|
||||||
|
|
||||||
|
@ -35,3 +41,16 @@ def good_func(arg1: Literal[int] | None): ...
|
||||||
# From flake8-pyi
|
# From flake8-pyi
|
||||||
Literal[None] # PYI061 None inside "Literal[]" expression. Replace with "None"
|
Literal[None] # PYI061 None inside "Literal[]" expression. Replace with "None"
|
||||||
Literal[True, None] # PYI061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
Literal[True, None] # PYI061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
||||||
|
|
||||||
|
|
||||||
|
# Regression tests for https://github.com/astral-sh/ruff/issues/14567
|
||||||
|
x: Literal[None] | None
|
||||||
|
y: None | Literal[None]
|
||||||
|
z: Union[Literal[None], None]
|
||||||
|
|
||||||
|
a: int | Literal[None] | None
|
||||||
|
b: None | Literal[None] | None
|
||||||
|
c: (None | Literal[None]) | None
|
||||||
|
d: None | (Literal[None] | None)
|
||||||
|
e: None | ((None | Literal[None]) | None) | None
|
||||||
|
f: Literal[None] | Literal[None]
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
use ruff_diagnostics::{Applicability, Diagnostic, Edit, Fix, FixAvailability, Violation};
|
use ruff_diagnostics::{Applicability, Diagnostic, Edit, Fix, FixAvailability, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::{Expr, ExprNoneLiteral};
|
use ruff_python_ast::{Expr, ExprBinOp, ExprNoneLiteral, ExprSubscript, Operator};
|
||||||
use ruff_python_semantic::analyze::typing::traverse_literal;
|
use ruff_python_semantic::{
|
||||||
|
analyze::typing::{traverse_literal, traverse_union},
|
||||||
|
SemanticModel,
|
||||||
|
};
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
@ -31,6 +34,9 @@ use crate::checkers::ast::Checker;
|
||||||
/// Literal[1, 2, 3, "foo", 5] | None
|
/// Literal[1, 2, 3, "foo", 5] | None
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// ## Fix safety
|
||||||
|
/// This rule's fix is marked as safe unless the literal contains comments.
|
||||||
|
///
|
||||||
/// ## 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)
|
||||||
#[violation]
|
#[violation]
|
||||||
|
@ -87,14 +93,16 @@ pub(crate) fn redundant_none_literal<'a>(checker: &mut Checker, literal_expr: &'
|
||||||
let fix = if other_literal_elements_seen {
|
let fix = if other_literal_elements_seen {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(Fix::applicable_edit(
|
create_fix_edit(checker.semantic(), literal_expr).map(|edit| {
|
||||||
Edit::range_replacement("None".to_string(), literal_expr.range()),
|
Fix::applicable_edit(
|
||||||
if checker.comment_ranges().intersects(literal_expr.range()) {
|
edit,
|
||||||
Applicability::Unsafe
|
if checker.comment_ranges().intersects(literal_expr.range()) {
|
||||||
} else {
|
Applicability::Unsafe
|
||||||
Applicability::Safe
|
} else {
|
||||||
},
|
Applicability::Safe
|
||||||
))
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
for none_expr in none_exprs {
|
for none_expr in none_exprs {
|
||||||
|
@ -110,3 +118,47 @@ pub(crate) fn redundant_none_literal<'a>(checker: &mut Checker, literal_expr: &'
|
||||||
checker.diagnostics.push(diagnostic);
|
checker.diagnostics.push(diagnostic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_fix_edit(semantic: &SemanticModel, literal_expr: &Expr) -> Option<Edit> {
|
||||||
|
let mut enclosing_union = None;
|
||||||
|
for expr in semantic.current_expressions().skip(1).take_while(|expr| {
|
||||||
|
matches!(
|
||||||
|
expr,
|
||||||
|
Expr::BinOp(ExprBinOp {
|
||||||
|
op: Operator::BitOr,
|
||||||
|
..
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
enclosing_union = Some(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut is_fixable = true;
|
||||||
|
if let Some(enclosing_union) = enclosing_union {
|
||||||
|
traverse_union(
|
||||||
|
&mut |expr, _| {
|
||||||
|
if matches!(expr, Expr::NoneLiteral(_)) {
|
||||||
|
is_fixable = false;
|
||||||
|
}
|
||||||
|
if expr != literal_expr {
|
||||||
|
if let Expr::Subscript(ExprSubscript { value, slice, .. }) = expr {
|
||||||
|
if semantic.match_typing_expr(value, "Literal")
|
||||||
|
&& matches!(**slice, Expr::NoneLiteral(_))
|
||||||
|
{
|
||||||
|
is_fixable = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
semantic,
|
||||||
|
enclosing_union,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoid producing code that would raise an exception when
|
||||||
|
// `Literal[None] | None` would be fixed to `None | None`.
|
||||||
|
// Instead do not provide a fix. No action needed for `typing.Union`,
|
||||||
|
// as `Union[None, None]` is valid Python.
|
||||||
|
// See https://github.com/astral-sh/ruff/issues/14567.
|
||||||
|
is_fixable.then(|| Edit::range_replacement("None".to_string(), literal_expr.range()))
|
||||||
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ PYI061.py:4:25: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
= help: Replace with `None`
|
= help: Replace with `None`
|
||||||
|
|
||||||
ℹ Safe fix
|
ℹ Safe fix
|
||||||
1 1 | from typing import Literal
|
1 1 | from typing import Literal, Union
|
||||||
2 2 |
|
2 2 |
|
||||||
3 3 |
|
3 3 |
|
||||||
4 |-def func1(arg1: Literal[None]):
|
4 |-def func1(arg1: Literal[None]):
|
||||||
|
@ -132,112 +132,250 @@ PYI061.py:33:5: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
36 34 |
|
36 34 |
|
||||||
37 35 |
|
37 35 |
|
||||||
|
|
||||||
PYI061.py:44:9: PYI061 [*] `Literal[None]` can be replaced with `None`
|
PYI061.py:38:25: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
|
||||||
43 | # From flake8-pyi
|
38 | def func8(arg1: Literal[None] | None):
|
||||||
44 | Literal[None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
|
||||||
| ^^^^ PYI061
|
|
||||||
45 | Literal[True, None] # Y061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
|
||||||
|
|
|
||||||
= help: Replace with `None`
|
|
||||||
|
|
||||||
ℹ Safe fix
|
|
||||||
41 41 |
|
|
||||||
42 42 |
|
|
||||||
43 43 | # From flake8-pyi
|
|
||||||
44 |-Literal[None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
|
||||||
44 |+None # Y061 None inside "Literal[]" expression. Replace with "None"
|
|
||||||
45 45 | Literal[True, None] # Y061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
|
||||||
46 46 |
|
|
||||||
47 47 | ###
|
|
||||||
|
|
||||||
PYI061.py:45:15: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
|
||||||
|
|
|
||||||
43 | # From flake8-pyi
|
|
||||||
44 | Literal[None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
|
||||||
45 | Literal[True, None] # Y061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
|
||||||
| ^^^^ PYI061
|
|
||||||
46 |
|
|
||||||
47 | ###
|
|
||||||
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
|
||||||
|
|
||||||
PYI061.py:54:9: PYI061 [*] `Literal[None]` can be replaced with `None`
|
|
||||||
|
|
|
||||||
52 | # If Y061 and Y062 both apply, but all the duplicate members are None,
|
|
||||||
53 | # only emit Y061...
|
|
||||||
54 | Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
|
||||||
| ^^^^ PYI061
|
|
||||||
55 | Literal[1, None, "foo", None] # Y061 None inside "Literal[]" expression. Replace with "Literal[1, 'foo'] | None"
|
|
||||||
|
|
|
||||||
= help: Replace with `None`
|
|
||||||
|
|
||||||
ℹ Safe fix
|
|
||||||
51 51 |
|
|
||||||
52 52 | # If Y061 and Y062 both apply, but all the duplicate members are None,
|
|
||||||
53 53 | # only emit Y061...
|
|
||||||
54 |-Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
|
||||||
54 |+None # Y061 None inside "Literal[]" expression. Replace with "None"
|
|
||||||
55 55 | Literal[1, None, "foo", None] # Y061 None inside "Literal[]" expression. Replace with "Literal[1, 'foo'] | None"
|
|
||||||
56 56 |
|
|
||||||
57 57 | # ... but if Y061 and Y062 both apply
|
|
||||||
|
|
||||||
PYI061.py:54:15: PYI061 [*] `Literal[None]` can be replaced with `None`
|
|
||||||
|
|
|
||||||
52 | # If Y061 and Y062 both apply, but all the duplicate members are None,
|
|
||||||
53 | # only emit Y061...
|
|
||||||
54 | Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
|
||||||
| ^^^^ PYI061
|
|
||||||
55 | Literal[1, None, "foo", None] # Y061 None inside "Literal[]" expression. Replace with "Literal[1, 'foo'] | None"
|
|
||||||
|
|
|
||||||
= help: Replace with `None`
|
|
||||||
|
|
||||||
ℹ Safe fix
|
|
||||||
51 51 |
|
|
||||||
52 52 | # If Y061 and Y062 both apply, but all the duplicate members are None,
|
|
||||||
53 53 | # only emit Y061...
|
|
||||||
54 |-Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
|
||||||
54 |+None # Y061 None inside "Literal[]" expression. Replace with "None"
|
|
||||||
55 55 | Literal[1, None, "foo", None] # Y061 None inside "Literal[]" expression. Replace with "Literal[1, 'foo'] | None"
|
|
||||||
56 56 |
|
|
||||||
57 57 | # ... but if Y061 and Y062 both apply
|
|
||||||
|
|
||||||
PYI061.py:55:12: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
|
||||||
|
|
|
||||||
53 | # only emit Y061...
|
|
||||||
54 | Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
|
||||||
55 | Literal[1, None, "foo", None] # Y061 None inside "Literal[]" expression. Replace with "Literal[1, 'foo'] | None"
|
|
||||||
| ^^^^ PYI061
|
|
||||||
56 |
|
|
||||||
57 | # ... but if Y061 and Y062 both apply
|
|
||||||
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
|
||||||
|
|
||||||
PYI061.py:55:25: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
|
||||||
|
|
|
||||||
53 | # only emit Y061...
|
|
||||||
54 | Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
|
||||||
55 | Literal[1, None, "foo", None] # Y061 None inside "Literal[]" expression. Replace with "Literal[1, 'foo'] | None"
|
|
||||||
| ^^^^ PYI061
|
| ^^^^ PYI061
|
||||||
56 |
|
39 | ...
|
||||||
57 | # ... but if Y061 and Y062 both apply
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.py:42:31: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
42 | def func9(arg1: Union[Literal[None], None]):
|
||||||
|
| ^^^^ PYI061
|
||||||
|
43 | ...
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
39 39 | ...
|
||||||
|
40 40 |
|
||||||
|
41 41 |
|
||||||
|
42 |-def func9(arg1: Union[Literal[None], None]):
|
||||||
|
42 |+def func9(arg1: Union[None, None]):
|
||||||
|
43 43 | ...
|
||||||
|
44 44 |
|
||||||
|
45 45 |
|
||||||
|
|
||||||
|
PYI061.py:52:9: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
51 | # From flake8-pyi
|
||||||
|
52 | Literal[None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
| ^^^^ PYI061
|
||||||
|
53 | Literal[True, None] # Y061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
49 49 |
|
||||||
|
50 50 |
|
||||||
|
51 51 | # From flake8-pyi
|
||||||
|
52 |-Literal[None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
52 |+None # Y061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
53 53 | Literal[True, None] # Y061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
||||||
|
54 54 |
|
||||||
|
55 55 | ###
|
||||||
|
|
||||||
|
PYI061.py:53:15: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
||||||
|
51 | # From flake8-pyi
|
||||||
|
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"
|
||||||
|
| ^^^^ PYI061
|
||||||
|
54 |
|
||||||
|
55 | ###
|
||||||
|
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
= help: Replace with `Literal[...] | None`
|
||||||
|
|
||||||
PYI061.py:60:9: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
PYI061.py:62:9: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
|
||||||
58 | # and there are no None members in the Literal[] slice,
|
60 | # If Y061 and Y062 both apply, but all the duplicate members are None,
|
||||||
59 | # only emit Y062:
|
61 | # only emit Y061...
|
||||||
60 | Literal[None, True, None, True] # Y062 Duplicate "Literal[]" member "True"
|
62 | Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
| ^^^^ PYI061
|
||||||
|
63 | Literal[1, None, "foo", None] # Y061 None inside "Literal[]" expression. Replace with "Literal[1, 'foo'] | None"
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
59 59 |
|
||||||
|
60 60 | # If Y061 and Y062 both apply, but all the duplicate members are None,
|
||||||
|
61 61 | # only emit Y061...
|
||||||
|
62 |-Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
62 |+None # Y061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
63 63 | Literal[1, None, "foo", None] # Y061 None inside "Literal[]" expression. Replace with "Literal[1, 'foo'] | None"
|
||||||
|
64 64 |
|
||||||
|
65 65 | # ... but if Y061 and Y062 both apply
|
||||||
|
|
||||||
|
PYI061.py:62:15: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
60 | # If Y061 and Y062 both apply, but all the duplicate members are None,
|
||||||
|
61 | # only emit Y061...
|
||||||
|
62 | Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
| ^^^^ PYI061
|
||||||
|
63 | Literal[1, None, "foo", None] # Y061 None inside "Literal[]" expression. Replace with "Literal[1, 'foo'] | None"
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
59 59 |
|
||||||
|
60 60 | # If Y061 and Y062 both apply, but all the duplicate members are None,
|
||||||
|
61 61 | # only emit Y061...
|
||||||
|
62 |-Literal[None, None] # Y061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
62 |+None # Y061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
63 63 | Literal[1, None, "foo", None] # Y061 None inside "Literal[]" expression. Replace with "Literal[1, 'foo'] | None"
|
||||||
|
64 64 |
|
||||||
|
65 65 | # ... but if Y061 and Y062 both apply
|
||||||
|
|
||||||
|
PYI061.py:63:12: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
||||||
|
61 | # only emit Y061...
|
||||||
|
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"
|
||||||
|
| ^^^^ PYI061
|
||||||
|
64 |
|
||||||
|
65 | # ... but if Y061 and Y062 both apply
|
||||||
|
|
|
||||||
|
= help: Replace with `Literal[...] | None`
|
||||||
|
|
||||||
|
PYI061.py:63:25: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
||||||
|
61 | # only emit Y061...
|
||||||
|
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"
|
||||||
|
| ^^^^ PYI061
|
||||||
|
64 |
|
||||||
|
65 | # ... but if Y061 and Y062 both apply
|
||||||
|
|
|
||||||
|
= help: Replace with `Literal[...] | None`
|
||||||
|
|
||||||
|
PYI061.py:68:9: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
||||||
|
66 | # and there are no None members in the Literal[] slice,
|
||||||
|
67 | # only emit Y062:
|
||||||
|
68 | Literal[None, True, None, True] # Y062 Duplicate "Literal[]" member "True"
|
||||||
| ^^^^ PYI061
|
| ^^^^ PYI061
|
||||||
|
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
= help: Replace with `Literal[...] | None`
|
||||||
|
|
||||||
PYI061.py:60:21: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
PYI061.py:68:21: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
|
||||||
58 | # and there are no None members in the Literal[] slice,
|
66 | # and there are no None members in the Literal[] slice,
|
||||||
59 | # only emit Y062:
|
67 | # only emit Y062:
|
||||||
60 | Literal[None, True, None, True] # Y062 Duplicate "Literal[]" member "True"
|
68 | Literal[None, True, None, True] # Y062 Duplicate "Literal[]" member "True"
|
||||||
| ^^^^ PYI061
|
| ^^^^ PYI061
|
||||||
|
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
= help: Replace with `Literal[...] | 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
|
||||||
|
72 | x: Literal[None] | None
|
||||||
|
| ^^^^ PYI061
|
||||||
|
73 | y: None | Literal[None]
|
||||||
|
74 | z: Union[Literal[None], None]
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.py:73:19: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
71 | # Regression tests for https://github.com/astral-sh/ruff/issues/14567
|
||||||
|
72 | x: Literal[None] | None
|
||||||
|
73 | y: None | Literal[None]
|
||||||
|
| ^^^^ PYI061
|
||||||
|
74 | z: Union[Literal[None], None]
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.py:74:18: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
72 | x: Literal[None] | None
|
||||||
|
73 | y: None | Literal[None]
|
||||||
|
74 | z: Union[Literal[None], None]
|
||||||
|
| ^^^^ PYI061
|
||||||
|
75 |
|
||||||
|
76 | a: int | Literal[None] | None
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
71 71 | # Regression tests for https://github.com/astral-sh/ruff/issues/14567
|
||||||
|
72 72 | x: Literal[None] | None
|
||||||
|
73 73 | y: None | Literal[None]
|
||||||
|
74 |-z: Union[Literal[None], None]
|
||||||
|
74 |+z: Union[None, None]
|
||||||
|
75 75 |
|
||||||
|
76 76 | a: int | Literal[None] | None
|
||||||
|
77 77 | b: None | Literal[None] | None
|
||||||
|
|
||||||
|
PYI061.py:76:18: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
74 | z: Union[Literal[None], None]
|
||||||
|
75 |
|
||||||
|
76 | a: int | Literal[None] | None
|
||||||
|
| ^^^^ PYI061
|
||||||
|
77 | b: None | Literal[None] | None
|
||||||
|
78 | c: (None | Literal[None]) | None
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.py:77:19: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
76 | a: int | Literal[None] | None
|
||||||
|
77 | b: None | Literal[None] | None
|
||||||
|
| ^^^^ PYI061
|
||||||
|
78 | c: (None | Literal[None]) | None
|
||||||
|
79 | d: None | (Literal[None] | None)
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.py:78:20: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
76 | a: int | Literal[None] | None
|
||||||
|
77 | b: None | Literal[None] | None
|
||||||
|
78 | c: (None | Literal[None]) | None
|
||||||
|
| ^^^^ PYI061
|
||||||
|
79 | d: None | (Literal[None] | None)
|
||||||
|
80 | e: None | ((None | Literal[None]) | None) | None
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.py:79:20: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
77 | b: None | Literal[None] | None
|
||||||
|
78 | c: (None | Literal[None]) | None
|
||||||
|
79 | d: None | (Literal[None] | None)
|
||||||
|
| ^^^^ PYI061
|
||||||
|
80 | e: None | ((None | Literal[None]) | None) | None
|
||||||
|
81 | f: Literal[None] | Literal[None]
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.py:80:28: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
78 | c: (None | Literal[None]) | None
|
||||||
|
79 | d: None | (Literal[None] | None)
|
||||||
|
80 | e: None | ((None | Literal[None]) | None) | None
|
||||||
|
| ^^^^ PYI061
|
||||||
|
81 | f: Literal[None] | Literal[None]
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.py:81:12: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
79 | d: None | (Literal[None] | None)
|
||||||
|
80 | e: None | ((None | Literal[None]) | None) | None
|
||||||
|
81 | f: Literal[None] | Literal[None]
|
||||||
|
| ^^^^ PYI061
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.py:81:28: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
79 | d: None | (Literal[None] | None)
|
||||||
|
80 | e: None | ((None | Literal[None]) | None) | None
|
||||||
|
81 | f: Literal[None] | Literal[None]
|
||||||
|
| ^^^^ PYI061
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
|
@ -9,7 +9,7 @@ PYI061.pyi:4:25: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
= help: Replace with `None`
|
= help: Replace with `None`
|
||||||
|
|
||||||
ℹ Safe fix
|
ℹ Safe fix
|
||||||
1 1 | from typing import Literal
|
1 1 | from typing import Literal, Union
|
||||||
2 2 |
|
2 2 |
|
||||||
3 3 |
|
3 3 |
|
||||||
4 |-def func1(arg1: Literal[None]): ...
|
4 |-def func1(arg1: Literal[None]): ...
|
||||||
|
@ -123,30 +123,168 @@ PYI061.pyi:27:5: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
26 |+def func7(arg1: None): ...
|
26 |+def func7(arg1: None): ...
|
||||||
29 27 |
|
29 27 |
|
||||||
30 28 |
|
30 28 |
|
||||||
31 29 | # OK
|
31 29 | def func8(arg1: Literal[None] | None):...
|
||||||
|
|
||||||
PYI061.pyi:36:9: PYI061 [*] `Literal[None]` can be replaced with `None`
|
PYI061.pyi:31:25: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
|
||||||
35 | # From flake8-pyi
|
31 | def func8(arg1: Literal[None] | None):...
|
||||||
36 | Literal[None] # PYI061 None inside "Literal[]" expression. Replace with "None"
|
| ^^^^ PYI061
|
||||||
| ^^^^ PYI061
|
|
|
||||||
37 | Literal[True, None] # PYI061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.pyi:34:31: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
34 | def func9(arg1: Union[Literal[None], None]): ...
|
||||||
|
| ^^^^ PYI061
|
||||||
|
|
|
|
||||||
= help: Replace with `None`
|
= help: Replace with `None`
|
||||||
|
|
||||||
ℹ Safe fix
|
ℹ Safe fix
|
||||||
|
31 31 | def func8(arg1: Literal[None] | None):...
|
||||||
|
32 32 |
|
||||||
33 33 |
|
33 33 |
|
||||||
34 34 |
|
34 |-def func9(arg1: Union[Literal[None], None]): ...
|
||||||
35 35 | # From flake8-pyi
|
34 |+def func9(arg1: Union[None, None]): ...
|
||||||
36 |-Literal[None] # PYI061 None inside "Literal[]" expression. Replace with "None"
|
35 35 |
|
||||||
36 |+None # PYI061 None inside "Literal[]" expression. Replace with "None"
|
36 36 |
|
||||||
37 37 | Literal[True, None] # PYI061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
37 37 | # OK
|
||||||
|
|
||||||
PYI061.pyi:37:15: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
PYI061.pyi:42:9: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
|
||||||
35 | # From flake8-pyi
|
41 | # From flake8-pyi
|
||||||
36 | Literal[None] # PYI061 None inside "Literal[]" expression. Replace with "None"
|
42 | Literal[None] # PYI061 None inside "Literal[]" expression. Replace with "None"
|
||||||
37 | Literal[True, None] # PYI061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
| ^^^^ PYI061
|
||||||
|
43 | Literal[True, None] # PYI061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
39 39 |
|
||||||
|
40 40 |
|
||||||
|
41 41 | # From flake8-pyi
|
||||||
|
42 |-Literal[None] # PYI061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
42 |+None # PYI061 None inside "Literal[]" expression. Replace with "None"
|
||||||
|
43 43 | Literal[True, None] # PYI061 None inside "Literal[]" expression. Replace with "Literal[True] | None"
|
||||||
|
44 44 |
|
||||||
|
45 45 |
|
||||||
|
|
||||||
|
PYI061.pyi:43:15: PYI061 `Literal[None, ...]` can be replaced with `Literal[...] | None`
|
||||||
|
|
|
||||||
|
41 | # From flake8-pyi
|
||||||
|
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"
|
||||||
| ^^^^ PYI061
|
| ^^^^ PYI061
|
||||||
|
|
|
|
||||||
= help: Replace with `Literal[...] | None`
|
= help: Replace with `Literal[...] | 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
|
||||||
|
47 | x: Literal[None] | None
|
||||||
|
| ^^^^ PYI061
|
||||||
|
48 | y: None | Literal[None]
|
||||||
|
49 | z: Union[Literal[None], None]
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.pyi:48:19: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
46 | # Regression tests for https://github.com/astral-sh/ruff/issues/14567
|
||||||
|
47 | x: Literal[None] | None
|
||||||
|
48 | y: None | Literal[None]
|
||||||
|
| ^^^^ PYI061
|
||||||
|
49 | z: Union[Literal[None], None]
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.pyi:49:18: PYI061 [*] `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
47 | x: Literal[None] | None
|
||||||
|
48 | y: None | Literal[None]
|
||||||
|
49 | z: Union[Literal[None], None]
|
||||||
|
| ^^^^ PYI061
|
||||||
|
50 |
|
||||||
|
51 | a: int | Literal[None] | None
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
ℹ Safe fix
|
||||||
|
46 46 | # Regression tests for https://github.com/astral-sh/ruff/issues/14567
|
||||||
|
47 47 | x: Literal[None] | None
|
||||||
|
48 48 | y: None | Literal[None]
|
||||||
|
49 |-z: Union[Literal[None], None]
|
||||||
|
49 |+z: Union[None, None]
|
||||||
|
50 50 |
|
||||||
|
51 51 | a: int | Literal[None] | None
|
||||||
|
52 52 | b: None | Literal[None] | None
|
||||||
|
|
||||||
|
PYI061.pyi:51:18: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
49 | z: Union[Literal[None], None]
|
||||||
|
50 |
|
||||||
|
51 | a: int | Literal[None] | None
|
||||||
|
| ^^^^ PYI061
|
||||||
|
52 | b: None | Literal[None] | None
|
||||||
|
53 | c: (None | Literal[None]) | None
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.pyi:52:19: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
51 | a: int | Literal[None] | None
|
||||||
|
52 | b: None | Literal[None] | None
|
||||||
|
| ^^^^ PYI061
|
||||||
|
53 | c: (None | Literal[None]) | None
|
||||||
|
54 | d: None | (Literal[None] | None)
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.pyi:53:20: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
51 | a: int | Literal[None] | None
|
||||||
|
52 | b: None | Literal[None] | None
|
||||||
|
53 | c: (None | Literal[None]) | None
|
||||||
|
| ^^^^ PYI061
|
||||||
|
54 | d: None | (Literal[None] | None)
|
||||||
|
55 | e: None | ((None | Literal[None]) | None) | None
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.pyi:54:20: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
52 | b: None | Literal[None] | None
|
||||||
|
53 | c: (None | Literal[None]) | None
|
||||||
|
54 | d: None | (Literal[None] | None)
|
||||||
|
| ^^^^ PYI061
|
||||||
|
55 | e: None | ((None | Literal[None]) | None) | None
|
||||||
|
56 | f: Literal[None] | Literal[None]
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.pyi:55:28: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
53 | c: (None | Literal[None]) | None
|
||||||
|
54 | d: None | (Literal[None] | None)
|
||||||
|
55 | e: None | ((None | Literal[None]) | None) | None
|
||||||
|
| ^^^^ PYI061
|
||||||
|
56 | f: Literal[None] | Literal[None]
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.pyi:56:12: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
54 | d: None | (Literal[None] | None)
|
||||||
|
55 | e: None | ((None | Literal[None]) | None) | None
|
||||||
|
56 | f: Literal[None] | Literal[None]
|
||||||
|
| ^^^^ PYI061
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
||||||
|
PYI061.pyi:56:28: PYI061 `Literal[None]` can be replaced with `None`
|
||||||
|
|
|
||||||
|
54 | d: None | (Literal[None] | None)
|
||||||
|
55 | e: None | ((None | Literal[None]) | None) | None
|
||||||
|
56 | f: Literal[None] | Literal[None]
|
||||||
|
| ^^^^ PYI061
|
||||||
|
|
|
||||||
|
= help: Replace with `None`
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue