[`flake8-comprehensions`] Handled special case for `C401` which also matches `C416` (#10596)

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

Similar to #10419, there was a case where there is a collision of C401
and C416 (as discussed in #10101).
Fixed this by implementing short-circuit for the comprehension of the
form `{x for x in foo}`.

## Test Plan

<!-- How was it tested? -->

Extended `C401.py` with the case where `set` is not builtin function,
and divided the case where the short-circuit should occur.
Removed the last testcase of `print(f"{ {set(a for a in 'abc')} }")`
test as this is invalid as a python code, but should I keep this?
This commit is contained in:
hikaru-kajita 2024-03-26 12:54:58 +09:00 committed by GitHub
parent 80b46889ed
commit a28776e3aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 286 additions and 233 deletions

View File

@ -1,20 +1,30 @@
x = set(x for x in range(3))
x = set(x for x in range(3))
y = f"{set(a if a < 6 else 0 for a in range(3))}"
_ = "{}".format(set(a if a < 6 else 0 for a in range(3)))
print(f"Hello {set(a for a in range(3))} World")
# Cannot conbime with C416. Should use set comprehension here.
even_nums = set(2 * x for x in range(3))
odd_nums = set(
2 * x + 1 for x in range(3)
)
small_nums = f"{set(a if a < 6 else 0 for a in range(3))}"
def f(x):
return x
print(f'Hello {set(a for a in "abc")} World')
print(f"Hello {set(a for a in 'abc')} World")
print(f"Hello {set(f(a) for a in 'abc')} World")
print(f"Hello { set(f(a) for a in 'abc') } World")
# Short-circuit case, combine with C416 and should produce x = set(range(3))
x = set(x for x in range(3))
x = set(
x for x in range(3)
)
print(f"Hello {set(a for a in range(3))} World")
print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
# The fix generated for this diagnostic is incorrect, as we add additional space
# around the set comprehension.
print(f"{ {set(a for a in 'abc')} }")
# Not built-in set.
def set(*args, **kwargs):
return None
set(2 * x for x in range(3))
set(x for x in range(3))

View File

@ -1,6 +1,8 @@
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast as ast;
use ruff_python_ast::comparable::ComparableExpr;
use ruff_python_ast::ExprGenerator;
use ruff_text_size::{Ranged, TextSize};
use crate::checkers::ast::Checker;
@ -10,37 +12,53 @@ use super::helpers;
/// ## What it does
/// Checks for unnecessary generators that can be rewritten as `set`
/// comprehensions.
/// comprehensions (or with `set` directly).
///
/// ## Why is this bad?
/// It is unnecessary to use `set` around a generator expression, since
/// there are equivalent comprehensions for these types. Using a
/// comprehension is clearer and more idiomatic.
///
/// Further, if the comprehension can be removed entirely, as in the case of
/// `set(x for x in foo)`, it's better to use `set(foo)` directly, since it's
/// even more direct.
///
/// ## Examples
/// ```python
/// set(f(x) for x in foo)
/// set(x for x in foo)
/// ```
///
/// Use instead:
/// ```python
/// {f(x) for x in foo}
/// set(foo)
/// ```
///
/// ## Fix safety
/// This rule's fix is marked as unsafe, as it may occasionally drop comments
/// when rewriting the call. In most cases, though, comments will be preserved.
#[violation]
pub struct UnnecessaryGeneratorSet;
pub struct UnnecessaryGeneratorSet {
short_circuit: bool,
}
impl AlwaysFixableViolation for UnnecessaryGeneratorSet {
#[derive_message_formats]
fn message(&self) -> String {
format!("Unnecessary generator (rewrite as a `set` comprehension)")
if self.short_circuit {
format!("Unnecessary generator (rewrite using `set()`")
} else {
format!("Unnecessary generator (rewrite as a `set` comprehension)")
}
}
fn fix_title(&self) -> String {
"Rewrite as a `set` comprehension".to_string()
if self.short_circuit {
"Rewrite using `set()`".to_string()
} else {
"Rewrite as a `set` comprehension".to_string()
}
}
}
@ -57,28 +75,59 @@ pub(crate) fn unnecessary_generator_set(checker: &mut Checker, call: &ast::ExprC
if !checker.semantic().is_builtin("set") {
return;
}
if argument.is_generator_expr() {
let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorSet, call.range());
// Convert `set(x for x in y)` to `{x for x in y}`.
diagnostic.set_fix({
// Replace `set(` with `}`.
let call_start = Edit::replacement(
pad_start("{", call.range(), checker.locator(), checker.semantic()),
call.start(),
call.arguments.start() + TextSize::from(1),
);
let Some(ExprGenerator {
elt, generators, ..
}) = argument.as_generator_expr()
else {
return;
};
// Replace `)` with `}`.
let call_end = Edit::replacement(
pad_end("}", call.range(), checker.locator(), checker.semantic()),
call.arguments.end() - TextSize::from(1),
call.end(),
);
Fix::unsafe_edits(call_start, [call_end])
});
checker.diagnostics.push(diagnostic);
// Short-circuit: given `set(x for x in y)`, generate `set(y)` (in lieu of `{x for x in y}`).
if let [generator] = generators.as_slice() {
if generator.ifs.is_empty() && !generator.is_async {
if ComparableExpr::from(elt) == ComparableExpr::from(&generator.target) {
let mut diagnostic = Diagnostic::new(
UnnecessaryGeneratorSet {
short_circuit: true,
},
call.range(),
);
let iterator = format!("set({})", checker.locator().slice(generator.iter.range()));
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
iterator,
call.range(),
)));
checker.diagnostics.push(diagnostic);
return;
}
}
}
// Convert `set(f(x) for x in y)` to `{f(x) for x in y}`.
let mut diagnostic = Diagnostic::new(
UnnecessaryGeneratorSet {
short_circuit: false,
},
call.range(),
);
diagnostic.set_fix({
// Replace `set(` with `}`.
let call_start = Edit::replacement(
pad_start("{", call.range(), checker.locator(), checker.semantic()),
call.start(),
call.arguments.start() + TextSize::from(1),
);
// Replace `)` with `}`.
let call_end = Edit::replacement(
pad_end("}", call.range(), checker.locator(), checker.semantic()),
call.arguments.end() - TextSize::from(1),
call.end(),
);
Fix::unsafe_edits(call_start, [call_end])
});
checker.diagnostics.push(diagnostic);
}

View File

@ -1,255 +1,249 @@
---
source: crates/ruff_linter/src/rules/flake8_comprehensions/mod.rs
---
C401.py:1:5: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
C401.py:2:13: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
|
1 | x = set(x for x in range(3))
| ^^^^^^^^^^^^^^^^^^^^^^^^ C401
2 | x = set(x for x in range(3))
3 | y = f"{set(a if a < 6 else 0 for a in range(3))}"
1 | # Cannot conbime with C416. Should use set comprehension here.
2 | even_nums = set(2 * x for x in range(3))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C401
3 | odd_nums = set(
4 | 2 * x + 1 for x in range(3)
|
= help: Rewrite as a `set` comprehension
Unsafe fix
1 |-x = set(x for x in range(3))
1 |+x = {x for x in range(3)}
2 2 | x = set(x for x in range(3))
3 3 | y = f"{set(a if a < 6 else 0 for a in range(3))}"
4 4 | _ = "{}".format(set(a if a < 6 else 0 for a in range(3)))
1 1 | # Cannot conbime with C416. Should use set comprehension here.
2 |-even_nums = set(2 * x for x in range(3))
2 |+even_nums = {2 * x for x in range(3)}
3 3 | odd_nums = set(
4 4 | 2 * x + 1 for x in range(3)
5 5 | )
C401.py:2:5: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
C401.py:3:12: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
|
1 | x = set(x for x in range(3))
2 | x = set(x for x in range(3))
| ^^^^^^^^^^^^^^^^^^^^^^^^ C401
3 | y = f"{set(a if a < 6 else 0 for a in range(3))}"
4 | _ = "{}".format(set(a if a < 6 else 0 for a in range(3)))
1 | # Cannot conbime with C416. Should use set comprehension here.
2 | even_nums = set(2 * x for x in range(3))
3 | odd_nums = set(
| ____________^
4 | | 2 * x + 1 for x in range(3)
5 | | )
| |_^ C401
6 | small_nums = f"{set(a if a < 6 else 0 for a in range(3))}"
|
= help: Rewrite as a `set` comprehension
Unsafe fix
1 1 | x = set(x for x in range(3))
2 |-x = set(x for x in range(3))
2 |+x = {x for x in range(3)}
3 3 | y = f"{set(a if a < 6 else 0 for a in range(3))}"
4 4 | _ = "{}".format(set(a if a < 6 else 0 for a in range(3)))
5 5 | print(f"Hello {set(a for a in range(3))} World")
C401.py:3:8: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
|
1 | x = set(x for x in range(3))
2 | x = set(x for x in range(3))
3 | y = f"{set(a if a < 6 else 0 for a in range(3))}"
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C401
4 | _ = "{}".format(set(a if a < 6 else 0 for a in range(3)))
5 | print(f"Hello {set(a for a in range(3))} World")
|
= help: Rewrite as a `set` comprehension
Unsafe fix
1 1 | x = set(x for x in range(3))
2 2 | x = set(x for x in range(3))
3 |-y = f"{set(a if a < 6 else 0 for a in range(3))}"
3 |+y = f"{ {a if a < 6 else 0 for a in range(3)} }"
4 4 | _ = "{}".format(set(a if a < 6 else 0 for a in range(3)))
5 5 | print(f"Hello {set(a for a in range(3))} World")
6 6 |
C401.py:4:17: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
|
2 | x = set(x for x in range(3))
3 | y = f"{set(a if a < 6 else 0 for a in range(3))}"
4 | _ = "{}".format(set(a if a < 6 else 0 for a in range(3)))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C401
5 | print(f"Hello {set(a for a in range(3))} World")
|
= help: Rewrite as a `set` comprehension
Unsafe fix
1 1 | x = set(x for x in range(3))
2 2 | x = set(x for x in range(3))
3 3 | y = f"{set(a if a < 6 else 0 for a in range(3))}"
4 |-_ = "{}".format(set(a if a < 6 else 0 for a in range(3)))
4 |+_ = "{}".format({a if a < 6 else 0 for a in range(3)})
5 5 | print(f"Hello {set(a for a in range(3))} World")
6 6 |
7 7 |
C401.py:5:16: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
|
3 | y = f"{set(a if a < 6 else 0 for a in range(3))}"
4 | _ = "{}".format(set(a if a < 6 else 0 for a in range(3)))
5 | print(f"Hello {set(a for a in range(3))} World")
| ^^^^^^^^^^^^^^^^^^^^^^^^ C401
|
= help: Rewrite as a `set` comprehension
Unsafe fix
2 2 | x = set(x for x in range(3))
3 3 | y = f"{set(a if a < 6 else 0 for a in range(3))}"
4 4 | _ = "{}".format(set(a if a < 6 else 0 for a in range(3)))
5 |-print(f"Hello {set(a for a in range(3))} World")
5 |+print(f"Hello { {a for a in range(3)} } World")
6 6 |
1 1 | # Cannot conbime with C416. Should use set comprehension here.
2 2 | even_nums = set(2 * x for x in range(3))
3 |-odd_nums = set(
3 |+odd_nums = {
4 4 | 2 * x + 1 for x in range(3)
5 |-)
5 |+}
6 6 | small_nums = f"{set(a if a < 6 else 0 for a in range(3))}"
7 7 |
8 8 | def f(x):
C401.py:12:16: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
C401.py:6:17: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
|
4 | 2 * x + 1 for x in range(3)
5 | )
6 | small_nums = f"{set(a if a < 6 else 0 for a in range(3))}"
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C401
7 |
8 | def f(x):
|
= help: Rewrite as a `set` comprehension
Unsafe fix
3 3 | odd_nums = set(
4 4 | 2 * x + 1 for x in range(3)
5 5 | )
6 |-small_nums = f"{set(a if a < 6 else 0 for a in range(3))}"
6 |+small_nums = f"{ {a if a < 6 else 0 for a in range(3)} }"
7 7 |
8 8 | def f(x):
9 9 | return x
C401.py:11:16: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
|
12 | print(f'Hello {set(a for a in "abc")} World')
| ^^^^^^^^^^^^^^^^^^^^^ C401
13 | print(f"Hello {set(a for a in 'abc')} World")
14 | print(f"Hello {set(f(a) for a in 'abc')} World")
9 | return x
10 |
11 | print(f"Hello {set(f(a) for a in 'abc')} World")
| ^^^^^^^^^^^^^^^^^^^^^^^^ C401
12 | print(f"Hello { set(f(a) for a in 'abc') } World")
|
= help: Rewrite as a `set` comprehension
Unsafe fix
8 8 | def f(x):
9 9 | return x
10 10 |
11 |-print(f"Hello {set(f(a) for a in 'abc')} World")
11 |+print(f"Hello { {f(a) for a in 'abc'} } World")
12 12 | print(f"Hello { set(f(a) for a in 'abc') } World")
13 13 |
14 14 |
C401.py:12:17: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
|
11 | print(f"Hello {set(f(a) for a in 'abc')} World")
12 | print(f"Hello { set(f(a) for a in 'abc') } World")
| ^^^^^^^^^^^^^^^^^^^^^^^^ C401
|
= help: Rewrite as a `set` comprehension
Unsafe fix
9 9 | return x
10 10 |
11 11 |
12 |-print(f'Hello {set(a for a in "abc")} World')
12 |+print(f'Hello { {a for a in "abc"} } World')
13 13 | print(f"Hello {set(a for a in 'abc')} World")
14 14 | print(f"Hello {set(f(a) for a in 'abc')} World")
15 15 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
11 11 | print(f"Hello {set(f(a) for a in 'abc')} World")
12 |-print(f"Hello { set(f(a) for a in 'abc') } World")
12 |+print(f"Hello { {f(a) for a in 'abc'} } World")
13 13 |
14 14 |
15 15 | # Short-circuit case, combine with C416 and should produce x = set(range(3))
C401.py:13:16: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
C401.py:16:5: C401 [*] Unnecessary generator (rewrite using `set()`
|
12 | print(f'Hello {set(a for a in "abc")} World')
13 | print(f"Hello {set(a for a in 'abc')} World")
| ^^^^^^^^^^^^^^^^^^^^^ C401
14 | print(f"Hello {set(f(a) for a in 'abc')} World")
15 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
15 | # Short-circuit case, combine with C416 and should produce x = set(range(3))
16 | x = set(x for x in range(3))
| ^^^^^^^^^^^^^^^^^^^^^^^^ C401
17 | x = set(
18 | x for x in range(3)
|
= help: Rewrite as a `set` comprehension
= help: Rewrite using `set()`
Unsafe fix
10 10 |
11 11 |
12 12 | print(f'Hello {set(a for a in "abc")} World')
13 |-print(f"Hello {set(a for a in 'abc')} World")
13 |+print(f"Hello { {a for a in 'abc'} } World")
14 14 | print(f"Hello {set(f(a) for a in 'abc')} World")
15 15 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
16 16 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
13 13 |
14 14 |
15 15 | # Short-circuit case, combine with C416 and should produce x = set(range(3))
16 |-x = set(x for x in range(3))
16 |+x = set(range(3))
17 17 | x = set(
18 18 | x for x in range(3)
19 19 | )
C401.py:14:16: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
C401.py:17:5: C401 [*] Unnecessary generator (rewrite using `set()`
|
12 | print(f'Hello {set(a for a in "abc")} World')
13 | print(f"Hello {set(a for a in 'abc')} World")
14 | print(f"Hello {set(f(a) for a in 'abc')} World")
15 | # Short-circuit case, combine with C416 and should produce x = set(range(3))
16 | x = set(x for x in range(3))
17 | x = set(
| _____^
18 | | x for x in range(3)
19 | | )
| |_^ C401
20 | print(f"Hello {set(a for a in range(3))} World")
21 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
|
= help: Rewrite using `set()`
Unsafe fix
14 14 |
15 15 | # Short-circuit case, combine with C416 and should produce x = set(range(3))
16 16 | x = set(x for x in range(3))
17 |-x = set(
18 |- x for x in range(3)
19 |-)
17 |+x = set(range(3))
20 18 | print(f"Hello {set(a for a in range(3))} World")
21 19 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
22 20 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
C401.py:20:16: C401 [*] Unnecessary generator (rewrite using `set()`
|
18 | x for x in range(3)
19 | )
20 | print(f"Hello {set(a for a in range(3))} World")
| ^^^^^^^^^^^^^^^^^^^^^^^^ C401
15 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
16 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
21 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
22 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
|
= help: Rewrite as a `set` comprehension
= help: Rewrite using `set()`
Unsafe fix
11 11 |
12 12 | print(f'Hello {set(a for a in "abc")} World')
13 13 | print(f"Hello {set(a for a in 'abc')} World")
14 |-print(f"Hello {set(f(a) for a in 'abc')} World")
14 |+print(f"Hello { {f(a) for a in 'abc'} } World")
15 15 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
16 16 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
17 17 |
17 17 | x = set(
18 18 | x for x in range(3)
19 19 | )
20 |-print(f"Hello {set(a for a in range(3))} World")
20 |+print(f"Hello {set(range(3))} World")
21 21 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
22 22 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
23 23 |
C401.py:15:10: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
C401.py:21:10: C401 [*] Unnecessary generator (rewrite using `set()`
|
13 | print(f"Hello {set(a for a in 'abc')} World")
14 | print(f"Hello {set(f(a) for a in 'abc')} World")
15 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
19 | )
20 | print(f"Hello {set(a for a in range(3))} World")
21 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
| ^^^^^^^^^^^^^^^^^^^^^ C401
16 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
22 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
|
= help: Rewrite as a `set` comprehension
= help: Rewrite using `set()`
Unsafe fix
12 12 | print(f'Hello {set(a for a in "abc")} World')
13 13 | print(f"Hello {set(a for a in 'abc')} World")
14 14 | print(f"Hello {set(f(a) for a in 'abc')} World")
15 |-print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
15 |+print(f"{ {a for a in 'abc'} - set(a for a in 'ab')}")
16 16 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
17 17 |
18 18 | # The fix generated for this diagnostic is incorrect, as we add additional space
18 18 | x for x in range(3)
19 19 | )
20 20 | print(f"Hello {set(a for a in range(3))} World")
21 |-print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
21 |+print(f"{set('abc') - set(a for a in 'ab')}")
22 22 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
23 23 |
24 24 |
C401.py:15:34: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
C401.py:21:34: C401 [*] Unnecessary generator (rewrite using `set()`
|
13 | print(f"Hello {set(a for a in 'abc')} World")
14 | print(f"Hello {set(f(a) for a in 'abc')} World")
15 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
19 | )
20 | print(f"Hello {set(a for a in range(3))} World")
21 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
| ^^^^^^^^^^^^^^^^^^^^ C401
16 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
22 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
|
= help: Rewrite as a `set` comprehension
= help: Rewrite using `set()`
Unsafe fix
12 12 | print(f'Hello {set(a for a in "abc")} World')
13 13 | print(f"Hello {set(a for a in 'abc')} World")
14 14 | print(f"Hello {set(f(a) for a in 'abc')} World")
15 |-print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
15 |+print(f"{set(a for a in 'abc') - {a for a in 'ab'} }")
16 16 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
17 17 |
18 18 | # The fix generated for this diagnostic is incorrect, as we add additional space
18 18 | x for x in range(3)
19 19 | )
20 20 | print(f"Hello {set(a for a in range(3))} World")
21 |-print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
21 |+print(f"{set(a for a in 'abc') - set('ab')}")
22 22 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
23 23 |
24 24 |
C401.py:16:11: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
C401.py:22:11: C401 [*] Unnecessary generator (rewrite using `set()`
|
14 | print(f"Hello {set(f(a) for a in 'abc')} World")
15 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
16 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
20 | print(f"Hello {set(a for a in range(3))} World")
21 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
22 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
| ^^^^^^^^^^^^^^^^^^^^^ C401
17 |
18 | # The fix generated for this diagnostic is incorrect, as we add additional space
|
= help: Rewrite as a `set` comprehension
= help: Rewrite using `set()`
Unsafe fix
13 13 | print(f"Hello {set(a for a in 'abc')} World")
14 14 | print(f"Hello {set(f(a) for a in 'abc')} World")
15 15 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
16 |-print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
16 |+print(f"{ {a for a in 'abc'} - set(a for a in 'ab') }")
17 17 |
18 18 | # The fix generated for this diagnostic is incorrect, as we add additional space
19 19 | # around the set comprehension.
19 19 | )
20 20 | print(f"Hello {set(a for a in range(3))} World")
21 21 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
22 |-print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
22 |+print(f"{ set('abc') - set(a for a in 'ab') }")
23 23 |
24 24 |
25 25 | # Not built-in set.
C401.py:16:35: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
C401.py:22:35: C401 [*] Unnecessary generator (rewrite using `set()`
|
14 | print(f"Hello {set(f(a) for a in 'abc')} World")
15 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
16 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
20 | print(f"Hello {set(a for a in range(3))} World")
21 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
22 | print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
| ^^^^^^^^^^^^^^^^^^^^ C401
17 |
18 | # The fix generated for this diagnostic is incorrect, as we add additional space
|
= help: Rewrite as a `set` comprehension
= help: Rewrite using `set()`
Unsafe fix
13 13 | print(f"Hello {set(a for a in 'abc')} World")
14 14 | print(f"Hello {set(f(a) for a in 'abc')} World")
15 15 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
16 |-print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
16 |+print(f"{ set(a for a in 'abc') - {a for a in 'ab'} }")
17 17 |
18 18 | # The fix generated for this diagnostic is incorrect, as we add additional space
19 19 | # around the set comprehension.
C401.py:20:12: C401 [*] Unnecessary generator (rewrite as a `set` comprehension)
|
18 | # The fix generated for this diagnostic is incorrect, as we add additional space
19 | # around the set comprehension.
20 | print(f"{ {set(a for a in 'abc')} }")
| ^^^^^^^^^^^^^^^^^^^^^ C401
|
= help: Rewrite as a `set` comprehension
Unsafe fix
17 17 |
18 18 | # The fix generated for this diagnostic is incorrect, as we add additional space
19 19 | # around the set comprehension.
20 |-print(f"{ {set(a for a in 'abc')} }")
20 |+print(f"{ { {a for a in 'abc'} } }")
19 19 | )
20 20 | print(f"Hello {set(a for a in range(3))} World")
21 21 | print(f"{set(a for a in 'abc') - set(a for a in 'ab')}")
22 |-print(f"{ set(a for a in 'abc') - set(a for a in 'ab') }")
22 |+print(f"{ set(a for a in 'abc') - set('ab') }")
23 23 |
24 24 |
25 25 | # Not built-in set.