[flake8-comprehensions] Skip iterables with named expressions in unnecessary-map (C417) (#14827)

This PR modifies [unnecessary-map
(C417)](https://docs.astral.sh/ruff/rules/unnecessary-map/#unnecessary-map-c417)
to skip `map` expressions if the iterable contains a named expression,
since those cannot appear in comprehensions.

Closes #14808
This commit is contained in:
Dylan 2024-12-06 21:00:33 -06:00 committed by GitHub
parent 8fdd88013d
commit 2c13e6513d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 26 additions and 1 deletions

View file

@ -47,3 +47,13 @@ dict(map(lambda k, v: (k, v), keys, values))
map(lambda x: x, y if y else z) map(lambda x: x, y if y else z)
map(lambda x: x, (y if y else z)) map(lambda x: x, (y if y else z))
map(lambda x: x, (x, y, z)) map(lambda x: x, (x, y, z))
# See https://github.com/astral-sh/ruff/issues/14808
# The following should be Ok since
# named expressions are a syntax error inside comprehensions
a = [1, 2, 3]
b = map(lambda x: x, c := a)
print(c)
# Check nested as well
map(lambda x:x, [c:=a])

View file

@ -3,6 +3,7 @@ use std::fmt;
use ruff_diagnostics::{Diagnostic, Fix}; use ruff_diagnostics::{Diagnostic, Fix};
use ruff_diagnostics::{FixAvailability, Violation}; use ruff_diagnostics::{FixAvailability, Violation};
use ruff_macros::{derive_message_formats, ViolationMetadata}; use ruff_macros::{derive_message_formats, ViolationMetadata};
use ruff_python_ast::helpers::any_over_expr;
use ruff_python_ast::visitor; use ruff_python_ast::visitor;
use ruff_python_ast::visitor::Visitor; use ruff_python_ast::visitor::Visitor;
use ruff_python_ast::{self as ast, Arguments, Expr, ExprContext, Parameters, Stmt}; use ruff_python_ast::{self as ast, Arguments, Expr, ExprContext, Parameters, Stmt};
@ -99,11 +100,17 @@ pub(crate) fn unnecessary_map(
// Only flag, e.g., `map(lambda x: x + 1, iterable)`. // Only flag, e.g., `map(lambda x: x + 1, iterable)`.
let [Expr::Lambda(ast::ExprLambda { let [Expr::Lambda(ast::ExprLambda {
parameters, body, .. parameters, body, ..
}), _] = args }), iterable] = args
else { else {
return; return;
}; };
// For example, (x+1 for x in (c:=a)) is invalid syntax
// so we can't suggest it.
if any_over_expr(iterable, &|expr| expr.is_named_expr()) {
return;
}
if parameters.as_ref().is_some_and(|parameters| { if parameters.as_ref().is_some_and(|parameters| {
late_binding(parameters, body) late_binding(parameters, body)
|| parameters || parameters

View file

@ -329,6 +329,7 @@ C417.py:47:1: C417 [*] Unnecessary `map()` usage (rewrite using a generator expr
47 |+(x for x in (y if y else z)) 47 |+(x for x in (y if y else z))
48 48 | map(lambda x: x, (y if y else z)) 48 48 | map(lambda x: x, (y if y else z))
49 49 | map(lambda x: x, (x, y, z)) 49 49 | map(lambda x: x, (x, y, z))
50 50 |
C417.py:48:1: C417 [*] Unnecessary `map()` usage (rewrite using a generator expression) C417.py:48:1: C417 [*] Unnecessary `map()` usage (rewrite using a generator expression)
| |
@ -347,6 +348,8 @@ C417.py:48:1: C417 [*] Unnecessary `map()` usage (rewrite using a generator expr
48 |-map(lambda x: x, (y if y else z)) 48 |-map(lambda x: x, (y if y else z))
48 |+(x for x in (y if y else z)) 48 |+(x for x in (y if y else z))
49 49 | map(lambda x: x, (x, y, z)) 49 49 | map(lambda x: x, (x, y, z))
50 50 |
51 51 | # See https://github.com/astral-sh/ruff/issues/14808
C417.py:49:1: C417 [*] Unnecessary `map()` usage (rewrite using a generator expression) C417.py:49:1: C417 [*] Unnecessary `map()` usage (rewrite using a generator expression)
| |
@ -354,6 +357,8 @@ C417.py:49:1: C417 [*] Unnecessary `map()` usage (rewrite using a generator expr
48 | map(lambda x: x, (y if y else z)) 48 | map(lambda x: x, (y if y else z))
49 | map(lambda x: x, (x, y, z)) 49 | map(lambda x: x, (x, y, z))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ C417 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ C417
50 |
51 | # See https://github.com/astral-sh/ruff/issues/14808
| |
= help: Replace `map()` with a generator expression = help: Replace `map()` with a generator expression
@ -363,3 +368,6 @@ C417.py:49:1: C417 [*] Unnecessary `map()` usage (rewrite using a generator expr
48 48 | map(lambda x: x, (y if y else z)) 48 48 | map(lambda x: x, (y if y else z))
49 |-map(lambda x: x, (x, y, z)) 49 |-map(lambda x: x, (x, y, z))
49 |+(x for x in (x, y, z)) 49 |+(x for x in (x, y, z))
50 50 |
51 51 | # See https://github.com/astral-sh/ruff/issues/14808
52 52 | # The following should be Ok since