mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-20 12:35:40 +00:00
[flake8-bugbear] Mark B905 and B912 fixes as unsafe (#20695)
Resolves https://github.com/astral-sh/ruff/issues/20694 This PR updates the `zip_without_explicit_strict` and `map_without_explicit_strict` rules so their fixes are always marked unsafe, following Brent's guidance that adding `strict=False` can silently preserve buggy behaviour when inputs differ. The fix safety docs now spell out that reasoning, the applicability drops to `Unsafe`, and the snapshots were refreshed so Ruff clearly warns users before applying the edit.
This commit is contained in:
parent
7a347c4370
commit
2be73e9afb
4 changed files with 29 additions and 28 deletions
|
|
@ -34,9 +34,10 @@ use crate::{AlwaysFixableViolation, Applicability, Fix};
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ## Fix safety
|
/// ## Fix safety
|
||||||
/// This rule's fix is marked as unsafe for `map` calls that contain
|
/// This rule's fix is marked as unsafe. While adding `strict=False` preserves
|
||||||
/// `**kwargs`, as adding a `strict` keyword argument to such a call may lead
|
/// the runtime behavior, it can obscure situations where the iterables are of
|
||||||
/// to a duplicate keyword argument error.
|
/// unequal length. Ruff prefers to alert users so they can choose the intended
|
||||||
|
/// behavior themselves.
|
||||||
///
|
///
|
||||||
/// ## References
|
/// ## References
|
||||||
/// - [Python documentation: `map`](https://docs.python.org/3/library/functions.html#map)
|
/// - [Python documentation: `map`](https://docs.python.org/3/library/functions.html#map)
|
||||||
|
|
@ -73,17 +74,7 @@ pub(crate) fn map_without_explicit_strict(checker: &Checker, call: &ast::ExprCal
|
||||||
checker.comment_ranges(),
|
checker.comment_ranges(),
|
||||||
checker.locator().contents(),
|
checker.locator().contents(),
|
||||||
),
|
),
|
||||||
// If the function call contains `**kwargs`, mark the fix as unsafe.
|
Applicability::Unsafe,
|
||||||
if call
|
|
||||||
.arguments
|
|
||||||
.keywords
|
|
||||||
.iter()
|
|
||||||
.any(|keyword| keyword.arg.is_none())
|
|
||||||
{
|
|
||||||
Applicability::Unsafe
|
|
||||||
} else {
|
|
||||||
Applicability::Safe
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,10 @@ use crate::{AlwaysFixableViolation, Applicability, Fix};
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ## Fix safety
|
/// ## Fix safety
|
||||||
/// This rule's fix is marked as unsafe for `zip` calls that contain
|
/// This rule's fix is marked as unsafe. While adding `strict=False` preserves
|
||||||
/// `**kwargs`, as adding a `strict` keyword argument to such a call may lead
|
/// the runtime behavior, it can obscure situations where the iterables are of
|
||||||
/// to a duplicate keyword argument error.
|
/// unequal length. Ruff prefers to alert users so they can choose the intended
|
||||||
|
/// behavior themselves.
|
||||||
///
|
///
|
||||||
/// ## References
|
/// ## References
|
||||||
/// - [Python documentation: `zip`](https://docs.python.org/3/library/functions.html#zip)
|
/// - [Python documentation: `zip`](https://docs.python.org/3/library/functions.html#zip)
|
||||||
|
|
@ -68,17 +69,7 @@ pub(crate) fn zip_without_explicit_strict(checker: &Checker, call: &ast::ExprCal
|
||||||
checker.comment_ranges(),
|
checker.comment_ranges(),
|
||||||
checker.locator().contents(),
|
checker.locator().contents(),
|
||||||
),
|
),
|
||||||
// If the function call contains `**kwargs`, mark the fix as unsafe.
|
Applicability::Unsafe,
|
||||||
if call
|
|
||||||
.arguments
|
|
||||||
.keywords
|
|
||||||
.iter()
|
|
||||||
.any(|keyword| keyword.arg.is_none())
|
|
||||||
{
|
|
||||||
Applicability::Unsafe
|
|
||||||
} else {
|
|
||||||
Applicability::Safe
|
|
||||||
},
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||||
|
assertion_line: 156
|
||||||
---
|
---
|
||||||
B905 [*] `zip()` without an explicit `strict=` parameter
|
B905 [*] `zip()` without an explicit `strict=` parameter
|
||||||
--> B905.py:4:1
|
--> B905.py:4:1
|
||||||
|
|
@ -19,6 +20,7 @@ help: Add explicit value for parameter `strict=`
|
||||||
5 | zip(range(3))
|
5 | zip(range(3))
|
||||||
6 | zip("a", "b")
|
6 | zip("a", "b")
|
||||||
7 | zip("a", "b", *zip("c"))
|
7 | zip("a", "b", *zip("c"))
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
B905 [*] `zip()` without an explicit `strict=` parameter
|
B905 [*] `zip()` without an explicit `strict=` parameter
|
||||||
--> B905.py:5:1
|
--> B905.py:5:1
|
||||||
|
|
@ -39,6 +41,7 @@ help: Add explicit value for parameter `strict=`
|
||||||
6 | zip("a", "b")
|
6 | zip("a", "b")
|
||||||
7 | zip("a", "b", *zip("c"))
|
7 | zip("a", "b", *zip("c"))
|
||||||
8 | zip(zip("a"), strict=False)
|
8 | zip(zip("a"), strict=False)
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
B905 [*] `zip()` without an explicit `strict=` parameter
|
B905 [*] `zip()` without an explicit `strict=` parameter
|
||||||
--> B905.py:6:1
|
--> B905.py:6:1
|
||||||
|
|
@ -59,6 +62,7 @@ help: Add explicit value for parameter `strict=`
|
||||||
7 | zip("a", "b", *zip("c"))
|
7 | zip("a", "b", *zip("c"))
|
||||||
8 | zip(zip("a"), strict=False)
|
8 | zip(zip("a"), strict=False)
|
||||||
9 | zip(zip("a", strict=True))
|
9 | zip(zip("a", strict=True))
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
B905 [*] `zip()` without an explicit `strict=` parameter
|
B905 [*] `zip()` without an explicit `strict=` parameter
|
||||||
--> B905.py:7:1
|
--> B905.py:7:1
|
||||||
|
|
@ -79,6 +83,7 @@ help: Add explicit value for parameter `strict=`
|
||||||
8 | zip(zip("a"), strict=False)
|
8 | zip(zip("a"), strict=False)
|
||||||
9 | zip(zip("a", strict=True))
|
9 | zip(zip("a", strict=True))
|
||||||
10 |
|
10 |
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
B905 [*] `zip()` without an explicit `strict=` parameter
|
B905 [*] `zip()` without an explicit `strict=` parameter
|
||||||
--> B905.py:7:16
|
--> B905.py:7:16
|
||||||
|
|
@ -99,6 +104,7 @@ help: Add explicit value for parameter `strict=`
|
||||||
8 | zip(zip("a"), strict=False)
|
8 | zip(zip("a"), strict=False)
|
||||||
9 | zip(zip("a", strict=True))
|
9 | zip(zip("a", strict=True))
|
||||||
10 |
|
10 |
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
B905 [*] `zip()` without an explicit `strict=` parameter
|
B905 [*] `zip()` without an explicit `strict=` parameter
|
||||||
--> B905.py:8:5
|
--> B905.py:8:5
|
||||||
|
|
@ -118,6 +124,7 @@ help: Add explicit value for parameter `strict=`
|
||||||
9 | zip(zip("a", strict=True))
|
9 | zip(zip("a", strict=True))
|
||||||
10 |
|
10 |
|
||||||
11 | # OK
|
11 | # OK
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
B905 [*] `zip()` without an explicit `strict=` parameter
|
B905 [*] `zip()` without an explicit `strict=` parameter
|
||||||
--> B905.py:9:1
|
--> B905.py:9:1
|
||||||
|
|
@ -138,6 +145,7 @@ help: Add explicit value for parameter `strict=`
|
||||||
10 |
|
10 |
|
||||||
11 | # OK
|
11 | # OK
|
||||||
12 | zip(range(3), strict=True)
|
12 | zip(range(3), strict=True)
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
B905 [*] `zip()` without an explicit `strict=` parameter
|
B905 [*] `zip()` without an explicit `strict=` parameter
|
||||||
--> B905.py:24:1
|
--> B905.py:24:1
|
||||||
|
|
@ -156,6 +164,7 @@ help: Add explicit value for parameter `strict=`
|
||||||
25 | zip([1, 2, 3], repeat(1, times=4))
|
25 | zip([1, 2, 3], repeat(1, times=4))
|
||||||
26 |
|
26 |
|
||||||
27 | import builtins
|
27 | import builtins
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
B905 [*] `zip()` without an explicit `strict=` parameter
|
B905 [*] `zip()` without an explicit `strict=` parameter
|
||||||
--> B905.py:25:1
|
--> B905.py:25:1
|
||||||
|
|
@ -176,6 +185,7 @@ help: Add explicit value for parameter `strict=`
|
||||||
26 |
|
26 |
|
||||||
27 | import builtins
|
27 | import builtins
|
||||||
28 | # Still an error even though it uses the qualified name
|
28 | # Still an error even though it uses the qualified name
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
B905 [*] `zip()` without an explicit `strict=` parameter
|
B905 [*] `zip()` without an explicit `strict=` parameter
|
||||||
--> B905.py:29:1
|
--> B905.py:29:1
|
||||||
|
|
@ -191,3 +201,4 @@ help: Add explicit value for parameter `strict=`
|
||||||
28 | # Still an error even though it uses the qualified name
|
28 | # Still an error even though it uses the qualified name
|
||||||
- builtins.zip([1, 2, 3])
|
- builtins.zip([1, 2, 3])
|
||||||
29 + builtins.zip([1, 2, 3], strict=False)
|
29 + builtins.zip([1, 2, 3], strict=False)
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||||
|
assertion_line: 112
|
||||||
---
|
---
|
||||||
B912 [*] `map()` without an explicit `strict=` parameter
|
B912 [*] `map()` without an explicit `strict=` parameter
|
||||||
--> B912.py:5:1
|
--> B912.py:5:1
|
||||||
|
|
@ -20,6 +21,7 @@ help: Add explicit value for parameter `strict=`
|
||||||
6 | map(lambda x, y, z: x + y + z, [1, 2, 3], [4, 5, 6], [7, 8, 9])
|
6 | map(lambda x, y, z: x + y + z, [1, 2, 3], [4, 5, 6], [7, 8, 9])
|
||||||
7 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]))
|
7 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]))
|
||||||
8 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]), strict=False)
|
8 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]), strict=False)
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
B912 [*] `map()` without an explicit `strict=` parameter
|
B912 [*] `map()` without an explicit `strict=` parameter
|
||||||
--> B912.py:6:1
|
--> B912.py:6:1
|
||||||
|
|
@ -40,6 +42,7 @@ help: Add explicit value for parameter `strict=`
|
||||||
7 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]))
|
7 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]))
|
||||||
8 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]), strict=False)
|
8 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]), strict=False)
|
||||||
9 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9], strict=True))
|
9 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9], strict=True))
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
B912 [*] `map()` without an explicit `strict=` parameter
|
B912 [*] `map()` without an explicit `strict=` parameter
|
||||||
--> B912.py:7:1
|
--> B912.py:7:1
|
||||||
|
|
@ -61,6 +64,7 @@ help: Add explicit value for parameter `strict=`
|
||||||
9 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9], strict=True))
|
9 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9], strict=True))
|
||||||
10 |
|
10 |
|
||||||
11 | # Errors (limited iterators).
|
11 | # Errors (limited iterators).
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
B912 [*] `map()` without an explicit `strict=` parameter
|
B912 [*] `map()` without an explicit `strict=` parameter
|
||||||
--> B912.py:9:1
|
--> B912.py:9:1
|
||||||
|
|
@ -81,6 +85,7 @@ help: Add explicit value for parameter `strict=`
|
||||||
10 |
|
10 |
|
||||||
11 | # Errors (limited iterators).
|
11 | # Errors (limited iterators).
|
||||||
12 | map(lambda x, y: x + y, [1, 2, 3], repeat(1, 1))
|
12 | map(lambda x, y: x + y, [1, 2, 3], repeat(1, 1))
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
B912 [*] `map()` without an explicit `strict=` parameter
|
B912 [*] `map()` without an explicit `strict=` parameter
|
||||||
--> B912.py:12:1
|
--> B912.py:12:1
|
||||||
|
|
@ -99,6 +104,7 @@ help: Add explicit value for parameter `strict=`
|
||||||
13 | map(lambda x, y: x + y, [1, 2, 3], repeat(1, times=4))
|
13 | map(lambda x, y: x + y, [1, 2, 3], repeat(1, times=4))
|
||||||
14 |
|
14 |
|
||||||
15 | import builtins
|
15 | import builtins
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
B912 [*] `map()` without an explicit `strict=` parameter
|
B912 [*] `map()` without an explicit `strict=` parameter
|
||||||
--> B912.py:13:1
|
--> B912.py:13:1
|
||||||
|
|
@ -119,6 +125,7 @@ help: Add explicit value for parameter `strict=`
|
||||||
14 |
|
14 |
|
||||||
15 | import builtins
|
15 | import builtins
|
||||||
16 | # Still an error even though it uses the qualified name
|
16 | # Still an error even though it uses the qualified name
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
B912 [*] `map()` without an explicit `strict=` parameter
|
B912 [*] `map()` without an explicit `strict=` parameter
|
||||||
--> B912.py:17:1
|
--> B912.py:17:1
|
||||||
|
|
@ -139,3 +146,4 @@ help: Add explicit value for parameter `strict=`
|
||||||
18 |
|
18 |
|
||||||
19 | # OK
|
19 | # OK
|
||||||
20 | map(lambda x: x, [1, 2, 3], strict=True)
|
20 | map(lambda x: x, [1, 2, 3], strict=True)
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue