[perflint] fix missing parentheses for lambda and ternary conditions (PERF401, PERF403) (#18412)

Closes #18405
This commit is contained in:
chiri 2025-06-05 17:57:08 +03:00 committed by GitHub
parent 74a4e9af3d
commit c0bb83b882
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 172 additions and 9 deletions

View file

@ -266,3 +266,15 @@ def f():
result = list() # this should be replaced with a comprehension result = list() # this should be replaced with a comprehension
for i in values: for i in values:
result.append(i + 1) # PERF401 result.append(i + 1) # PERF401
def f():
src = [1]
dst = []
for i in src:
if True if True else False:
dst.append(i)
for i in src:
if lambda: 0:
dst.append(i)

View file

@ -151,3 +151,16 @@ def foo():
result = {} result = {}
for idx, name in indices, fruit: for idx, name in indices, fruit:
result[name] = idx # PERF403 result[name] = idx # PERF403
def foo():
src = (("x", 1),)
dst = {}
for k, v in src:
if True if True else False:
dst[k] = v
for k, v in src:
if lambda: 0:
dst[k] = v

View file

@ -346,10 +346,11 @@ fn convert_to_dict_comprehension(
// since if the assignment expression appears // since if the assignment expression appears
// internally (e.g. as an operand in a boolean // internally (e.g. as an operand in a boolean
// operation) then it will already be parenthesized. // operation) then it will already be parenthesized.
if test.is_named_expr() { match test {
format!(" if ({})", locator.slice(test.range())) Expr::Named(_) | Expr::If(_) | Expr::Lambda(_) => {
} else { format!(" if ({})", locator.slice(test.range()))
format!(" if {}", locator.slice(test.range())) }
_ => format!(" if {}", locator.slice(test.range())),
} }
} }
None => String::new(), None => String::new(),

View file

@ -358,7 +358,7 @@ fn convert_to_list_extend(
fix_type: ComprehensionType, fix_type: ComprehensionType,
binding: &Binding, binding: &Binding,
for_stmt: &ast::StmtFor, for_stmt: &ast::StmtFor,
if_test: Option<&ast::Expr>, if_test: Option<&Expr>,
to_append: &Expr, to_append: &Expr,
checker: &Checker, checker: &Checker,
) -> Result<Fix> { ) -> Result<Fix> {
@ -374,10 +374,11 @@ fn convert_to_list_extend(
// since if the assignment expression appears // since if the assignment expression appears
// internally (e.g. as an operand in a boolean // internally (e.g. as an operand in a boolean
// operation) then it will already be parenthesized. // operation) then it will already be parenthesized.
if test.is_named_expr() { match test {
format!(" if ({})", locator.slice(test.range())) Expr::Named(_) | Expr::If(_) | Expr::Lambda(_) => {
} else { format!(" if ({})", locator.slice(test.range()))
format!(" if {}", locator.slice(test.range())) }
_ => format!(" if {}", locator.slice(test.range())),
} }
} }
None => String::new(), None => String::new(),

View file

@ -219,5 +219,27 @@ PERF401.py:268:9: PERF401 Use a list comprehension to create a transformed list
267 | for i in values: 267 | for i in values:
268 | result.append(i + 1) # PERF401 268 | result.append(i + 1) # PERF401
| ^^^^^^^^^^^^^^^^^^^^ PERF401 | ^^^^^^^^^^^^^^^^^^^^ PERF401
269 |
270 | def f():
| |
= help: Replace for loop with list comprehension = help: Replace for loop with list comprehension
PERF401.py:276:13: PERF401 Use a list comprehension to create a transformed list
|
274 | for i in src:
275 | if True if True else False:
276 | dst.append(i)
| ^^^^^^^^^^^^^ PERF401
277 |
278 | for i in src:
|
= help: Replace for loop with list comprehension
PERF401.py:280:13: PERF401 Use `list.extend` to create a transformed list
|
278 | for i in src:
279 | if lambda: 0:
280 | dst.append(i)
| ^^^^^^^^^^^^^ PERF401
|
= help: Replace for loop with list.extend

View file

@ -128,3 +128,23 @@ PERF403.py:153:9: PERF403 Use a dictionary comprehension instead of a for-loop
| ^^^^^^^^^^^^^^^^^^ PERF403 | ^^^^^^^^^^^^^^^^^^ PERF403
| |
= help: Replace for loop with dict comprehension = help: Replace for loop with dict comprehension
PERF403.py:162:13: PERF403 Use a dictionary comprehension instead of a for-loop
|
160 | for k, v in src:
161 | if True if True else False:
162 | dst[k] = v
| ^^^^^^^^^^ PERF403
163 |
164 | for k, v in src:
|
= help: Replace for loop with dict comprehension
PERF403.py:166:13: PERF403 Use a dictionary comprehension instead of a for-loop
|
164 | for k, v in src:
165 | if lambda: 0:
166 | dst[k] = v
| ^^^^^^^^^^ PERF403
|
= help: Replace for loop with dict comprehension

View file

@ -517,6 +517,8 @@ PERF401.py:268:9: PERF401 [*] Use a list comprehension to create a transformed l
267 | for i in values: 267 | for i in values:
268 | result.append(i + 1) # PERF401 268 | result.append(i + 1) # PERF401
| ^^^^^^^^^^^^^^^^^^^^ PERF401 | ^^^^^^^^^^^^^^^^^^^^ PERF401
269 |
270 | def f():
| |
= help: Replace for loop with list comprehension = help: Replace for loop with list comprehension
@ -529,3 +531,49 @@ PERF401.py:268:9: PERF401 [*] Use a list comprehension to create a transformed l
268 |- result.append(i + 1) # PERF401 268 |- result.append(i + 1) # PERF401
266 |+ # this should be replaced with a comprehension 266 |+ # this should be replaced with a comprehension
267 |+ result = [i + 1 for i in values] # PERF401 267 |+ result = [i + 1 for i in values] # PERF401
269 268 |
270 269 | def f():
271 270 | src = [1]
PERF401.py:276:13: PERF401 [*] Use a list comprehension to create a transformed list
|
274 | for i in src:
275 | if True if True else False:
276 | dst.append(i)
| ^^^^^^^^^^^^^ PERF401
277 |
278 | for i in src:
|
= help: Replace for loop with list comprehension
Unsafe fix
269 269 |
270 270 | def f():
271 271 | src = [1]
272 |- dst = []
273 272 |
274 |- for i in src:
275 |- if True if True else False:
276 |- dst.append(i)
273 |+ dst = [i for i in src if (True if True else False)]
277 274 |
278 275 | for i in src:
279 276 | if lambda: 0:
PERF401.py:280:13: PERF401 [*] Use `list.extend` to create a transformed list
|
278 | for i in src:
279 | if lambda: 0:
280 | dst.append(i)
| ^^^^^^^^^^^^^ PERF401
|
= help: Replace for loop with list.extend
Unsafe fix
275 275 | if True if True else False:
276 276 | dst.append(i)
277 277 |
278 |- for i in src:
279 |- if lambda: 0:
280 |- dst.append(i)
278 |+ dst.extend(i for i in src if (lambda: 0))

View file

@ -305,3 +305,49 @@ PERF403.py:153:9: PERF403 [*] Use a dictionary comprehension instead of a for-lo
152 |- for idx, name in indices, fruit: 152 |- for idx, name in indices, fruit:
153 |- result[name] = idx # PERF403 153 |- result[name] = idx # PERF403
151 |+ result = {name: idx for idx, name in (indices, fruit)} # PERF403 151 |+ result = {name: idx for idx, name in (indices, fruit)} # PERF403
154 152 |
155 153 |
156 154 | def foo():
PERF403.py:162:13: PERF403 [*] Use a dictionary comprehension instead of a for-loop
|
160 | for k, v in src:
161 | if True if True else False:
162 | dst[k] = v
| ^^^^^^^^^^ PERF403
163 |
164 | for k, v in src:
|
= help: Replace for loop with dict comprehension
Unsafe fix
155 155 |
156 156 | def foo():
157 157 | src = (("x", 1),)
158 |- dst = {}
159 158 |
160 |- for k, v in src:
161 |- if True if True else False:
162 |- dst[k] = v
159 |+ dst = {k: v for k, v in src if (True if True else False)}
163 160 |
164 161 | for k, v in src:
165 162 | if lambda: 0:
PERF403.py:166:13: PERF403 [*] Use `dict.update` instead of a for-loop
|
164 | for k, v in src:
165 | if lambda: 0:
166 | dst[k] = v
| ^^^^^^^^^^ PERF403
|
= help: Replace for loop with `dict.update`
Unsafe fix
161 161 | if True if True else False:
162 162 | dst[k] = v
163 163 |
164 |- for k, v in src:
165 |- if lambda: 0:
166 |- dst[k] = v
164 |+ dst.update({k: v for k, v in src if (lambda: 0)})