Implement B026 (#668)

This commit is contained in:
Harutaka Kawamura
2022-11-11 00:47:42 +09:00
committed by GitHub
parent 8213b64ad5
commit 05c19f0091
9 changed files with 139 additions and 3 deletions

View File

@@ -1064,6 +1064,11 @@ where
if self.settings.enabled.contains(&CheckCode::B005) {
flake8_bugbear::plugins::strip_with_multi_characters(self, expr, func, args);
}
if self.settings.enabled.contains(&CheckCode::B026) {
flake8_bugbear::plugins::star_arg_unpacking_after_keyword_arg(
self, args, keywords,
);
}
// flake8-comprehensions
if self.settings.enabled.contains(&CheckCode::C400) {

View File

@@ -92,6 +92,7 @@ pub enum CheckCode {
B017,
B018,
B025,
B026,
// flake8-comprehensions
C400,
C401,
@@ -356,6 +357,7 @@ pub enum CheckKind {
NoAssertRaisesException,
UselessExpression,
DuplicateTryBlockException(String),
StarArgUnpackingAfterKeywordArg,
// flake8-comprehensions
UnnecessaryGeneratorList,
UnnecessaryGeneratorSet,
@@ -569,6 +571,7 @@ impl CheckCode {
CheckCode::B017 => CheckKind::NoAssertRaisesException,
CheckCode::B018 => CheckKind::UselessExpression,
CheckCode::B025 => CheckKind::DuplicateTryBlockException("Exception".to_string()),
CheckCode::B026 => CheckKind::StarArgUnpackingAfterKeywordArg,
// flake8-comprehensions
CheckCode::C400 => CheckKind::UnnecessaryGeneratorList,
CheckCode::C401 => CheckKind::UnnecessaryGeneratorSet,
@@ -784,6 +787,7 @@ impl CheckCode {
CheckCode::B017 => CheckCategory::Flake8Bugbear,
CheckCode::B018 => CheckCategory::Flake8Bugbear,
CheckCode::B025 => CheckCategory::Flake8Bugbear,
CheckCode::B026 => CheckCategory::Flake8Bugbear,
CheckCode::C400 => CheckCategory::Flake8Comprehensions,
CheckCode::C401 => CheckCategory::Flake8Comprehensions,
CheckCode::C402 => CheckCategory::Flake8Comprehensions,
@@ -965,6 +969,7 @@ impl CheckKind {
CheckKind::NoAssertRaisesException => &CheckCode::B017,
CheckKind::UselessExpression => &CheckCode::B018,
CheckKind::DuplicateTryBlockException(_) => &CheckCode::B025,
CheckKind::StarArgUnpackingAfterKeywordArg => &CheckCode::B026,
// flake8-comprehensions
CheckKind::UnnecessaryGeneratorList => &CheckCode::C400,
CheckKind::UnnecessaryGeneratorSet => &CheckCode::C401,
@@ -1297,6 +1302,13 @@ impl CheckKind {
CheckKind::DuplicateTryBlockException(name) => {
format!("try-except block with duplicate exception `{name}`")
}
CheckKind::StarArgUnpackingAfterKeywordArg => {
"Star-arg unpacking after a keyword argument is strongly discouraged, because it \
only works when the keyword parameter is declared after all parameters supplied \
by the unpacked sequence, and this change of ordering can surprise and mislead \
readers."
.to_string()
}
// flake8-comprehensions
CheckKind::UnnecessaryGeneratorList => {
"Unnecessary generator (rewrite as a `list` comprehension)".to_string()
@@ -1675,6 +1687,9 @@ impl CheckKind {
CheckKind::NoAssertRaisesException => {
"`assertRaises(Exception):` should be considered evil.".to_string()
}
CheckKind::StarArgUnpackingAfterKeywordArg => {
"Star-arg unpacking after a keyword argument is strongly discouraged.".to_string()
}
_ => self.body(),
}
}

View File

@@ -53,6 +53,7 @@ pub enum CheckCodePrefix {
B018,
B02,
B025,
B026,
C,
C4,
C40,
@@ -343,6 +344,7 @@ impl CheckCodePrefix {
CheckCode::B017,
CheckCode::B018,
CheckCode::B025,
CheckCode::B026,
],
CheckCodePrefix::B0 => vec![
CheckCode::B002,
@@ -360,6 +362,7 @@ impl CheckCodePrefix {
CheckCode::B017,
CheckCode::B018,
CheckCode::B025,
CheckCode::B026,
],
CheckCodePrefix::B00 => vec![
CheckCode::B002,
@@ -393,8 +396,9 @@ impl CheckCodePrefix {
CheckCodePrefix::B016 => vec![CheckCode::B016],
CheckCodePrefix::B017 => vec![CheckCode::B017],
CheckCodePrefix::B018 => vec![CheckCode::B018],
CheckCodePrefix::B02 => vec![CheckCode::B025],
CheckCodePrefix::B02 => vec![CheckCode::B025, CheckCode::B026],
CheckCodePrefix::B025 => vec![CheckCode::B025],
CheckCodePrefix::B026 => vec![CheckCode::B026],
CheckCodePrefix::C => vec![
CheckCode::C400,
CheckCode::C401,
@@ -1057,6 +1061,7 @@ impl CheckCodePrefix {
CheckCodePrefix::B018 => PrefixSpecificity::Explicit,
CheckCodePrefix::B02 => PrefixSpecificity::Tens,
CheckCodePrefix::B025 => PrefixSpecificity::Explicit,
CheckCodePrefix::B026 => PrefixSpecificity::Explicit,
CheckCodePrefix::C => PrefixSpecificity::Category,
CheckCodePrefix::C4 => PrefixSpecificity::Hundreds,
CheckCodePrefix::C40 => PrefixSpecificity::Tens,

View File

@@ -6,6 +6,7 @@ pub use duplicate_exceptions::{duplicate_exceptions, duplicate_handler_exception
pub use function_call_argument_default::function_call_argument_default;
pub use mutable_argument_default::mutable_argument_default;
pub use redundant_tuple_in_exception_handler::redundant_tuple_in_exception_handler;
pub use star_arg_unpacking_after_keyword_arg::star_arg_unpacking_after_keyword_arg;
pub use strip_with_multi_characters::strip_with_multi_characters;
pub use unary_prefix_increment::unary_prefix_increment;
pub use unreliable_callable_check::unreliable_callable_check;
@@ -21,6 +22,7 @@ mod duplicate_exceptions;
mod function_call_argument_default;
mod mutable_argument_default;
mod redundant_tuple_in_exception_handler;
mod star_arg_unpacking_after_keyword_arg;
mod strip_with_multi_characters;
mod unary_prefix_increment;
mod unreliable_callable_check;

View File

@@ -0,0 +1,25 @@
use rustpython_ast::{Expr, ExprKind, Keyword};
use crate::ast::types::Range;
use crate::check_ast::Checker;
use crate::checks::{Check, CheckKind};
/// B026
pub fn star_arg_unpacking_after_keyword_arg(
checker: &mut Checker,
args: &[Expr],
keywords: &[Keyword],
) {
if let Some(keyword) = keywords.first() {
for arg in args {
if let ExprKind::Starred { .. } = arg.node {
if arg.location > keyword.location {
checker.add_check(Check::new(
CheckKind::StarArgUnpackingAfterKeywordArg,
Range::from_located(arg),
));
}
}
}
}
}

View File

@@ -307,6 +307,7 @@ mod tests {
#[test_case(CheckCode::B017, Path::new("B017.py"); "B017")]
#[test_case(CheckCode::B018, Path::new("B018.py"); "B018")]
#[test_case(CheckCode::B025, Path::new("B025.py"); "B025")]
#[test_case(CheckCode::B026, Path::new("B026.py"); "B026")]
#[test_case(CheckCode::C400, Path::new("C400.py"); "C400")]
#[test_case(CheckCode::C401, Path::new("C401.py"); "C401")]
#[test_case(CheckCode::C402, Path::new("C402.py"); "C402")]

View File

@@ -0,0 +1,61 @@
---
source: src/linter.rs
expression: checks
---
- kind: StarArgUnpackingAfterKeywordArg
location:
row: 16
column: 15
end_location:
row: 16
column: 30
fix: ~
- kind: StarArgUnpackingAfterKeywordArg
location:
row: 17
column: 15
end_location:
row: 17
column: 23
fix: ~
- kind: StarArgUnpackingAfterKeywordArg
location:
row: 18
column: 26
end_location:
row: 18
column: 34
fix: ~
- kind: StarArgUnpackingAfterKeywordArg
location:
row: 19
column: 37
end_location:
row: 19
column: 40
fix: ~
- kind: StarArgUnpackingAfterKeywordArg
location:
row: 20
column: 15
end_location:
row: 20
column: 23
fix: ~
- kind: StarArgUnpackingAfterKeywordArg
location:
row: 20
column: 25
end_location:
row: 20
column: 33
fix: ~
- kind: StarArgUnpackingAfterKeywordArg
location:
row: 21
column: 25
end_location:
row: 21
column: 33
fix: ~