[pycodestyle] Fix E731 autofix creating a syntax error for expressions spanned across multiple lines (#18479)
Some checks are pending
CI / cargo clippy (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / mkdocs (push) Waiting to run
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions

This commit is contained in:
Victor Hugo Gomes 2025-06-13 03:44:15 -03:00 committed by GitHub
parent 015222900f
commit 76d9009a6e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 95 additions and 8 deletions

View file

@ -92,7 +92,7 @@ pub(crate) fn lambda_assignment(
let first_line = checker.locator().line_str(stmt.start());
let indentation = leading_indentation(first_line);
let mut indented = String::new();
for (idx, line) in function(id, lambda, annotation, checker)
for (idx, line) in function(id, lambda, annotation, stmt, checker)
.universal_newlines()
.enumerate()
{
@ -177,6 +177,7 @@ fn function(
name: &str,
lambda: &ExprLambda,
annotation: Option<&Expr>,
stmt: &Stmt,
checker: &Checker,
) -> String {
// Use a dummy body. It gets replaced at the end with the actual body.
@ -236,7 +237,7 @@ fn function(
});
let generated = checker.generator().stmt(&func);
return replace_trailing_ellipsis_with_original_expr(generated, lambda, checker);
return replace_trailing_ellipsis_with_original_expr(generated, lambda, stmt, checker);
}
}
let function = Stmt::FunctionDef(ast::StmtFunctionDef {
@ -251,12 +252,13 @@ fn function(
});
let generated = checker.generator().stmt(&function);
replace_trailing_ellipsis_with_original_expr(generated, lambda, checker)
replace_trailing_ellipsis_with_original_expr(generated, lambda, stmt, checker)
}
fn replace_trailing_ellipsis_with_original_expr(
mut generated: String,
lambda: &ExprLambda,
stmt: &Stmt,
checker: &Checker,
) -> String {
let original_expr_range = parenthesized_range(
@ -267,14 +269,28 @@ fn replace_trailing_ellipsis_with_original_expr(
)
.unwrap_or(lambda.body.range());
let original_expr_in_source = checker.locator().slice(original_expr_range);
// This prevents the autofix of introducing a syntax error if the lambda's body is an
// expression spanned across multiple lines. To avoid the syntax error we preserve
// the parenthesis around the body.
let original_expr_in_source = if parenthesized_range(
lambda.into(),
stmt.into(),
checker.comment_ranges(),
checker.source(),
)
.is_some()
{
format!("({})", checker.locator().slice(original_expr_range))
} else {
checker.locator().slice(original_expr_range).to_string()
};
let placeholder_ellipsis_start = generated.rfind("...").unwrap();
let placeholder_ellipsis_end = placeholder_ellipsis_start + "...".len();
generated.replace_range(
placeholder_ellipsis_start..placeholder_ellipsis_end,
original_expr_in_source,
&original_expr_in_source,
);
generated
}

View file

@ -318,7 +318,7 @@ E731.py:139:5: E731 Do not assign a `lambda` expression, use a `def`
138 138 | class TemperatureScales(Enum):
139 |- CELSIUS = (lambda deg_c: deg_c)
139 |+ def CELSIUS(deg_c):
140 |+ return deg_c
140 |+ return (deg_c)
140 141 | FAHRENHEIT = (lambda deg_c: deg_c * 9 / 5 + 32)
141 142 |
142 143 |
@ -338,7 +338,7 @@ E731.py:140:5: E731 Do not assign a `lambda` expression, use a `def`
139 139 | CELSIUS = (lambda deg_c: deg_c)
140 |- FAHRENHEIT = (lambda deg_c: deg_c * 9 / 5 + 32)
140 |+ def FAHRENHEIT(deg_c):
141 |+ return deg_c * 9 / 5 + 32
141 |+ return (deg_c * 9 / 5 + 32)
141 142 |
142 143 |
143 144 | # Regression test for: https://github.com/astral-sh/ruff/issues/7141
@ -449,6 +449,8 @@ E731.py:176:1: E731 [*] Do not assign a `lambda` expression, use a `def`
178 | | y := 10
179 | | )
| |_^ E731
180 |
181 | # https://github.com/astral-sh/ruff/issues/18475
|
= help: Rewrite `x` as a `def`
@ -462,3 +464,59 @@ E731.py:176:1: E731 [*] Do not assign a `lambda` expression, use a `def`
177 178 | # comment
178 179 | y := 10
179 180 | )
E731.py:182:1: E731 [*] Do not assign a `lambda` expression, use a `def`
|
181 | # https://github.com/astral-sh/ruff/issues/18475
182 | / foo_tooltip = (
183 | | lambda x, data: f"\nfoo: {data['foo'][int(x)]}"
184 | | if data["foo"] is not None
185 | | else ""
186 | | )
| |_^ E731
187 |
188 | foo_tooltip = (
|
= help: Rewrite `foo_tooltip` as a `def`
Unsafe fix
179 179 | )
180 180 |
181 181 | # https://github.com/astral-sh/ruff/issues/18475
182 |-foo_tooltip = (
183 |- lambda x, data: f"\nfoo: {data['foo'][int(x)]}"
182 |+def foo_tooltip(x, data):
183 |+ return (f"\nfoo: {data['foo'][int(x)]}"
184 184 | if data["foo"] is not None
185 |- else ""
186 |-)
185 |+ else "")
187 186 |
188 187 | foo_tooltip = (
189 188 | lambda x, data: f"\nfoo: {data['foo'][int(x)]}" +
E731.py:188:1: E731 [*] Do not assign a `lambda` expression, use a `def`
|
186 | )
187 |
188 | / foo_tooltip = (
189 | | lambda x, data: f"\nfoo: {data['foo'][int(x)]}" +
190 | | more
191 | |
192 | | )
| |_^ E731
|
= help: Rewrite `foo_tooltip` as a `def`
Unsafe fix
185 185 | else ""
186 186 | )
187 187 |
188 |-foo_tooltip = (
189 |- lambda x, data: f"\nfoo: {data['foo'][int(x)]}" +
190 |- more
191 |-
192 |-)
188 |+def foo_tooltip(x, data):
189 |+ return (f"\nfoo: {data['foo'][int(x)]}" +
190 |+ more)