mirror of https://github.com/astral-sh/ruff
[`flake8-bugbear`] Add `B912`: `map()` without an explicit `strict=` parameter (#20429)
## Summary Implements new rule `B912` that requires the `strict=` argument for `map(...)` calls with two or more iterables on Python 3.14+, following the same pattern as `B905` for `zip()`. Closes #20057 --------- Co-authored-by: dylwil3 <dylwil3@gmail.com>
This commit is contained in:
parent
bae8ddfb8a
commit
c94ddb590f
|
|
@ -0,0 +1,33 @@
|
|||
from itertools import count, cycle, repeat
|
||||
|
||||
# Errors
|
||||
map(lambda x: x, [1, 2, 3])
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6])
|
||||
map(lambda x, y, z: x + y + z, [1, 2, 3], [4, 5, 6], [7, 8, 9])
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]))
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]), strict=False)
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9], strict=True))
|
||||
|
||||
# Errors (limited iterators).
|
||||
map(lambda x, y: x + y, [1, 2, 3], repeat(1, 1))
|
||||
map(lambda x, y: x + y, [1, 2, 3], repeat(1, times=4))
|
||||
|
||||
import builtins
|
||||
# Still an error even though it uses the qualified name
|
||||
builtins.map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6])
|
||||
|
||||
# OK
|
||||
map(lambda x: x, [1, 2, 3], strict=True)
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], strict=True)
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], strict=False)
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]), strict=True)
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9], strict=True), strict=True)
|
||||
|
||||
# OK (single iterable - no strict required)
|
||||
map(lambda x: x, [1, 2, 3])
|
||||
|
||||
# OK (infinite iterators)
|
||||
map(lambda x, y: x + y, [1, 2, 3], cycle([1, 2, 3]))
|
||||
map(lambda x, y: x + y, [1, 2, 3], repeat(1))
|
||||
map(lambda x, y: x + y, [1, 2, 3], repeat(1, times=None))
|
||||
map(lambda x, y: x + y, [1, 2, 3], count())
|
||||
|
|
@ -741,6 +741,11 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
|
|||
flake8_bugbear::rules::zip_without_explicit_strict(checker, call);
|
||||
}
|
||||
}
|
||||
if checker.is_rule_enabled(Rule::MapWithoutExplicitStrict) {
|
||||
if checker.target_version() >= PythonVersion::PY314 {
|
||||
flake8_bugbear::rules::map_without_explicit_strict(checker, call);
|
||||
}
|
||||
}
|
||||
if checker.is_rule_enabled(Rule::NoExplicitStacklevel) {
|
||||
flake8_bugbear::rules::no_explicit_stacklevel(checker, call);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -394,6 +394,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
|||
(Flake8Bugbear, "905") => (RuleGroup::Stable, rules::flake8_bugbear::rules::ZipWithoutExplicitStrict),
|
||||
(Flake8Bugbear, "909") => (RuleGroup::Preview, rules::flake8_bugbear::rules::LoopIteratorMutation),
|
||||
(Flake8Bugbear, "911") => (RuleGroup::Stable, rules::flake8_bugbear::rules::BatchedWithoutExplicitStrict),
|
||||
(Flake8Bugbear, "912") => (RuleGroup::Preview, rules::flake8_bugbear::rules::MapWithoutExplicitStrict),
|
||||
|
||||
// flake8-blind-except
|
||||
(Flake8BlindExcept, "001") => (RuleGroup::Stable, rules::flake8_blind_except::rules::BlindExcept),
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer};
|
|||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::Locator;
|
||||
use ruff_python_ast::{self as ast, Arguments, Expr};
|
||||
|
||||
/// Return `true` if the statement containing the current expression is the last
|
||||
/// top-level expression in the cell. This assumes that the source is a Jupyter
|
||||
|
|
@ -27,3 +28,54 @@ pub(super) fn at_last_top_level_expression_in_cell(
|
|||
.all(|token| token.kind() == SimpleTokenKind::Semi || token.kind().is_trivia())
|
||||
})
|
||||
}
|
||||
|
||||
/// Return `true` if the [`Expr`] appears to be an infinite iterator (e.g., a call to
|
||||
/// `itertools.cycle` or similar).
|
||||
pub(crate) fn is_infinite_iterable(arg: &Expr, semantic: &SemanticModel) -> bool {
|
||||
let Expr::Call(ast::ExprCall {
|
||||
func,
|
||||
arguments: Arguments { args, keywords, .. },
|
||||
..
|
||||
}) = &arg
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
|
||||
semantic
|
||||
.resolve_qualified_name(func)
|
||||
.is_some_and(|qualified_name| match qualified_name.segments() {
|
||||
["itertools", "cycle" | "count"] => true,
|
||||
["itertools", "repeat"] => {
|
||||
// Ex) `itertools.repeat(1)`
|
||||
if keywords.is_empty() && args.len() == 1 {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ex) `itertools.repeat(1, None)`
|
||||
if args.len() == 2 && args[1].is_none_literal_expr() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ex) `itertools.repeat(1, times=None)`
|
||||
for keyword in keywords {
|
||||
if keyword.arg.as_ref().is_some_and(|name| name == "times")
|
||||
&& keyword.value.is_none_literal_expr()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
|
||||
/// Return `true` if any expression in the iterator appears to be an infinite iterator.
|
||||
pub(crate) fn any_infinite_iterables<'a>(
|
||||
iter: impl IntoIterator<Item = &'a Expr>,
|
||||
semantic: &SemanticModel,
|
||||
) -> bool {
|
||||
iter.into_iter()
|
||||
.any(|arg| is_infinite_iterable(arg, semantic))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ mod tests {
|
|||
use crate::settings::LinterSettings;
|
||||
use crate::test::test_path;
|
||||
|
||||
use crate::settings::types::PreviewMode;
|
||||
use ruff_python_ast::PythonVersion;
|
||||
|
||||
#[test_case(Rule::AbstractBaseClassWithoutAbstractMethod, Path::new("B024.py"))]
|
||||
|
|
@ -81,11 +82,35 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case(Rule::MapWithoutExplicitStrict, Path::new("B912.py"))]
|
||||
fn preview_rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!(
|
||||
"preview__{}_{}",
|
||||
rule_code.noqa_code(),
|
||||
path.to_string_lossy()
|
||||
);
|
||||
let diagnostics = test_path(
|
||||
Path::new("flake8_bugbear").join(path).as_path(),
|
||||
&LinterSettings {
|
||||
preview: PreviewMode::Enabled,
|
||||
unresolved_target_version: PythonVersion::PY314.into(),
|
||||
..LinterSettings::for_rule(rule_code)
|
||||
},
|
||||
)?;
|
||||
assert_diagnostics!(snapshot, diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case(
|
||||
Rule::ClassAsDataStructure,
|
||||
Path::new("class_as_data_structure.py"),
|
||||
PythonVersion::PY39
|
||||
)]
|
||||
#[test_case(
|
||||
Rule::MapWithoutExplicitStrict,
|
||||
Path::new("B912.py"),
|
||||
PythonVersion::PY313
|
||||
)]
|
||||
fn rules_with_target_version(
|
||||
rule_code: Rule,
|
||||
path: &Path,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use ruff_python_ast::ExprCall;
|
|||
use ruff_python_ast::PythonVersion;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::rules::flake8_bugbear::rules::is_infinite_iterable;
|
||||
use crate::rules::flake8_bugbear::helpers::is_infinite_iterable;
|
||||
use crate::{FixAvailability, Violation};
|
||||
|
||||
/// ## What it does
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
|
||||
use ruff_python_ast::{self as ast};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::fix::edits::add_argument;
|
||||
use crate::rules::flake8_bugbear::helpers::any_infinite_iterables;
|
||||
use crate::{AlwaysFixableViolation, Applicability, Fix};
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `map` calls without an explicit `strict` parameter when called with two or more iterables.
|
||||
///
|
||||
/// This rule applies to Python 3.14 and later, where `map` accepts a `strict` keyword
|
||||
/// argument. For details, see: [What’s New in Python 3.14](https://docs.python.org/dev/whatsnew/3.14.html).
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// By default, if the iterables passed to `map` are of different lengths, the
|
||||
/// resulting iterator will be silently truncated to the length of the shortest
|
||||
/// iterable. This can lead to subtle bugs.
|
||||
///
|
||||
/// Pass `strict=True` to raise a `ValueError` if the iterables are of
|
||||
/// non-uniform length. Alternatively, if the iterables are deliberately of
|
||||
/// different lengths, pass `strict=False` to make the intention explicit.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// map(f, a, b)
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// map(f, a, b, strict=True)
|
||||
/// ```
|
||||
///
|
||||
/// ## Fix safety
|
||||
/// This rule's fix is marked as unsafe for `map` calls that contain
|
||||
/// `**kwargs`, as adding a `strict` keyword argument to such a call may lead
|
||||
/// to a duplicate keyword argument error.
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: `map`](https://docs.python.org/3/library/functions.html#map)
|
||||
/// - [What’s New in Python 3.14](https://docs.python.org/dev/whatsnew/3.14.html)
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct MapWithoutExplicitStrict;
|
||||
|
||||
impl AlwaysFixableViolation for MapWithoutExplicitStrict {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"`map()` without an explicit `strict=` parameter".to_string()
|
||||
}
|
||||
|
||||
fn fix_title(&self) -> String {
|
||||
"Add explicit value for parameter `strict=`".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
/// B912
|
||||
pub(crate) fn map_without_explicit_strict(checker: &Checker, call: &ast::ExprCall) {
|
||||
let semantic = checker.semantic();
|
||||
|
||||
if semantic.match_builtin_expr(&call.func, "map")
|
||||
&& call.arguments.find_keyword("strict").is_none()
|
||||
&& call.arguments.args.len() >= 3 // function + at least 2 iterables
|
||||
&& !any_infinite_iterables(call.arguments.args.iter().skip(1), semantic)
|
||||
{
|
||||
checker
|
||||
.report_diagnostic(MapWithoutExplicitStrict, call.range())
|
||||
.set_fix(Fix::applicable_edit(
|
||||
add_argument(
|
||||
"strict=False",
|
||||
&call.arguments,
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
),
|
||||
// If the function call contains `**kwargs`, mark the fix as unsafe.
|
||||
if call
|
||||
.arguments
|
||||
.keywords
|
||||
.iter()
|
||||
.any(|keyword| keyword.arg.is_none())
|
||||
{
|
||||
Applicability::Unsafe
|
||||
} else {
|
||||
Applicability::Safe
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ pub(crate) use getattr_with_constant::*;
|
|||
pub(crate) use jump_statement_in_finally::*;
|
||||
pub(crate) use loop_iterator_mutation::*;
|
||||
pub(crate) use loop_variable_overrides_iterator::*;
|
||||
pub(crate) use map_without_explicit_strict::*;
|
||||
pub(crate) use mutable_argument_default::*;
|
||||
pub(crate) use mutable_contextvar_default::*;
|
||||
pub(crate) use no_explicit_stacklevel::*;
|
||||
|
|
@ -56,6 +57,7 @@ mod getattr_with_constant;
|
|||
mod jump_statement_in_finally;
|
||||
mod loop_iterator_mutation;
|
||||
mod loop_variable_overrides_iterator;
|
||||
mod map_without_explicit_strict;
|
||||
mod mutable_argument_default;
|
||||
mod mutable_contextvar_default;
|
||||
mod no_explicit_stacklevel;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
|
||||
use ruff_python_ast::{self as ast, Arguments, Expr};
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
use ruff_python_ast::{self as ast};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::fix::edits::add_argument;
|
||||
use crate::rules::flake8_bugbear::helpers::any_infinite_iterables;
|
||||
use crate::{AlwaysFixableViolation, Applicability, Fix};
|
||||
|
||||
/// ## What it does
|
||||
|
|
@ -57,11 +57,7 @@ pub(crate) fn zip_without_explicit_strict(checker: &Checker, call: &ast::ExprCal
|
|||
|
||||
if semantic.match_builtin_expr(&call.func, "zip")
|
||||
&& call.arguments.find_keyword("strict").is_none()
|
||||
&& !call
|
||||
.arguments
|
||||
.args
|
||||
.iter()
|
||||
.any(|arg| is_infinite_iterable(arg, semantic))
|
||||
&& !any_infinite_iterables(call.arguments.args.iter(), semantic)
|
||||
{
|
||||
checker
|
||||
.report_diagnostic(ZipWithoutExplicitStrict, call.range())
|
||||
|
|
@ -86,47 +82,3 @@ pub(crate) fn zip_without_explicit_strict(checker: &Checker, call: &ast::ExprCal
|
|||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// Return `true` if the [`Expr`] appears to be an infinite iterator (e.g., a call to
|
||||
/// `itertools.cycle` or similar).
|
||||
pub(crate) fn is_infinite_iterable(arg: &Expr, semantic: &SemanticModel) -> bool {
|
||||
let Expr::Call(ast::ExprCall {
|
||||
func,
|
||||
arguments: Arguments { args, keywords, .. },
|
||||
..
|
||||
}) = &arg
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
|
||||
semantic
|
||||
.resolve_qualified_name(func)
|
||||
.is_some_and(|qualified_name| {
|
||||
match qualified_name.segments() {
|
||||
["itertools", "cycle" | "count"] => true,
|
||||
["itertools", "repeat"] => {
|
||||
// Ex) `itertools.repeat(1)`
|
||||
if keywords.is_empty() && args.len() == 1 {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ex) `itertools.repeat(1, None)`
|
||||
if args.len() == 2 && args[1].is_none_literal_expr() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ex) `iterools.repeat(1, times=None)`
|
||||
for keyword in keywords {
|
||||
if keyword.arg.as_ref().is_some_and(|name| name == "times") {
|
||||
if keyword.value.is_none_literal_expr() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||
---
|
||||
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
|
||||
---
|
||||
B912 [*] `map()` without an explicit `strict=` parameter
|
||||
--> B912.py:5:1
|
||||
|
|
||||
3 | # Errors
|
||||
4 | map(lambda x: x, [1, 2, 3])
|
||||
5 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6])
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
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]))
|
||||
|
|
||||
help: Add explicit value for parameter `strict=`
|
||||
2 |
|
||||
3 | # Errors
|
||||
4 | map(lambda x: x, [1, 2, 3])
|
||||
- map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6])
|
||||
5 + map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], strict=False)
|
||||
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]))
|
||||
8 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]), strict=False)
|
||||
|
||||
B912 [*] `map()` without an explicit `strict=` parameter
|
||||
--> B912.py:6:1
|
||||
|
|
||||
4 | map(lambda x: x, [1, 2, 3])
|
||||
5 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6])
|
||||
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]))
|
||||
8 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]), strict=False)
|
||||
|
|
||||
help: Add explicit value for parameter `strict=`
|
||||
3 | # Errors
|
||||
4 | map(lambda x: x, [1, 2, 3])
|
||||
5 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 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], strict=False)
|
||||
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)
|
||||
9 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9], strict=True))
|
||||
|
||||
B912 [*] `map()` without an explicit `strict=` parameter
|
||||
--> B912.py:7:1
|
||||
|
|
||||
5 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6])
|
||||
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]))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
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))
|
||||
|
|
||||
help: Add explicit value for parameter `strict=`
|
||||
4 | map(lambda x: x, [1, 2, 3])
|
||||
5 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6])
|
||||
6 | map(lambda x, y, z: x + y + z, [1, 2, 3], [4, 5, 6], [7, 8, 9])
|
||||
- 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]), 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))
|
||||
10 |
|
||||
11 | # Errors (limited iterators).
|
||||
|
||||
B912 [*] `map()` without an explicit `strict=` parameter
|
||||
--> B912.py:9:1
|
||||
|
|
||||
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)
|
||||
9 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9], strict=True))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
10 |
|
||||
11 | # Errors (limited iterators).
|
||||
|
|
||||
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])
|
||||
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)
|
||||
- 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), strict=False)
|
||||
10 |
|
||||
11 | # Errors (limited iterators).
|
||||
12 | map(lambda x, y: x + y, [1, 2, 3], repeat(1, 1))
|
||||
|
||||
B912 [*] `map()` without an explicit `strict=` parameter
|
||||
--> B912.py:12:1
|
||||
|
|
||||
11 | # Errors (limited iterators).
|
||||
12 | map(lambda x, y: x + y, [1, 2, 3], repeat(1, 1))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
13 | map(lambda x, y: x + y, [1, 2, 3], repeat(1, times=4))
|
||||
|
|
||||
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))
|
||||
10 |
|
||||
11 | # Errors (limited iterators).
|
||||
- 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), strict=False)
|
||||
13 | map(lambda x, y: x + y, [1, 2, 3], repeat(1, times=4))
|
||||
14 |
|
||||
15 | import builtins
|
||||
|
||||
B912 [*] `map()` without an explicit `strict=` parameter
|
||||
--> B912.py:13:1
|
||||
|
|
||||
11 | # Errors (limited iterators).
|
||||
12 | map(lambda x, y: x + y, [1, 2, 3], repeat(1, 1))
|
||||
13 | map(lambda x, y: x + y, [1, 2, 3], repeat(1, times=4))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
14 |
|
||||
15 | import builtins
|
||||
|
|
||||
help: Add explicit value for parameter `strict=`
|
||||
10 |
|
||||
11 | # Errors (limited iterators).
|
||||
12 | map(lambda x, y: x + y, [1, 2, 3], repeat(1, 1))
|
||||
- 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), strict=False)
|
||||
14 |
|
||||
15 | import builtins
|
||||
16 | # Still an error even though it uses the qualified name
|
||||
|
||||
B912 [*] `map()` without an explicit `strict=` parameter
|
||||
--> B912.py:17:1
|
||||
|
|
||||
15 | import builtins
|
||||
16 | # Still an error even though it uses the qualified name
|
||||
17 | builtins.map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6])
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
18 |
|
||||
19 | # OK
|
||||
|
|
||||
help: Add explicit value for parameter `strict=`
|
||||
14 |
|
||||
15 | import builtins
|
||||
16 | # Still an error even though it uses the qualified name
|
||||
- builtins.map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6])
|
||||
17 + builtins.map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], strict=False)
|
||||
18 |
|
||||
19 | # OK
|
||||
20 | map(lambda x: x, [1, 2, 3], strict=True)
|
||||
|
|
@ -3073,6 +3073,7 @@
|
|||
"B909",
|
||||
"B91",
|
||||
"B911",
|
||||
"B912",
|
||||
"BLE",
|
||||
"BLE0",
|
||||
"BLE00",
|
||||
|
|
|
|||
Loading…
Reference in New Issue