add autofix for `PYI030` (#7880)

## Summary

Adds autofix to `PYI030`

Closes #7854. 

Unsure if the cloning method I chose is the best solution here, feel
free to suggest alternatives!

## Test Plan

`cargo test` as well as manually
This commit is contained in:
Steve C 2023-10-09 23:15:13 -04:00 committed by GitHub
parent 097b654ba7
commit d8c0360fc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 467 additions and 47 deletions

View File

@ -1,9 +1,10 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::{self as ast, Expr};
use ruff_text_size::Ranged;
use crate::checkers::ast::Checker;
use crate::registry::AsRule;
use crate::rules::flake8_pyi::helpers::traverse_union;
/// ## What it does
@ -31,7 +32,7 @@ pub struct UnnecessaryLiteralUnion {
members: Vec<String>,
}
impl Violation for UnnecessaryLiteralUnion {
impl AlwaysFixableViolation for UnnecessaryLiteralUnion {
#[derive_message_formats]
fn message(&self) -> String {
format!(
@ -39,13 +40,17 @@ impl Violation for UnnecessaryLiteralUnion {
self.members.join(", ")
)
}
fn fix_title(&self) -> String {
format!("Replace with a single `Literal`")
}
}
/// PYI030
pub(crate) fn unnecessary_literal_union<'a>(checker: &mut Checker, expr: &'a Expr) {
let mut literal_exprs = Vec::new();
// Adds a member to `literal_exprs` if it is a `Literal` annotation
// Adds a member to `literal_exprs` if it is a `Literal` annotation.
let mut collect_literal_expr = |expr: &'a Expr, _| {
if let Expr::Subscript(ast::ExprSubscript { value, slice, .. }) = expr {
if checker.semantic().match_typing_expr(value, "Literal") {
@ -54,21 +59,30 @@ pub(crate) fn unnecessary_literal_union<'a>(checker: &mut Checker, expr: &'a Exp
}
};
// Traverse the union, collect all literal members
// Traverse the union, collect all literal members.
traverse_union(&mut collect_literal_expr, checker.semantic(), expr, None);
// Raise a violation if more than one
// Raise a violation if more than one.
if literal_exprs.len() > 1 {
let diagnostic = Diagnostic::new(
let literal_members: Vec<String> = literal_exprs
.into_iter()
.map(|expr| checker.locator().slice(expr.as_ref()).to_string())
.collect();
let mut diagnostic = Diagnostic::new(
UnnecessaryLiteralUnion {
members: literal_exprs
.into_iter()
.map(|expr| checker.locator().slice(expr.as_ref()).to_string())
.collect(),
members: literal_members.clone(),
},
expr.range(),
);
if checker.patch(diagnostic.kind.rule()) {
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
format!("Literal[{}]", literal_members.join(", ")),
expr.range(),
)));
}
checker.diagnostics.push(diagnostic);
}
}

View File

@ -1,7 +1,7 @@
---
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
---
PYI030.py:9:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
PYI030.py:9:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
8 | # Should emit for duplicate field types.
9 | field2: Literal[1] | Literal[2] # Error
@ -9,24 +9,57 @@ PYI030.py:9:9: PYI030 Multiple literal members in a union. Use a single literal,
10 |
11 | # Should emit for union types in arguments.
|
= help: Replace with a single `Literal`
PYI030.py:12:17: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
6 6 | field1: Literal[1] # OK
7 7 |
8 8 | # Should emit for duplicate field types.
9 |-field2: Literal[1] | Literal[2] # Error
9 |+field2: Literal[1, 2] # Error
10 10 |
11 11 | # Should emit for union types in arguments.
12 12 | def func1(arg1: Literal[1] | Literal[2]): # Error
PYI030.py:12:17: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
11 | # Should emit for union types in arguments.
12 | def func1(arg1: Literal[1] | Literal[2]): # Error
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
13 | print(arg1)
|
= help: Replace with a single `Literal`
PYI030.py:17:16: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
9 9 | field2: Literal[1] | Literal[2] # Error
10 10 |
11 11 | # Should emit for union types in arguments.
12 |-def func1(arg1: Literal[1] | Literal[2]): # Error
12 |+def func1(arg1: Literal[1, 2]): # Error
13 13 | print(arg1)
14 14 |
15 15 |
PYI030.py:17:16: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
16 | # Should emit for unions in return types.
17 | def func2() -> Literal[1] | Literal[2]: # Error
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
18 | return "my Literal[1]ing"
|
= help: Replace with a single `Literal`
PYI030.py:22:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
14 14 |
15 15 |
16 16 | # Should emit for unions in return types.
17 |-def func2() -> Literal[1] | Literal[2]: # Error
17 |+def func2() -> Literal[1, 2]: # Error
18 18 | return "my Literal[1]ing"
19 19 |
20 20 |
PYI030.py:22:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
21 | # Should emit in longer unions, even if not directly adjacent.
22 | field3: Literal[1] | Literal[2] | str # Error
@ -34,8 +67,19 @@ PYI030.py:22:9: PYI030 Multiple literal members in a union. Use a single literal
23 | field4: str | Literal[1] | Literal[2] # Error
24 | field5: Literal[1] | str | Literal[2] # Error
|
= help: Replace with a single `Literal`
PYI030.py:23:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
19 19 |
20 20 |
21 21 | # Should emit in longer unions, even if not directly adjacent.
22 |-field3: Literal[1] | Literal[2] | str # Error
22 |+field3: Literal[1, 2] # Error
23 23 | field4: str | Literal[1] | Literal[2] # Error
24 24 | field5: Literal[1] | str | Literal[2] # Error
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
PYI030.py:23:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
21 | # Should emit in longer unions, even if not directly adjacent.
22 | field3: Literal[1] | Literal[2] | str # Error
@ -44,8 +88,19 @@ PYI030.py:23:9: PYI030 Multiple literal members in a union. Use a single literal
24 | field5: Literal[1] | str | Literal[2] # Error
25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
= help: Replace with a single `Literal`
PYI030.py:24:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
20 20 |
21 21 | # Should emit in longer unions, even if not directly adjacent.
22 22 | field3: Literal[1] | Literal[2] | str # Error
23 |-field4: str | Literal[1] | Literal[2] # Error
23 |+field4: Literal[1, 2] # Error
24 24 | field5: Literal[1] | str | Literal[2] # Error
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
26 26 |
PYI030.py:24:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
22 | field3: Literal[1] | Literal[2] | str # Error
23 | field4: str | Literal[1] | Literal[2] # Error
@ -53,8 +108,19 @@ PYI030.py:24:9: PYI030 Multiple literal members in a union. Use a single literal
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
= help: Replace with a single `Literal`
PYI030.py:25:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
21 21 | # Should emit in longer unions, even if not directly adjacent.
22 22 | field3: Literal[1] | Literal[2] | str # Error
23 23 | field4: str | Literal[1] | Literal[2] # Error
24 |-field5: Literal[1] | str | Literal[2] # Error
24 |+field5: Literal[1, 2] # Error
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
26 26 |
27 27 | # Should emit for non-type unions.
PYI030.py:25:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
23 | field4: str | Literal[1] | Literal[2] # Error
24 | field5: Literal[1] | str | Literal[2] # Error
@ -63,8 +129,19 @@ PYI030.py:25:9: PYI030 Multiple literal members in a union. Use a single literal
26 |
27 | # Should emit for non-type unions.
|
= help: Replace with a single `Literal`
PYI030.py:28:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
22 22 | field3: Literal[1] | Literal[2] | str # Error
23 23 | field4: str | Literal[1] | Literal[2] # Error
24 24 | field5: Literal[1] | str | Literal[2] # Error
25 |-field6: Literal[1] | bool | Literal[2] | str # Error
25 |+field6: Literal[1, 2] # Error
26 26 |
27 27 | # Should emit for non-type unions.
28 28 | field7 = Literal[1] | Literal[2] # Error
PYI030.py:28:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
27 | # Should emit for non-type unions.
28 | field7 = Literal[1] | Literal[2] # Error
@ -72,8 +149,19 @@ PYI030.py:28:10: PYI030 Multiple literal members in a union. Use a single litera
29 |
30 | # Should emit for parenthesized unions.
|
= help: Replace with a single `Literal`
PYI030.py:31:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
26 26 |
27 27 | # Should emit for non-type unions.
28 |-field7 = Literal[1] | Literal[2] # Error
28 |+field7 = Literal[1, 2] # Error
29 29 |
30 30 | # Should emit for parenthesized unions.
31 31 | field8: Literal[1] | (Literal[2] | str) # Error
PYI030.py:31:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
30 | # Should emit for parenthesized unions.
31 | field8: Literal[1] | (Literal[2] | str) # Error
@ -81,16 +169,38 @@ PYI030.py:31:9: PYI030 Multiple literal members in a union. Use a single literal
32 |
33 | # Should handle user parentheses when fixing.
|
= help: Replace with a single `Literal`
PYI030.py:34:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
28 28 | field7 = Literal[1] | Literal[2] # Error
29 29 |
30 30 | # Should emit for parenthesized unions.
31 |-field8: Literal[1] | (Literal[2] | str) # Error
31 |+field8: Literal[1, 2] # Error
32 32 |
33 33 | # Should handle user parentheses when fixing.
34 34 | field9: Literal[1] | (Literal[2] | str) # Error
PYI030.py:34:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
33 | # Should handle user parentheses when fixing.
34 | field9: Literal[1] | (Literal[2] | str) # Error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
35 | field10: (Literal[1] | str) | Literal[2] # Error
|
= help: Replace with a single `Literal`
PYI030.py:35:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
31 31 | field8: Literal[1] | (Literal[2] | str) # Error
32 32 |
33 33 | # Should handle user parentheses when fixing.
34 |-field9: Literal[1] | (Literal[2] | str) # Error
34 |+field9: Literal[1, 2] # Error
35 35 | field10: (Literal[1] | str) | Literal[2] # Error
36 36 |
37 37 | # Should emit for union in generic parent type.
PYI030.py:35:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
33 | # Should handle user parentheses when fixing.
34 | field9: Literal[1] | (Literal[2] | str) # Error
@ -99,12 +209,31 @@ PYI030.py:35:10: PYI030 Multiple literal members in a union. Use a single litera
36 |
37 | # Should emit for union in generic parent type.
|
= help: Replace with a single `Literal`
PYI030.py:38:15: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
32 32 |
33 33 | # Should handle user parentheses when fixing.
34 34 | field9: Literal[1] | (Literal[2] | str) # Error
35 |-field10: (Literal[1] | str) | Literal[2] # Error
35 |+field10: Literal[1, 2] # Error
36 36 |
37 37 | # Should emit for union in generic parent type.
38 38 | field11: dict[Literal[1] | Literal[2], str] # Error
PYI030.py:38:15: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
37 | # Should emit for union in generic parent type.
38 | field11: dict[Literal[1] | Literal[2], str] # Error
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
= help: Replace with a single `Literal`
Fix
35 35 | field10: (Literal[1] | str) | Literal[2] # Error
36 36 |
37 37 | # Should emit for union in generic parent type.
38 |-field11: dict[Literal[1] | Literal[2], str] # Error
38 |+field11: dict[Literal[1, 2], str] # Error

View File

@ -1,7 +1,7 @@
---
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
---
PYI030.pyi:9:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
PYI030.pyi:9:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
8 | # Should emit for duplicate field types.
9 | field2: Literal[1] | Literal[2] # Error
@ -9,24 +9,57 @@ PYI030.pyi:9:9: PYI030 Multiple literal members in a union. Use a single literal
10 |
11 | # Should emit for union types in arguments.
|
= help: Replace with a single `Literal`
PYI030.pyi:12:17: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
6 6 | field1: Literal[1] # OK
7 7 |
8 8 | # Should emit for duplicate field types.
9 |-field2: Literal[1] | Literal[2] # Error
9 |+field2: Literal[1, 2] # Error
10 10 |
11 11 | # Should emit for union types in arguments.
12 12 | def func1(arg1: Literal[1] | Literal[2]): # Error
PYI030.pyi:12:17: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
11 | # Should emit for union types in arguments.
12 | def func1(arg1: Literal[1] | Literal[2]): # Error
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
13 | print(arg1)
|
= help: Replace with a single `Literal`
PYI030.pyi:17:16: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
9 9 | field2: Literal[1] | Literal[2] # Error
10 10 |
11 11 | # Should emit for union types in arguments.
12 |-def func1(arg1: Literal[1] | Literal[2]): # Error
12 |+def func1(arg1: Literal[1, 2]): # Error
13 13 | print(arg1)
14 14 |
15 15 |
PYI030.pyi:17:16: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
16 | # Should emit for unions in return types.
17 | def func2() -> Literal[1] | Literal[2]: # Error
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
18 | return "my Literal[1]ing"
|
= help: Replace with a single `Literal`
PYI030.pyi:22:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
14 14 |
15 15 |
16 16 | # Should emit for unions in return types.
17 |-def func2() -> Literal[1] | Literal[2]: # Error
17 |+def func2() -> Literal[1, 2]: # Error
18 18 | return "my Literal[1]ing"
19 19 |
20 20 |
PYI030.pyi:22:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
21 | # Should emit in longer unions, even if not directly adjacent.
22 | field3: Literal[1] | Literal[2] | str # Error
@ -34,8 +67,19 @@ PYI030.pyi:22:9: PYI030 Multiple literal members in a union. Use a single litera
23 | field4: str | Literal[1] | Literal[2] # Error
24 | field5: Literal[1] | str | Literal[2] # Error
|
= help: Replace with a single `Literal`
PYI030.pyi:23:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
19 19 |
20 20 |
21 21 | # Should emit in longer unions, even if not directly adjacent.
22 |-field3: Literal[1] | Literal[2] | str # Error
22 |+field3: Literal[1, 2] # Error
23 23 | field4: str | Literal[1] | Literal[2] # Error
24 24 | field5: Literal[1] | str | Literal[2] # Error
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
PYI030.pyi:23:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
21 | # Should emit in longer unions, even if not directly adjacent.
22 | field3: Literal[1] | Literal[2] | str # Error
@ -44,8 +88,19 @@ PYI030.pyi:23:9: PYI030 Multiple literal members in a union. Use a single litera
24 | field5: Literal[1] | str | Literal[2] # Error
25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
= help: Replace with a single `Literal`
PYI030.pyi:24:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
20 20 |
21 21 | # Should emit in longer unions, even if not directly adjacent.
22 22 | field3: Literal[1] | Literal[2] | str # Error
23 |-field4: str | Literal[1] | Literal[2] # Error
23 |+field4: Literal[1, 2] # Error
24 24 | field5: Literal[1] | str | Literal[2] # Error
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
26 26 |
PYI030.pyi:24:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
22 | field3: Literal[1] | Literal[2] | str # Error
23 | field4: str | Literal[1] | Literal[2] # Error
@ -53,8 +108,19 @@ PYI030.pyi:24:9: PYI030 Multiple literal members in a union. Use a single litera
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
= help: Replace with a single `Literal`
PYI030.pyi:25:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
21 21 | # Should emit in longer unions, even if not directly adjacent.
22 22 | field3: Literal[1] | Literal[2] | str # Error
23 23 | field4: str | Literal[1] | Literal[2] # Error
24 |-field5: Literal[1] | str | Literal[2] # Error
24 |+field5: Literal[1, 2] # Error
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
26 26 |
27 27 | # Should emit for non-type unions.
PYI030.pyi:25:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
23 | field4: str | Literal[1] | Literal[2] # Error
24 | field5: Literal[1] | str | Literal[2] # Error
@ -63,8 +129,19 @@ PYI030.pyi:25:9: PYI030 Multiple literal members in a union. Use a single litera
26 |
27 | # Should emit for non-type unions.
|
= help: Replace with a single `Literal`
PYI030.pyi:28:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
22 22 | field3: Literal[1] | Literal[2] | str # Error
23 23 | field4: str | Literal[1] | Literal[2] # Error
24 24 | field5: Literal[1] | str | Literal[2] # Error
25 |-field6: Literal[1] | bool | Literal[2] | str # Error
25 |+field6: Literal[1, 2] # Error
26 26 |
27 27 | # Should emit for non-type unions.
28 28 | field7 = Literal[1] | Literal[2] # Error
PYI030.pyi:28:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
27 | # Should emit for non-type unions.
28 | field7 = Literal[1] | Literal[2] # Error
@ -72,8 +149,19 @@ PYI030.pyi:28:10: PYI030 Multiple literal members in a union. Use a single liter
29 |
30 | # Should emit for parenthesized unions.
|
= help: Replace with a single `Literal`
PYI030.pyi:31:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
26 26 |
27 27 | # Should emit for non-type unions.
28 |-field7 = Literal[1] | Literal[2] # Error
28 |+field7 = Literal[1, 2] # Error
29 29 |
30 30 | # Should emit for parenthesized unions.
31 31 | field8: Literal[1] | (Literal[2] | str) # Error
PYI030.pyi:31:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
30 | # Should emit for parenthesized unions.
31 | field8: Literal[1] | (Literal[2] | str) # Error
@ -81,16 +169,38 @@ PYI030.pyi:31:9: PYI030 Multiple literal members in a union. Use a single litera
32 |
33 | # Should handle user parentheses when fixing.
|
= help: Replace with a single `Literal`
PYI030.pyi:34:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
28 28 | field7 = Literal[1] | Literal[2] # Error
29 29 |
30 30 | # Should emit for parenthesized unions.
31 |-field8: Literal[1] | (Literal[2] | str) # Error
31 |+field8: Literal[1, 2] # Error
32 32 |
33 33 | # Should handle user parentheses when fixing.
34 34 | field9: Literal[1] | (Literal[2] | str) # Error
PYI030.pyi:34:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
33 | # Should handle user parentheses when fixing.
34 | field9: Literal[1] | (Literal[2] | str) # Error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
35 | field10: (Literal[1] | str) | Literal[2] # Error
|
= help: Replace with a single `Literal`
PYI030.pyi:35:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
31 31 | field8: Literal[1] | (Literal[2] | str) # Error
32 32 |
33 33 | # Should handle user parentheses when fixing.
34 |-field9: Literal[1] | (Literal[2] | str) # Error
34 |+field9: Literal[1, 2] # Error
35 35 | field10: (Literal[1] | str) | Literal[2] # Error
36 36 |
37 37 | # Should emit for union in generic parent type.
PYI030.pyi:35:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
33 | # Should handle user parentheses when fixing.
34 | field9: Literal[1] | (Literal[2] | str) # Error
@ -99,8 +209,19 @@ PYI030.pyi:35:10: PYI030 Multiple literal members in a union. Use a single liter
36 |
37 | # Should emit for union in generic parent type.
|
= help: Replace with a single `Literal`
PYI030.pyi:38:15: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
32 32 |
33 33 | # Should handle user parentheses when fixing.
34 34 | field9: Literal[1] | (Literal[2] | str) # Error
35 |-field10: (Literal[1] | str) | Literal[2] # Error
35 |+field10: Literal[1, 2] # Error
36 36 |
37 37 | # Should emit for union in generic parent type.
38 38 | field11: dict[Literal[1] | Literal[2], str] # Error
PYI030.pyi:38:15: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
37 | # Should emit for union in generic parent type.
38 | field11: dict[Literal[1] | Literal[2], str] # Error
@ -108,16 +229,38 @@ PYI030.pyi:38:15: PYI030 Multiple literal members in a union. Use a single liter
39 |
40 | # Should emit for unions with more than two cases
|
= help: Replace with a single `Literal`
PYI030.pyi:41:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3]`
Fix
35 35 | field10: (Literal[1] | str) | Literal[2] # Error
36 36 |
37 37 | # Should emit for union in generic parent type.
38 |-field11: dict[Literal[1] | Literal[2], str] # Error
38 |+field11: dict[Literal[1, 2], str] # Error
39 39 |
40 40 | # Should emit for unions with more than two cases
41 41 | field12: Literal[1] | Literal[2] | Literal[3] # Error
PYI030.pyi:41:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3]`
|
40 | # Should emit for unions with more than two cases
41 | field12: Literal[1] | Literal[2] | Literal[3] # Error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
42 | field13: Literal[1] | Literal[2] | Literal[3] | Literal[4] # Error
|
= help: Replace with a single `Literal`
PYI030.pyi:42:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]`
Fix
38 38 | field11: dict[Literal[1] | Literal[2], str] # Error
39 39 |
40 40 | # Should emit for unions with more than two cases
41 |-field12: Literal[1] | Literal[2] | Literal[3] # Error
41 |+field12: Literal[1, 2, 3] # Error
42 42 | field13: Literal[1] | Literal[2] | Literal[3] | Literal[4] # Error
43 43 |
44 44 | # Should emit for unions with more than two cases, even if not directly adjacent
PYI030.pyi:42:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]`
|
40 | # Should emit for unions with more than two cases
41 | field12: Literal[1] | Literal[2] | Literal[3] # Error
@ -126,8 +269,19 @@ PYI030.pyi:42:10: PYI030 Multiple literal members in a union. Use a single liter
43 |
44 | # Should emit for unions with more than two cases, even if not directly adjacent
|
= help: Replace with a single `Literal`
PYI030.pyi:45:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3]`
Fix
39 39 |
40 40 | # Should emit for unions with more than two cases
41 41 | field12: Literal[1] | Literal[2] | Literal[3] # Error
42 |-field13: Literal[1] | Literal[2] | Literal[3] | Literal[4] # Error
42 |+field13: Literal[1, 2, 3, 4] # Error
43 43 |
44 44 | # Should emit for unions with more than two cases, even if not directly adjacent
45 45 | field14: Literal[1] | Literal[2] | str | Literal[3] # Error
PYI030.pyi:45:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3]`
|
44 | # Should emit for unions with more than two cases, even if not directly adjacent
45 | field14: Literal[1] | Literal[2] | str | Literal[3] # Error
@ -135,8 +289,19 @@ PYI030.pyi:45:10: PYI030 Multiple literal members in a union. Use a single liter
46 |
47 | # Should emit for unions with mixed literal internal types
|
= help: Replace with a single `Literal`
PYI030.pyi:48:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, "foo", True]`
Fix
42 42 | field13: Literal[1] | Literal[2] | Literal[3] | Literal[4] # Error
43 43 |
44 44 | # Should emit for unions with more than two cases, even if not directly adjacent
45 |-field14: Literal[1] | Literal[2] | str | Literal[3] # Error
45 |+field14: Literal[1, 2, 3] # Error
46 46 |
47 47 | # Should emit for unions with mixed literal internal types
48 48 | field15: Literal[1] | Literal["foo"] | Literal[True] # Error
PYI030.pyi:48:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, "foo", True]`
|
47 | # Should emit for unions with mixed literal internal types
48 | field15: Literal[1] | Literal["foo"] | Literal[True] # Error
@ -144,8 +309,19 @@ PYI030.pyi:48:10: PYI030 Multiple literal members in a union. Use a single liter
49 |
50 | # Shouldn't emit for duplicate field types with same value; covered by Y016
|
= help: Replace with a single `Literal`
PYI030.pyi:51:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 1]`
Fix
45 45 | field14: Literal[1] | Literal[2] | str | Literal[3] # Error
46 46 |
47 47 | # Should emit for unions with mixed literal internal types
48 |-field15: Literal[1] | Literal["foo"] | Literal[True] # Error
48 |+field15: Literal[1, "foo", True] # Error
49 49 |
50 50 | # Shouldn't emit for duplicate field types with same value; covered by Y016
51 51 | field16: Literal[1] | Literal[1] # OK
PYI030.pyi:51:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 1]`
|
50 | # Shouldn't emit for duplicate field types with same value; covered by Y016
51 | field16: Literal[1] | Literal[1] # OK
@ -153,8 +329,19 @@ PYI030.pyi:51:10: PYI030 Multiple literal members in a union. Use a single liter
52 |
53 | # Shouldn't emit if in new parent type
|
= help: Replace with a single `Literal`
PYI030.pyi:60:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
48 48 | field15: Literal[1] | Literal["foo"] | Literal[True] # Error
49 49 |
50 50 | # Shouldn't emit for duplicate field types with same value; covered by Y016
51 |-field16: Literal[1] | Literal[1] # OK
51 |+field16: Literal[1, 1] # OK
52 52 |
53 53 | # Shouldn't emit if in new parent type
54 54 | field17: Literal[1] | dict[Literal[2], str] # OK
PYI030.pyi:60:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
59 | # Should respect name of literal type used
60 | field19: typing.Literal[1] | typing.Literal[2] # Error
@ -162,8 +349,19 @@ PYI030.pyi:60:10: PYI030 Multiple literal members in a union. Use a single liter
61 |
62 | # Should emit in cases with newlines
|
= help: Replace with a single `Literal`
PYI030.pyi:63:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
57 57 | field18: dict[Literal[1], Literal[2]] # OK
58 58 |
59 59 | # Should respect name of literal type used
60 |-field19: typing.Literal[1] | typing.Literal[2] # Error
60 |+field19: Literal[1, 2] # Error
61 61 |
62 62 | # Should emit in cases with newlines
63 63 | field20: typing.Union[
PYI030.pyi:63:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
62 | # Should emit in cases with newlines
63 | field20: typing.Union[
@ -177,8 +375,24 @@ PYI030.pyi:63:10: PYI030 Multiple literal members in a union. Use a single liter
69 |
70 | # Should handle multiple unions with multiple members
|
= help: Replace with a single `Literal`
PYI030.pyi:71:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]`
Fix
60 60 | field19: typing.Literal[1] | typing.Literal[2] # Error
61 61 |
62 62 | # Should emit in cases with newlines
63 |-field20: typing.Union[
64 |- Literal[
65 |- 1 # test
66 |- ],
67 |- Literal[2],
68 |-] # Error, newline and comment will not be emitted in message
63 |+field20: Literal[1, 2] # Error, newline and comment will not be emitted in message
69 64 |
70 65 | # Should handle multiple unions with multiple members
71 66 | field21: Literal[1, 2] | Literal[3, 4] # Error
PYI030.pyi:71:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]`
|
70 | # Should handle multiple unions with multiple members
71 | field21: Literal[1, 2] | Literal[3, 4] # Error
@ -186,8 +400,19 @@ PYI030.pyi:71:10: PYI030 Multiple literal members in a union. Use a single liter
72 |
73 | # Should emit in cases with `typing.Union` instead of `|`
|
= help: Replace with a single `Literal`
PYI030.pyi:74:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
68 68 | ] # Error, newline and comment will not be emitted in message
69 69 |
70 70 | # Should handle multiple unions with multiple members
71 |-field21: Literal[1, 2] | Literal[3, 4] # Error
71 |+field21: Literal[1, 2, 3, 4] # Error
72 72 |
73 73 | # Should emit in cases with `typing.Union` instead of `|`
74 74 | field22: typing.Union[Literal[1], Literal[2]] # Error
PYI030.pyi:74:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
73 | # Should emit in cases with `typing.Union` instead of `|`
74 | field22: typing.Union[Literal[1], Literal[2]] # Error
@ -195,8 +420,19 @@ PYI030.pyi:74:10: PYI030 Multiple literal members in a union. Use a single liter
75 |
76 | # Should emit in cases with `typing_extensions.Literal`
|
= help: Replace with a single `Literal`
PYI030.pyi:77:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
71 71 | field21: Literal[1, 2] | Literal[3, 4] # Error
72 72 |
73 73 | # Should emit in cases with `typing.Union` instead of `|`
74 |-field22: typing.Union[Literal[1], Literal[2]] # Error
74 |+field22: Literal[1, 2] # Error
75 75 |
76 76 | # Should emit in cases with `typing_extensions.Literal`
77 77 | field23: typing_extensions.Literal[1] | typing_extensions.Literal[2] # Error
PYI030.pyi:77:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
76 | # Should emit in cases with `typing_extensions.Literal`
77 | field23: typing_extensions.Literal[1] | typing_extensions.Literal[2] # Error
@ -204,8 +440,19 @@ PYI030.pyi:77:10: PYI030 Multiple literal members in a union. Use a single liter
78 |
79 | # Should emit in cases with nested `typing.Union`
|
= help: Replace with a single `Literal`
PYI030.pyi:80:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
74 74 | field22: typing.Union[Literal[1], Literal[2]] # Error
75 75 |
76 76 | # Should emit in cases with `typing_extensions.Literal`
77 |-field23: typing_extensions.Literal[1] | typing_extensions.Literal[2] # Error
77 |+field23: Literal[1, 2] # Error
78 78 |
79 79 | # Should emit in cases with nested `typing.Union`
80 80 | field24: typing.Union[Literal[1], typing.Union[Literal[2], str]] # Error
PYI030.pyi:80:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
79 | # Should emit in cases with nested `typing.Union`
80 | field24: typing.Union[Literal[1], typing.Union[Literal[2], str]] # Error
@ -213,8 +460,19 @@ PYI030.pyi:80:10: PYI030 Multiple literal members in a union. Use a single liter
81 |
82 | # Should emit in cases with mixed `typing.Union` and `|`
|
= help: Replace with a single `Literal`
PYI030.pyi:83:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
Fix
77 77 | field23: typing_extensions.Literal[1] | typing_extensions.Literal[2] # Error
78 78 |
79 79 | # Should emit in cases with nested `typing.Union`
80 |-field24: typing.Union[Literal[1], typing.Union[Literal[2], str]] # Error
80 |+field24: Literal[1, 2] # Error
81 81 |
82 82 | # Should emit in cases with mixed `typing.Union` and `|`
83 83 | field25: typing.Union[Literal[1], Literal[2] | str] # Error
PYI030.pyi:83:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
82 | # Should emit in cases with mixed `typing.Union` and `|`
83 | field25: typing.Union[Literal[1], Literal[2] | str] # Error
@ -222,12 +480,31 @@ PYI030.pyi:83:10: PYI030 Multiple literal members in a union. Use a single liter
84 |
85 | # Should emit only once in cases with multiple nested `typing.Union`
|
= help: Replace with a single `Literal`
PYI030.pyi:86:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]`
Fix
80 80 | field24: typing.Union[Literal[1], typing.Union[Literal[2], str]] # Error
81 81 |
82 82 | # Should emit in cases with mixed `typing.Union` and `|`
83 |-field25: typing.Union[Literal[1], Literal[2] | str] # Error
83 |+field25: Literal[1, 2] # Error
84 84 |
85 85 | # Should emit only once in cases with multiple nested `typing.Union`
86 86 | field24: typing.Union[Literal[1], typing.Union[Literal[2], typing.Union[Literal[3], Literal[4]]]] # Error
PYI030.pyi:86:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]`
|
85 | # Should emit only once in cases with multiple nested `typing.Union`
86 | field24: typing.Union[Literal[1], typing.Union[Literal[2], typing.Union[Literal[3], Literal[4]]]] # Error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
= help: Replace with a single `Literal`
Fix
83 83 | field25: typing.Union[Literal[1], Literal[2] | str] # Error
84 84 |
85 85 | # Should emit only once in cases with multiple nested `typing.Union`
86 |-field24: typing.Union[Literal[1], typing.Union[Literal[2], typing.Union[Literal[3], Literal[4]]]] # Error
86 |+field24: Literal[1, 2, 3, 4] # Error