From 5ddf143cae100359ef9f22398f67463bd0bca43e Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 14 Aug 2023 15:24:16 -0400 Subject: [PATCH] Clarify FBT documentation and refine rule names (#6567) Closes https://github.com/astral-sh/ruff/issues/6530. --- .../src/checkers/ast/analyze/expression.rs | 6 +- .../src/checkers/ast/analyze/statement.rs | 8 +- crates/ruff/src/codes.rs | 6 +- crates/ruff/src/registry/rule_set.rs | 6 +- .../src/rules/flake8_boolean_trap/helpers.rs | 17 +-- .../ruff/src/rules/flake8_boolean_trap/mod.rs | 6 +- ...olean_default_value_positional_argument.rs | 126 ++++++++++++++++++ ...rs => boolean_positional_value_in_call.rs} | 32 ++--- ... boolean_type_hint_positional_argument.rs} | 44 ++++-- ...an_default_value_in_function_definition.rs | 91 ------------- .../rules/flake8_boolean_trap/rules/mod.rs | 12 +- ...e8_boolean_trap__tests__FBT001_FBT.py.snap | 36 ++--- ...e8_boolean_trap__tests__FBT002_FBT.py.snap | 16 +-- 13 files changed, 221 insertions(+), 185 deletions(-) create mode 100644 crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_default_value_positional_argument.rs rename crates/ruff/src/rules/flake8_boolean_trap/rules/{check_boolean_positional_value_in_function_call.rs => boolean_positional_value_in_call.rs} (60%) rename crates/ruff/src/rules/flake8_boolean_trap/rules/{check_positional_boolean_in_def.rs => boolean_type_hint_positional_argument.rs} (70%) delete mode 100644 crates/ruff/src/rules/flake8_boolean_trap/rules/check_boolean_default_value_in_function_definition.rs diff --git a/crates/ruff/src/checkers/ast/analyze/expression.rs b/crates/ruff/src/checkers/ast/analyze/expression.rs index 15cf51627d..2ea6293cdc 100644 --- a/crates/ruff/src/checkers/ast/analyze/expression.rs +++ b/crates/ruff/src/checkers/ast/analyze/expression.rs @@ -673,10 +673,8 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { checker, expr, func, args, keywords, ); } - if checker.enabled(Rule::BooleanPositionalValueInFunctionCall) { - flake8_boolean_trap::rules::check_boolean_positional_value_in_function_call( - checker, args, func, - ); + if checker.enabled(Rule::BooleanPositionalValueInCall) { + flake8_boolean_trap::rules::boolean_positional_value_in_call(checker, args, func); } if checker.enabled(Rule::Debugger) { flake8_debugger::rules::debugger_call(checker, expr, func); diff --git a/crates/ruff/src/checkers/ast/analyze/statement.rs b/crates/ruff/src/checkers/ast/analyze/statement.rs index c7f2d0223d..aeb82605fd 100644 --- a/crates/ruff/src/checkers/ast/analyze/statement.rs +++ b/crates/ruff/src/checkers/ast/analyze/statement.rs @@ -309,16 +309,16 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) { ]) { flake8_pytest_style::rules::marks(checker, decorator_list); } - if checker.enabled(Rule::BooleanPositionalArgInFunctionDefinition) { - flake8_boolean_trap::rules::check_positional_boolean_in_def( + if checker.enabled(Rule::BooleanTypeHintPositionalArgument) { + flake8_boolean_trap::rules::boolean_type_hint_positional_argument( checker, name, decorator_list, parameters, ); } - if checker.enabled(Rule::BooleanDefaultValueInFunctionDefinition) { - flake8_boolean_trap::rules::check_boolean_default_value_in_function_definition( + if checker.enabled(Rule::BooleanDefaultValuePositionalArgument) { + flake8_boolean_trap::rules::boolean_default_value_positional_argument( checker, name, decorator_list, diff --git a/crates/ruff/src/codes.rs b/crates/ruff/src/codes.rs index ba86706c6a..b8ac97ab17 100644 --- a/crates/ruff/src/codes.rs +++ b/crates/ruff/src/codes.rs @@ -568,9 +568,9 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> { (Flake8Bandit, "701") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::Jinja2AutoescapeFalse), // flake8-boolean-trap - (Flake8BooleanTrap, "001") => (RuleGroup::Unspecified, rules::flake8_boolean_trap::rules::BooleanPositionalArgInFunctionDefinition), - (Flake8BooleanTrap, "002") => (RuleGroup::Unspecified, rules::flake8_boolean_trap::rules::BooleanDefaultValueInFunctionDefinition), - (Flake8BooleanTrap, "003") => (RuleGroup::Unspecified, rules::flake8_boolean_trap::rules::BooleanPositionalValueInFunctionCall), + (Flake8BooleanTrap, "001") => (RuleGroup::Unspecified, rules::flake8_boolean_trap::rules::BooleanTypeHintPositionalArgument), + (Flake8BooleanTrap, "002") => (RuleGroup::Unspecified, rules::flake8_boolean_trap::rules::BooleanDefaultValuePositionalArgument), + (Flake8BooleanTrap, "003") => (RuleGroup::Unspecified, rules::flake8_boolean_trap::rules::BooleanPositionalValueInCall), // flake8-unused-arguments (Flake8UnusedArguments, "001") => (RuleGroup::Unspecified, rules::flake8_unused_arguments::rules::UnusedFunctionArgument), diff --git a/crates/ruff/src/registry/rule_set.rs b/crates/ruff/src/registry/rule_set.rs index 555ba0e5b2..e141a4e25e 100644 --- a/crates/ruff/src/registry/rule_set.rs +++ b/crates/ruff/src/registry/rule_set.rs @@ -72,7 +72,7 @@ impl RuleSet { /// let set_1 = RuleSet::from_rules(&[Rule::AmbiguousFunctionName, Rule::AnyType]); /// let set_2 = RuleSet::from_rules(&[ /// Rule::BadQuotesInlineString, - /// Rule::BooleanPositionalValueInFunctionCall, + /// Rule::BooleanPositionalValueInCall, /// ]); /// /// let union = set_1.union(&set_2); @@ -80,7 +80,7 @@ impl RuleSet { /// assert!(union.contains(Rule::AmbiguousFunctionName)); /// assert!(union.contains(Rule::AnyType)); /// assert!(union.contains(Rule::BadQuotesInlineString)); - /// assert!(union.contains(Rule::BooleanPositionalValueInFunctionCall)); + /// assert!(union.contains(Rule::BooleanPositionalValueInCall)); /// ``` #[must_use] pub const fn union(mut self, other: &Self) -> Self { @@ -132,7 +132,7 @@ impl RuleSet { /// ]))); /// /// assert!(!set_1.intersects(&RuleSet::from_rules(&[ - /// Rule::BooleanPositionalValueInFunctionCall, + /// Rule::BooleanPositionalValueInCall, /// Rule::BadQuotesInlineString /// ]))); /// ``` diff --git a/crates/ruff/src/rules/flake8_boolean_trap/helpers.rs b/crates/ruff/src/rules/flake8_boolean_trap/helpers.rs index 2c5f68aaa3..9e1e101e07 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/helpers.rs +++ b/crates/ruff/src/rules/flake8_boolean_trap/helpers.rs @@ -1,8 +1,4 @@ -use ruff_python_ast::{self as ast, Constant, Expr, Ranged}; - -use ruff_diagnostics::{Diagnostic, DiagnosticKind}; - -use crate::checkers::ast::Checker; +use ruff_python_ast::{self as ast, Constant, Expr}; /// Returns `true` if a function call is allowed to use a boolean trap. pub(super) fn is_allowed_func_call(name: &str) -> bool { @@ -62,18 +58,13 @@ pub(super) fn allow_boolean_trap(func: &Expr) -> bool { false } -const fn is_boolean_arg(arg: &Expr) -> bool { +/// Returns `true` if an expression is a boolean literal. +pub(super) const fn is_boolean(expr: &Expr) -> bool { matches!( - &arg, + &expr, Expr::Constant(ast::ExprConstant { value: Constant::Bool(_), .. }) ) } - -pub(super) fn add_if_boolean(checker: &mut Checker, arg: &Expr, kind: DiagnosticKind) { - if is_boolean_arg(arg) { - checker.diagnostics.push(Diagnostic::new(kind, arg.range())); - } -} diff --git a/crates/ruff/src/rules/flake8_boolean_trap/mod.rs b/crates/ruff/src/rules/flake8_boolean_trap/mod.rs index ab0d6f8741..7a4a1ff943 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/mod.rs +++ b/crates/ruff/src/rules/flake8_boolean_trap/mod.rs @@ -13,9 +13,9 @@ mod tests { use crate::test::test_path; use crate::{assert_messages, settings}; - #[test_case(Rule::BooleanPositionalArgInFunctionDefinition, Path::new("FBT.py"))] - #[test_case(Rule::BooleanDefaultValueInFunctionDefinition, Path::new("FBT.py"))] - #[test_case(Rule::BooleanPositionalValueInFunctionCall, Path::new("FBT.py"))] + #[test_case(Rule::BooleanTypeHintPositionalArgument, Path::new("FBT.py"))] + #[test_case(Rule::BooleanDefaultValuePositionalArgument, Path::new("FBT.py"))] + #[test_case(Rule::BooleanPositionalValueInCall, Path::new("FBT.py"))] fn rules(rule_code: Rule, path: &Path) -> Result<()> { let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy()); let diagnostics = test_path( diff --git a/crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_default_value_positional_argument.rs b/crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_default_value_positional_argument.rs new file mode 100644 index 0000000000..b80bff7752 --- /dev/null +++ b/crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_default_value_positional_argument.rs @@ -0,0 +1,126 @@ +use ruff_diagnostics::{Diagnostic, Violation}; +use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::call_path::collect_call_path; +use ruff_python_ast::{Decorator, ParameterWithDefault, Parameters, Ranged}; + +use crate::checkers::ast::Checker; +use crate::rules::flake8_boolean_trap::helpers::{is_allowed_func_def, is_boolean}; + +/// ## What it does +/// Checks for the use of boolean positional arguments in function definitions, +/// as determined by the presence of a boolean default value. +/// +/// ## Why is this bad? +/// Calling a function with boolean positional arguments is confusing as the +/// meaning of the boolean value is not clear to the caller and to future +/// readers of the code. +/// +/// The use of a boolean will also limit the function to only two possible +/// behaviors, which makes the function difficult to extend in the future. +/// +/// Instead, consider refactoring into separate implementations for the +/// `True` and `False` cases, using an `Enum`, or making the argument a +/// keyword-only argument, to force callers to be explicit when providing +/// the argument. +/// +/// ## Example +/// ```python +/// from math import ceil, floor +/// +/// +/// def round_number(number, up=True): +/// return ceil(number) if up else floor(number) +/// +/// +/// round_number(1.5, True) # What does `True` mean? +/// round_number(1.5, False) # What does `False` mean? +/// ``` +/// +/// Instead, refactor into separate implementations: +/// ```python +/// from math import ceil, floor +/// +/// +/// def round_up(number): +/// return ceil(number) +/// +/// +/// def round_down(number): +/// return floor(number) +/// +/// +/// round_up(1.5) +/// round_down(1.5) +/// ``` +/// +/// Or, refactor to use an `Enum`: +/// ```python +/// from enum import Enum +/// +/// +/// class RoundingMethod(Enum): +/// UP = 1 +/// DOWN = 2 +/// +/// +/// def round_number(value, method): +/// ... +/// ``` +/// +/// Or, make the argument a keyword-only argument: +/// ```python +/// from math import ceil, floor +/// +/// +/// def round_number(number, *, up=True): +/// return ceil(number) if up else floor(number) +/// +/// +/// round_number(1.5, up=True) +/// round_number(1.5, up=False) +/// ``` +/// +/// ## References +/// - [Python documentation: Calls](https://docs.python.org/3/reference/expressions.html#calls) +/// - [_How to Avoid “The Boolean Trap”_ by Adam Johnson](https://adamj.eu/tech/2021/07/10/python-type-hints-how-to-avoid-the-boolean-trap/) +#[violation] +pub struct BooleanDefaultValuePositionalArgument; + +impl Violation for BooleanDefaultValuePositionalArgument { + #[derive_message_formats] + fn message(&self) -> String { + format!("Boolean default positional argument in function definition") + } +} + +pub(crate) fn boolean_default_value_positional_argument( + checker: &mut Checker, + name: &str, + decorator_list: &[Decorator], + parameters: &Parameters, +) { + if is_allowed_func_def(name) { + return; + } + + if decorator_list.iter().any(|decorator| { + collect_call_path(&decorator.expression) + .is_some_and(|call_path| call_path.as_slice() == [name, "setter"]) + }) { + return; + } + + for ParameterWithDefault { + parameter, + default, + range: _, + } in parameters.posonlyargs.iter().chain(¶meters.args) + { + if default.as_ref().is_some_and(|default| is_boolean(default)) { + checker.diagnostics.push(Diagnostic::new( + BooleanDefaultValuePositionalArgument, + parameter.name.range(), + )); + } + } +} diff --git a/crates/ruff/src/rules/flake8_boolean_trap/rules/check_boolean_positional_value_in_function_call.rs b/crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_positional_value_in_call.rs similarity index 60% rename from crates/ruff/src/rules/flake8_boolean_trap/rules/check_boolean_positional_value_in_function_call.rs rename to crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_positional_value_in_call.rs index 6138fa67bd..0f6bf1fca7 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/rules/check_boolean_positional_value_in_function_call.rs +++ b/crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_positional_value_in_call.rs @@ -1,11 +1,9 @@ -use ruff_python_ast::Expr; - -use ruff_diagnostics::Violation; - +use ruff_diagnostics::{Diagnostic, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::{Expr, Ranged}; use crate::checkers::ast::Checker; -use crate::rules::flake8_boolean_trap::helpers::{add_if_boolean, allow_boolean_trap}; +use crate::rules::flake8_boolean_trap::helpers::{allow_boolean_trap, is_boolean}; /// ## What it does /// Checks for boolean positional arguments in function calls. @@ -17,44 +15,42 @@ use crate::rules::flake8_boolean_trap::helpers::{add_if_boolean, allow_boolean_t /// /// ## Example /// ```python -/// def foo(flag: bool) -> None: +/// def func(flag: bool) -> None: /// ... /// /// -/// foo(True) +/// func(True) /// ``` /// /// Use instead: /// ```python -/// def foo(flag: bool) -> None: +/// def func(flag: bool) -> None: /// ... /// /// -/// foo(flag=True) +/// func(flag=True) /// ``` /// /// ## References /// - [Python documentation: Calls](https://docs.python.org/3/reference/expressions.html#calls) /// - [_How to Avoid “The Boolean Trap”_ by Adam Johnson](https://adamj.eu/tech/2021/07/10/python-type-hints-how-to-avoid-the-boolean-trap/) #[violation] -pub struct BooleanPositionalValueInFunctionCall; +pub struct BooleanPositionalValueInCall; -impl Violation for BooleanPositionalValueInFunctionCall { +impl Violation for BooleanPositionalValueInCall { #[derive_message_formats] fn message(&self) -> String { format!("Boolean positional value in function call") } } -pub(crate) fn check_boolean_positional_value_in_function_call( - checker: &mut Checker, - args: &[Expr], - func: &Expr, -) { +pub(crate) fn boolean_positional_value_in_call(checker: &mut Checker, args: &[Expr], func: &Expr) { if allow_boolean_trap(func) { return; } - for arg in args { - add_if_boolean(checker, arg, BooleanPositionalValueInFunctionCall.into()); + for arg in args.iter().filter(|arg| is_boolean(arg)) { + checker + .diagnostics + .push(Diagnostic::new(BooleanPositionalValueInCall, arg.range())); } } diff --git a/crates/ruff/src/rules/flake8_boolean_trap/rules/check_positional_boolean_in_def.rs b/crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_type_hint_positional_argument.rs similarity index 70% rename from crates/ruff/src/rules/flake8_boolean_trap/rules/check_positional_boolean_in_def.rs rename to crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_type_hint_positional_argument.rs index b1197a75a7..cfe52b2829 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/rules/check_positional_boolean_in_def.rs +++ b/crates/ruff/src/rules/flake8_boolean_trap/rules/boolean_type_hint_positional_argument.rs @@ -11,16 +11,22 @@ use crate::checkers::ast::Checker; use crate::rules::flake8_boolean_trap::helpers::is_allowed_func_def; /// ## What it does -/// Checks for boolean positional arguments in function definitions. +/// Checks for the use of boolean positional arguments in function definitions, +/// as determined by the presence of a `bool` type hint. /// /// ## Why is this bad? /// Calling a function with boolean positional arguments is confusing as the -/// meaning of the boolean value is not clear to the caller, and to future +/// meaning of the boolean value is not clear to the caller and to future /// readers of the code. /// /// The use of a boolean will also limit the function to only two possible /// behaviors, which makes the function difficult to extend in the future. /// +/// Instead, consider refactoring into separate implementations for the +/// `True` and `False` cases, using an `Enum`, or making the argument a +/// keyword-only argument, to force callers to be explicit when providing +/// the argument. +/// /// ## Example /// ```python /// from math import ceil, floor @@ -65,20 +71,33 @@ use crate::rules::flake8_boolean_trap::helpers::is_allowed_func_def; /// ... /// ``` /// +/// Or, make the argument a keyword-only argument: +/// ```python +/// from math import ceil, floor +/// +/// +/// def round_number(number: float, *, up: bool) -> int: +/// return ceil(number) if up else floor(number) +/// +/// +/// round_number(1.5, up=True) +/// round_number(1.5, up=False) +/// ``` +/// /// ## References /// - [Python documentation: Calls](https://docs.python.org/3/reference/expressions.html#calls) /// - [_How to Avoid “The Boolean Trap”_ by Adam Johnson](https://adamj.eu/tech/2021/07/10/python-type-hints-how-to-avoid-the-boolean-trap/) #[violation] -pub struct BooleanPositionalArgInFunctionDefinition; +pub struct BooleanTypeHintPositionalArgument; -impl Violation for BooleanPositionalArgInFunctionDefinition { +impl Violation for BooleanTypeHintPositionalArgument { #[derive_message_formats] fn message(&self) -> String { - format!("Boolean positional arg in function definition") + format!("Boolean-typed positional argument in function definition") } } -pub(crate) fn check_positional_boolean_in_def( +pub(crate) fn boolean_type_hint_positional_argument( checker: &mut Checker, name: &str, decorator_list: &[Decorator], @@ -101,15 +120,12 @@ pub(crate) fn check_positional_boolean_in_def( range: _, } in parameters.posonlyargs.iter().chain(¶meters.args) { - if parameter.annotation.is_none() { - continue; - } - let Some(expr) = ¶meter.annotation else { + let Some(annotation) = parameter.annotation.as_ref() else { continue; }; // check for both bool (python class) and 'bool' (string annotation) - let hint = match expr.as_ref() { + let hint = match annotation.as_ref() { Expr::Name(name) => &name.id == "bool", Expr::Constant(ast::ExprConstant { value: Constant::Str(ast::StringConstant { value, .. }), @@ -117,12 +133,12 @@ pub(crate) fn check_positional_boolean_in_def( }) => value == "bool", _ => false, }; - if !hint { + if !hint || !checker.semantic().is_builtin("bool") { continue; } checker.diagnostics.push(Diagnostic::new( - BooleanPositionalArgInFunctionDefinition, - parameter.range(), + BooleanTypeHintPositionalArgument, + parameter.name.range(), )); } } diff --git a/crates/ruff/src/rules/flake8_boolean_trap/rules/check_boolean_default_value_in_function_definition.rs b/crates/ruff/src/rules/flake8_boolean_trap/rules/check_boolean_default_value_in_function_definition.rs deleted file mode 100644 index ecf8ff7dc8..0000000000 --- a/crates/ruff/src/rules/flake8_boolean_trap/rules/check_boolean_default_value_in_function_definition.rs +++ /dev/null @@ -1,91 +0,0 @@ -use ruff_python_ast::{Decorator, ParameterWithDefault, Parameters}; - -use ruff_diagnostics::Violation; -use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::call_path::collect_call_path; - -use crate::checkers::ast::Checker; -use crate::rules::flake8_boolean_trap::helpers::{add_if_boolean, is_allowed_func_def}; - -/// ## What it does -/// Checks for the use of booleans as default values in function definitions. -/// -/// ## Why is this bad? -/// Calling a function with boolean default means that the keyword argument -/// argument can be omitted, which makes the function call ambiguous. -/// -/// Instead, consider defining the relevant argument as a required keyword -/// argument to force callers to be explicit about their intent. -/// -/// ## Example -/// ```python -/// from math import ceil, floor -/// -/// -/// def round_number(number: float, up: bool = True) -> int: -/// return ceil(number) if up else floor(number) -/// -/// -/// round_number(1.5) -/// round_number(1.5, up=False) -/// ``` -/// -/// Use instead: -/// ```python -/// from math import ceil, floor -/// -/// -/// def round_number(number: float, *, up: bool) -> int: -/// return ceil(number) if up else floor(number) -/// -/// -/// round_number(1.5, up=True) -/// round_number(1.5, up=False) -/// ``` -/// -/// ## References -/// - [Python documentation: Calls](https://docs.python.org/3/reference/expressions.html#calls) -/// - [_How to Avoid “The Boolean Trap”_ by Adam Johnson](https://adamj.eu/tech/2021/07/10/python-type-hints-how-to-avoid-the-boolean-trap/) -#[violation] -pub struct BooleanDefaultValueInFunctionDefinition; - -impl Violation for BooleanDefaultValueInFunctionDefinition { - #[derive_message_formats] - fn message(&self) -> String { - format!("Boolean default value in function definition") - } -} - -pub(crate) fn check_boolean_default_value_in_function_definition( - checker: &mut Checker, - name: &str, - decorator_list: &[Decorator], - parameters: &Parameters, -) { - if is_allowed_func_def(name) { - return; - } - - if decorator_list.iter().any(|decorator| { - collect_call_path(&decorator.expression) - .is_some_and(|call_path| call_path.as_slice() == [name, "setter"]) - }) { - return; - } - - for ParameterWithDefault { - parameter: _, - default, - range: _, - } in parameters.args.iter().chain(¶meters.posonlyargs) - { - let Some(default) = default else { - continue; - }; - add_if_boolean( - checker, - default, - BooleanDefaultValueInFunctionDefinition.into(), - ); - } -} diff --git a/crates/ruff/src/rules/flake8_boolean_trap/rules/mod.rs b/crates/ruff/src/rules/flake8_boolean_trap/rules/mod.rs index b40aa58dc5..a9aae13b67 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/rules/mod.rs +++ b/crates/ruff/src/rules/flake8_boolean_trap/rules/mod.rs @@ -1,7 +1,7 @@ -pub(crate) use check_boolean_default_value_in_function_definition::*; -pub(crate) use check_boolean_positional_value_in_function_call::*; -pub(crate) use check_positional_boolean_in_def::*; +pub(crate) use boolean_default_value_positional_argument::*; +pub(crate) use boolean_positional_value_in_call::*; +pub(crate) use boolean_type_hint_positional_argument::*; -mod check_boolean_default_value_in_function_definition; -mod check_boolean_positional_value_in_function_call; -mod check_positional_boolean_in_def; +mod boolean_default_value_positional_argument; +mod boolean_positional_value_in_call; +mod boolean_type_hint_positional_argument; diff --git a/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT001_FBT.py.snap b/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT001_FBT.py.snap index f973bacf59..1c38f9930e 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT001_FBT.py.snap +++ b/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT001_FBT.py.snap @@ -1,91 +1,91 @@ --- source: crates/ruff/src/rules/flake8_boolean_trap/mod.rs --- -FBT.py:4:5: FBT001 Boolean positional arg in function definition +FBT.py:4:5: FBT001 Boolean-typed positional argument in function definition | 2 | posonly_nohint, 3 | posonly_nonboolhint: int, 4 | posonly_boolhint: bool, - | ^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^ FBT001 5 | posonly_boolstrhint: "bool", 6 | /, | -FBT.py:5:5: FBT001 Boolean positional arg in function definition +FBT.py:5:5: FBT001 Boolean-typed positional argument in function definition | 3 | posonly_nonboolhint: int, 4 | posonly_boolhint: bool, 5 | posonly_boolstrhint: "bool", - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^^^^ FBT001 6 | /, 7 | offset, | -FBT.py:10:5: FBT001 Boolean positional arg in function definition +FBT.py:10:5: FBT001 Boolean-typed positional argument in function definition | 8 | posorkw_nonvalued_nohint, 9 | posorkw_nonvalued_nonboolhint: int, 10 | posorkw_nonvalued_boolhint: bool, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 11 | posorkw_nonvalued_boolstrhint: "bool", 12 | posorkw_boolvalued_nohint=True, | -FBT.py:11:5: FBT001 Boolean positional arg in function definition +FBT.py:11:5: FBT001 Boolean-typed positional argument in function definition | 9 | posorkw_nonvalued_nonboolhint: int, 10 | posorkw_nonvalued_boolhint: bool, 11 | posorkw_nonvalued_boolstrhint: "bool", - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 12 | posorkw_boolvalued_nohint=True, 13 | posorkw_boolvalued_nonboolhint: int = True, | -FBT.py:14:5: FBT001 Boolean positional arg in function definition +FBT.py:14:5: FBT001 Boolean-typed positional argument in function definition | 12 | posorkw_boolvalued_nohint=True, 13 | posorkw_boolvalued_nonboolhint: int = True, 14 | posorkw_boolvalued_boolhint: bool = True, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 15 | posorkw_boolvalued_boolstrhint: "bool" = True, 16 | posorkw_nonboolvalued_nohint=1, | -FBT.py:15:5: FBT001 Boolean positional arg in function definition +FBT.py:15:5: FBT001 Boolean-typed positional argument in function definition | 13 | posorkw_boolvalued_nonboolhint: int = True, 14 | posorkw_boolvalued_boolhint: bool = True, 15 | posorkw_boolvalued_boolstrhint: "bool" = True, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 16 | posorkw_nonboolvalued_nohint=1, 17 | posorkw_nonboolvalued_nonboolhint: int = 2, | -FBT.py:18:5: FBT001 Boolean positional arg in function definition +FBT.py:18:5: FBT001 Boolean-typed positional argument in function definition | 16 | posorkw_nonboolvalued_nohint=1, 17 | posorkw_nonboolvalued_nonboolhint: int = 2, 18 | posorkw_nonboolvalued_boolhint: bool = 3, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 19 | posorkw_nonboolvalued_boolstrhint: "bool" = 4, 20 | *, | -FBT.py:19:5: FBT001 Boolean positional arg in function definition +FBT.py:19:5: FBT001 Boolean-typed positional argument in function definition | 17 | posorkw_nonboolvalued_nonboolhint: int = 2, 18 | posorkw_nonboolvalued_boolhint: bool = 3, 19 | posorkw_nonboolvalued_boolstrhint: "bool" = 4, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT001 20 | *, 21 | kwonly_nonvalued_nohint, | -FBT.py:86:19: FBT001 Boolean positional arg in function definition +FBT.py:86:19: FBT001 Boolean-typed positional argument in function definition | 85 | # FBT001: Boolean positional arg in function definition 86 | def foo(self, value: bool) -> None: - | ^^^^^^^^^^^ FBT001 + | ^^^^^ FBT001 87 | pass | diff --git a/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT002_FBT.py.snap b/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT002_FBT.py.snap index 5a76f50142..688254791d 100644 --- a/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT002_FBT.py.snap +++ b/crates/ruff/src/rules/flake8_boolean_trap/snapshots/ruff__rules__flake8_boolean_trap__tests__FBT002_FBT.py.snap @@ -1,42 +1,42 @@ --- source: crates/ruff/src/rules/flake8_boolean_trap/mod.rs --- -FBT.py:12:31: FBT002 Boolean default value in function definition +FBT.py:12:5: FBT002 Boolean default positional argument in function definition | 10 | posorkw_nonvalued_boolhint: bool, 11 | posorkw_nonvalued_boolstrhint: "bool", 12 | posorkw_boolvalued_nohint=True, - | ^^^^ FBT002 + | ^^^^^^^^^^^^^^^^^^^^^^^^^ FBT002 13 | posorkw_boolvalued_nonboolhint: int = True, 14 | posorkw_boolvalued_boolhint: bool = True, | -FBT.py:13:43: FBT002 Boolean default value in function definition +FBT.py:13:5: FBT002 Boolean default positional argument in function definition | 11 | posorkw_nonvalued_boolstrhint: "bool", 12 | posorkw_boolvalued_nohint=True, 13 | posorkw_boolvalued_nonboolhint: int = True, - | ^^^^ FBT002 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT002 14 | posorkw_boolvalued_boolhint: bool = True, 15 | posorkw_boolvalued_boolstrhint: "bool" = True, | -FBT.py:14:41: FBT002 Boolean default value in function definition +FBT.py:14:5: FBT002 Boolean default positional argument in function definition | 12 | posorkw_boolvalued_nohint=True, 13 | posorkw_boolvalued_nonboolhint: int = True, 14 | posorkw_boolvalued_boolhint: bool = True, - | ^^^^ FBT002 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT002 15 | posorkw_boolvalued_boolstrhint: "bool" = True, 16 | posorkw_nonboolvalued_nohint=1, | -FBT.py:15:46: FBT002 Boolean default value in function definition +FBT.py:15:5: FBT002 Boolean default positional argument in function definition | 13 | posorkw_boolvalued_nonboolhint: int = True, 14 | posorkw_boolvalued_boolhint: bool = True, 15 | posorkw_boolvalued_boolstrhint: "bool" = True, - | ^^^^ FBT002 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FBT002 16 | posorkw_nonboolvalued_nohint=1, 17 | posorkw_nonboolvalued_nonboolhint: int = 2, |