Mark `FURB118` fix as unsafe (#13613)

Closes https://github.com/astral-sh/ruff/issues/13421
This commit is contained in:
Zanie Blue 2024-10-03 16:39:22 -05:00 committed by GitHub
parent 7ad07c2c5d
commit 99e4566fce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 49 additions and 43 deletions

View File

@ -17,14 +17,14 @@ use crate::checkers::ast::Checker;
use crate::importer::{ImportRequest, Importer}; use crate::importer::{ImportRequest, Importer};
/// ## What it does /// ## What it does
/// Checks for lambda expressions and function definitions that can be replaced /// Checks for lambda expressions and function definitions that can be replaced with a function from
/// with a function from the `operator` module. /// the `operator` module.
/// ///
/// ## Why is this bad? /// ## Why is this bad?
/// The `operator` module provides functions that implement the same functionality /// The `operator` module provides functions that implement the same functionality as the
/// as the corresponding operators. For example, `operator.add` is equivalent to /// corresponding operators. For example, `operator.add` is equivalent to `lambda x, y: x + y`.
/// `lambda x, y: x + y`. Using the functions from the `operator` module is more /// Using the functions from the `operator` module is more concise and communicates the intent of
/// concise and communicates the intent of the code more clearly. /// the code more clearly.
/// ///
/// ## Example /// ## Example
/// ```python /// ```python
@ -42,6 +42,12 @@ use crate::importer::{ImportRequest, Importer};
/// nums = [1, 2, 3] /// nums = [1, 2, 3]
/// total = functools.reduce(operator.add, nums) /// total = functools.reduce(operator.add, nums)
/// ``` /// ```
///
/// ## Fix safety
/// This fix is usually safe, but if the lambda is called with keyword arguments, e.g.,
/// `add = lambda x, y: x + y; add(x=1, y=2)`, replacing the lambda with an operator function, e.g.,
/// `operator.add`, will cause the call to raise a `TypeError`, as functions in `operator` do not allow
/// keyword arguments.
#[violation] #[violation]
pub struct ReimplementedOperator { pub struct ReimplementedOperator {
operator: Operator, operator: Operator,
@ -177,7 +183,7 @@ impl FunctionLike<'_> {
} else { } else {
format!("{binding}({})", operator.args.join(", ")) format!("{binding}({})", operator.args.join(", "))
}; };
Ok(Some(Fix::safe_edits( Ok(Some(Fix::unsafe_edits(
Edit::range_replacement(content, self.range()), Edit::range_replacement(content, self.range()),
[edit], [edit],
))) )))

View File

@ -11,7 +11,7 @@ FURB118.py:2:13: FURB118 [*] Use `operator.invert` instead of defining a lambda
| |
= help: Replace with `operator.invert` = help: Replace with `operator.invert`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |-op_bitnot = lambda x: ~x 2 |-op_bitnot = lambda x: ~x
2 |+import operator 2 |+import operator
@ -31,7 +31,7 @@ FURB118.py:3:10: FURB118 [*] Use `operator.not_` instead of defining a lambda
| |
= help: Replace with `operator.not_` = help: Replace with `operator.not_`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -51,7 +51,7 @@ FURB118.py:4:10: FURB118 [*] Use `operator.pos` instead of defining a lambda
| |
= help: Replace with `operator.pos` = help: Replace with `operator.pos`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -73,7 +73,7 @@ FURB118.py:5:10: FURB118 [*] Use `operator.neg` instead of defining a lambda
| |
= help: Replace with `operator.neg` = help: Replace with `operator.neg`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -96,7 +96,7 @@ FURB118.py:7:10: FURB118 [*] Use `operator.add` instead of defining a lambda
| |
= help: Replace with `operator.add` = help: Replace with `operator.add`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -120,7 +120,7 @@ FURB118.py:8:10: FURB118 [*] Use `operator.sub` instead of defining a lambda
| |
= help: Replace with `operator.sub` = help: Replace with `operator.sub`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -146,7 +146,7 @@ FURB118.py:9:11: FURB118 [*] Use `operator.mul` instead of defining a lambda
| |
= help: Replace with `operator.mul` = help: Replace with `operator.mul`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -173,7 +173,7 @@ FURB118.py:10:14: FURB118 [*] Use `operator.matmul` instead of defining a lambda
| |
= help: Replace with `operator.matmul` = help: Replace with `operator.matmul`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -200,7 +200,7 @@ FURB118.py:11:14: FURB118 [*] Use `operator.truediv` instead of defining a lambd
| |
= help: Replace with `operator.truediv` = help: Replace with `operator.truediv`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -227,7 +227,7 @@ FURB118.py:12:10: FURB118 [*] Use `operator.mod` instead of defining a lambda
| |
= help: Replace with `operator.mod` = help: Replace with `operator.mod`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -254,7 +254,7 @@ FURB118.py:13:10: FURB118 [*] Use `operator.pow` instead of defining a lambda
| |
= help: Replace with `operator.pow` = help: Replace with `operator.pow`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -281,7 +281,7 @@ FURB118.py:14:13: FURB118 [*] Use `operator.lshift` instead of defining a lambda
| |
= help: Replace with `operator.lshift` = help: Replace with `operator.lshift`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -308,7 +308,7 @@ FURB118.py:15:13: FURB118 [*] Use `operator.rshift` instead of defining a lambda
| |
= help: Replace with `operator.rshift` = help: Replace with `operator.rshift`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -335,7 +335,7 @@ FURB118.py:16:12: FURB118 [*] Use `operator.or_` instead of defining a lambda
| |
= help: Replace with `operator.or_` = help: Replace with `operator.or_`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -362,7 +362,7 @@ FURB118.py:17:10: FURB118 [*] Use `operator.xor` instead of defining a lambda
| |
= help: Replace with `operator.xor` = help: Replace with `operator.xor`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -388,7 +388,7 @@ FURB118.py:18:13: FURB118 [*] Use `operator.and_` instead of defining a lambda
| |
= help: Replace with `operator.and_` = help: Replace with `operator.and_`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -415,7 +415,7 @@ FURB118.py:19:15: FURB118 [*] Use `operator.floordiv` instead of defining a lamb
| |
= help: Replace with `operator.floordiv` = help: Replace with `operator.floordiv`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -442,7 +442,7 @@ FURB118.py:21:9: FURB118 [*] Use `operator.eq` instead of defining a lambda
| |
= help: Replace with `operator.eq` = help: Replace with `operator.eq`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -468,7 +468,7 @@ FURB118.py:22:9: FURB118 [*] Use `operator.ne` instead of defining a lambda
| |
= help: Replace with `operator.ne` = help: Replace with `operator.ne`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -495,7 +495,7 @@ FURB118.py:23:9: FURB118 [*] Use `operator.lt` instead of defining a lambda
| |
= help: Replace with `operator.lt` = help: Replace with `operator.lt`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -522,7 +522,7 @@ FURB118.py:24:10: FURB118 [*] Use `operator.le` instead of defining a lambda
| |
= help: Replace with `operator.le` = help: Replace with `operator.le`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -549,7 +549,7 @@ FURB118.py:25:9: FURB118 [*] Use `operator.gt` instead of defining a lambda
| |
= help: Replace with `operator.gt` = help: Replace with `operator.gt`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -576,7 +576,7 @@ FURB118.py:26:10: FURB118 [*] Use `operator.ge` instead of defining a lambda
| |
= help: Replace with `operator.ge` = help: Replace with `operator.ge`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -603,7 +603,7 @@ FURB118.py:27:9: FURB118 [*] Use `operator.is_` instead of defining a lambda
| |
= help: Replace with `operator.is_` = help: Replace with `operator.is_`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -630,7 +630,7 @@ FURB118.py:28:12: FURB118 [*] Use `operator.is_not` instead of defining a lambda
| |
= help: Replace with `operator.is_not` = help: Replace with `operator.is_not`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -657,7 +657,7 @@ FURB118.py:29:9: FURB118 [*] Use `operator.contains` instead of defining a lambd
| |
= help: Replace with `operator.contains` = help: Replace with `operator.contains`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -684,7 +684,7 @@ FURB118.py:30:17: FURB118 [*] Use `operator.itemgetter(0)` instead of defining a
| |
= help: Replace with `operator.itemgetter(0)` = help: Replace with `operator.itemgetter(0)`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -711,7 +711,7 @@ FURB118.py:31:17: FURB118 [*] Use `operator.itemgetter(0, 1, 2)` instead of defi
| |
= help: Replace with `operator.itemgetter(0, 1, 2)` = help: Replace with `operator.itemgetter(0, 1, 2)`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -738,7 +738,7 @@ FURB118.py:32:17: FURB118 [*] Use `operator.itemgetter(slice(1, None), 2)` inste
| |
= help: Replace with `operator.itemgetter(slice(1, None), 2)` = help: Replace with `operator.itemgetter(slice(1, None), 2)`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -765,7 +765,7 @@ FURB118.py:33:17: FURB118 [*] Use `operator.itemgetter(slice(None))` instead of
| |
= help: Replace with `operator.itemgetter(slice(None))` = help: Replace with `operator.itemgetter(slice(None))`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -791,7 +791,7 @@ FURB118.py:34:17: FURB118 [*] Use `operator.itemgetter((0, 1))` instead of defin
| |
= help: Replace with `operator.itemgetter((0, 1))` = help: Replace with `operator.itemgetter((0, 1))`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -816,7 +816,7 @@ FURB118.py:35:17: FURB118 [*] Use `operator.itemgetter((0, 1))` instead of defin
| |
= help: Replace with `operator.itemgetter((0, 1))` = help: Replace with `operator.itemgetter((0, 1))`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -857,7 +857,7 @@ FURB118.py:88:17: FURB118 [*] Use `operator.itemgetter((slice(None), 1))` instea
| |
= help: Replace with `operator.itemgetter((slice(None), 1))` = help: Replace with `operator.itemgetter((slice(None), 1))`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -884,7 +884,7 @@ FURB118.py:89:17: FURB118 [*] Use `operator.itemgetter((1, slice(None)))` instea
| |
= help: Replace with `operator.itemgetter((1, slice(None)))` = help: Replace with `operator.itemgetter((1, slice(None)))`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -910,7 +910,7 @@ FURB118.py:92:17: FURB118 [*] Use `operator.itemgetter((1, slice(None)))` instea
| |
= help: Replace with `operator.itemgetter((1, slice(None)))` = help: Replace with `operator.itemgetter((1, slice(None)))`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x
@ -934,7 +934,7 @@ FURB118.py:95:17: FURB118 [*] Use `operator.itemgetter((1, 2))` instead
| |
= help: Replace with `operator.itemgetter((1, 2))` = help: Replace with `operator.itemgetter((1, 2))`
Safe fix Unsafe fix
1 1 | # Errors. 1 1 | # Errors.
2 |+import operator 2 |+import operator
2 3 | op_bitnot = lambda x: ~x 2 3 | op_bitnot = lambda x: ~x