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);
|
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) {
|
if checker.is_rule_enabled(Rule::NoExplicitStacklevel) {
|
||||||
flake8_bugbear::rules::no_explicit_stacklevel(checker, call);
|
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, "905") => (RuleGroup::Stable, rules::flake8_bugbear::rules::ZipWithoutExplicitStrict),
|
||||||
(Flake8Bugbear, "909") => (RuleGroup::Preview, rules::flake8_bugbear::rules::LoopIteratorMutation),
|
(Flake8Bugbear, "909") => (RuleGroup::Preview, rules::flake8_bugbear::rules::LoopIteratorMutation),
|
||||||
(Flake8Bugbear, "911") => (RuleGroup::Stable, rules::flake8_bugbear::rules::BatchedWithoutExplicitStrict),
|
(Flake8Bugbear, "911") => (RuleGroup::Stable, rules::flake8_bugbear::rules::BatchedWithoutExplicitStrict),
|
||||||
|
(Flake8Bugbear, "912") => (RuleGroup::Preview, rules::flake8_bugbear::rules::MapWithoutExplicitStrict),
|
||||||
|
|
||||||
// flake8-blind-except
|
// flake8-blind-except
|
||||||
(Flake8BlindExcept, "001") => (RuleGroup::Stable, rules::flake8_blind_except::rules::BlindExcept),
|
(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 ruff_text_size::{Ranged, TextRange};
|
||||||
|
|
||||||
use crate::Locator;
|
use crate::Locator;
|
||||||
|
use ruff_python_ast::{self as ast, Arguments, Expr};
|
||||||
|
|
||||||
/// Return `true` if the statement containing the current expression is the last
|
/// 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
|
/// 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())
|
.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::settings::LinterSettings;
|
||||||
use crate::test::test_path;
|
use crate::test::test_path;
|
||||||
|
|
||||||
|
use crate::settings::types::PreviewMode;
|
||||||
use ruff_python_ast::PythonVersion;
|
use ruff_python_ast::PythonVersion;
|
||||||
|
|
||||||
#[test_case(Rule::AbstractBaseClassWithoutAbstractMethod, Path::new("B024.py"))]
|
#[test_case(Rule::AbstractBaseClassWithoutAbstractMethod, Path::new("B024.py"))]
|
||||||
|
|
@ -81,11 +82,35 @@ mod tests {
|
||||||
Ok(())
|
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(
|
#[test_case(
|
||||||
Rule::ClassAsDataStructure,
|
Rule::ClassAsDataStructure,
|
||||||
Path::new("class_as_data_structure.py"),
|
Path::new("class_as_data_structure.py"),
|
||||||
PythonVersion::PY39
|
PythonVersion::PY39
|
||||||
)]
|
)]
|
||||||
|
#[test_case(
|
||||||
|
Rule::MapWithoutExplicitStrict,
|
||||||
|
Path::new("B912.py"),
|
||||||
|
PythonVersion::PY313
|
||||||
|
)]
|
||||||
fn rules_with_target_version(
|
fn rules_with_target_version(
|
||||||
rule_code: Rule,
|
rule_code: Rule,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use ruff_python_ast::ExprCall;
|
||||||
use ruff_python_ast::PythonVersion;
|
use ruff_python_ast::PythonVersion;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
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};
|
use crate::{FixAvailability, Violation};
|
||||||
|
|
||||||
/// ## What it does
|
/// ## 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 jump_statement_in_finally::*;
|
||||||
pub(crate) use loop_iterator_mutation::*;
|
pub(crate) use loop_iterator_mutation::*;
|
||||||
pub(crate) use loop_variable_overrides_iterator::*;
|
pub(crate) use loop_variable_overrides_iterator::*;
|
||||||
|
pub(crate) use map_without_explicit_strict::*;
|
||||||
pub(crate) use mutable_argument_default::*;
|
pub(crate) use mutable_argument_default::*;
|
||||||
pub(crate) use mutable_contextvar_default::*;
|
pub(crate) use mutable_contextvar_default::*;
|
||||||
pub(crate) use no_explicit_stacklevel::*;
|
pub(crate) use no_explicit_stacklevel::*;
|
||||||
|
|
@ -56,6 +57,7 @@ mod getattr_with_constant;
|
||||||
mod jump_statement_in_finally;
|
mod jump_statement_in_finally;
|
||||||
mod loop_iterator_mutation;
|
mod loop_iterator_mutation;
|
||||||
mod loop_variable_overrides_iterator;
|
mod loop_variable_overrides_iterator;
|
||||||
|
mod map_without_explicit_strict;
|
||||||
mod mutable_argument_default;
|
mod mutable_argument_default;
|
||||||
mod mutable_contextvar_default;
|
mod mutable_contextvar_default;
|
||||||
mod no_explicit_stacklevel;
|
mod no_explicit_stacklevel;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||||
|
|
||||||
use ruff_python_ast::{self as ast, Arguments, Expr};
|
use ruff_python_ast::{self as ast};
|
||||||
use ruff_python_semantic::SemanticModel;
|
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::fix::edits::add_argument;
|
use crate::fix::edits::add_argument;
|
||||||
|
use crate::rules::flake8_bugbear::helpers::any_infinite_iterables;
|
||||||
use crate::{AlwaysFixableViolation, Applicability, Fix};
|
use crate::{AlwaysFixableViolation, Applicability, Fix};
|
||||||
|
|
||||||
/// ## What it does
|
/// ## 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")
|
if semantic.match_builtin_expr(&call.func, "zip")
|
||||||
&& call.arguments.find_keyword("strict").is_none()
|
&& call.arguments.find_keyword("strict").is_none()
|
||||||
&& !call
|
&& !any_infinite_iterables(call.arguments.args.iter(), semantic)
|
||||||
.arguments
|
|
||||||
.args
|
|
||||||
.iter()
|
|
||||||
.any(|arg| is_infinite_iterable(arg, semantic))
|
|
||||||
{
|
{
|
||||||
checker
|
checker
|
||||||
.report_diagnostic(ZipWithoutExplicitStrict, call.range())
|
.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",
|
"B909",
|
||||||
"B91",
|
"B91",
|
||||||
"B911",
|
"B911",
|
||||||
|
"B912",
|
||||||
"BLE",
|
"BLE",
|
||||||
"BLE0",
|
"BLE0",
|
||||||
"BLE00",
|
"BLE00",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue