Properly combine CLI and pyproject.toml ignores and selects (#329)

This commit is contained in:
Charlie Marsh 2022-10-04 20:07:17 -04:00 committed by GitHub
parent f80d5e70dd
commit 5bf8b13644
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 195 additions and 162 deletions

View file

@ -234,7 +234,7 @@ where
} }
} }
if self.settings.select.contains(&CheckCode::E741) { if self.settings.enabled.contains(&CheckCode::E741) {
let location = self.locate_check(Range::from_located(stmt)); let location = self.locate_check(Range::from_located(stmt));
self.checks.extend( self.checks.extend(
names.iter().filter_map(|name| { names.iter().filter_map(|name| {
@ -244,7 +244,7 @@ where
} }
} }
StmtKind::Break => { StmtKind::Break => {
if self.settings.select.contains(&CheckCode::F701) { if self.settings.enabled.contains(&CheckCode::F701) {
if let Some(check) = checks::check_break_outside_loop( if let Some(check) = checks::check_break_outside_loop(
stmt, stmt,
&self.parents, &self.parents,
@ -256,7 +256,7 @@ where
} }
} }
StmtKind::Continue => { StmtKind::Continue => {
if self.settings.select.contains(&CheckCode::F702) { if self.settings.enabled.contains(&CheckCode::F702) {
if let Some(check) = checks::check_continue_outside_loop( if let Some(check) = checks::check_continue_outside_loop(
stmt, stmt,
&self.parents, &self.parents,
@ -281,7 +281,7 @@ where
args, args,
.. ..
} => { } => {
if self.settings.select.contains(&CheckCode::E743) { if self.settings.enabled.contains(&CheckCode::E743) {
if let Some(check) = checks::check_ambiguous_function_name( if let Some(check) = checks::check_ambiguous_function_name(
name, name,
self.locate_check(Range::from_located(stmt)), self.locate_check(Range::from_located(stmt)),
@ -342,7 +342,7 @@ where
StmtKind::Return { .. } => { StmtKind::Return { .. } => {
if self if self
.settings .settings
.select .enabled
.contains(CheckKind::ReturnOutsideFunction.code()) .contains(CheckKind::ReturnOutsideFunction.code())
{ {
if let Some(scope_index) = self.scope_stack.last().cloned() { if let Some(scope_index) = self.scope_stack.last().cloned() {
@ -365,7 +365,7 @@ where
decorator_list, decorator_list,
.. ..
} => { } => {
if self.settings.select.contains(&CheckCode::R001) { if self.settings.enabled.contains(&CheckCode::R001) {
let scope = let scope =
&self.scopes[*(self.scope_stack.last().expect("No current scope found."))]; &self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
if let Some(check) = checks::check_useless_object_inheritance( if let Some(check) = checks::check_useless_object_inheritance(
@ -381,7 +381,7 @@ where
} }
} }
if self.settings.select.contains(&CheckCode::E742) { if self.settings.enabled.contains(&CheckCode::E742) {
if let Some(check) = checks::check_ambiguous_class_name( if let Some(check) = checks::check_ambiguous_class_name(
name, name,
self.locate_check(Range::from_located(stmt)), self.locate_check(Range::from_located(stmt)),
@ -410,7 +410,7 @@ where
StmtKind::Import { names } => { StmtKind::Import { names } => {
if self if self
.settings .settings
.select .enabled
.contains(CheckKind::ModuleImportNotAtTopOfFile.code()) .contains(CheckKind::ModuleImportNotAtTopOfFile.code())
&& self.seen_non_import && self.seen_non_import
&& stmt.location.column() == 1 && stmt.location.column() == 1
@ -470,7 +470,7 @@ where
} => { } => {
if self if self
.settings .settings
.select .enabled
.contains(CheckKind::ModuleImportNotAtTopOfFile.code()) .contains(CheckKind::ModuleImportNotAtTopOfFile.code())
&& self.seen_non_import && self.seen_non_import
&& stmt.location.column() == 1 && stmt.location.column() == 1
@ -508,7 +508,7 @@ where
self.annotations_future_enabled = true; self.annotations_future_enabled = true;
} }
if self.settings.select.contains(&CheckCode::F407) if self.settings.enabled.contains(&CheckCode::F407)
&& !ALL_FEATURE_NAMES.contains(&alias.node.name.deref()) && !ALL_FEATURE_NAMES.contains(&alias.node.name.deref())
{ {
self.checks.push(Check::new( self.checks.push(Check::new(
@ -517,7 +517,7 @@ where
)); ));
} }
if self.settings.select.contains(&CheckCode::F404) && !self.futures_allowed if self.settings.enabled.contains(&CheckCode::F404) && !self.futures_allowed
{ {
self.checks.push(Check::new( self.checks.push(Check::new(
CheckKind::LateFutureImport, CheckKind::LateFutureImport,
@ -540,7 +540,7 @@ where
}, },
); );
if self.settings.select.contains(&CheckCode::F406) { if self.settings.enabled.contains(&CheckCode::F406) {
let scope = &self.scopes let scope = &self.scopes
[*(self.scope_stack.last().expect("No current scope found."))]; [*(self.scope_stack.last().expect("No current scope found."))];
if !matches!(scope.kind, ScopeKind::Module) { if !matches!(scope.kind, ScopeKind::Module) {
@ -551,7 +551,7 @@ where
} }
} }
if self.settings.select.contains(&CheckCode::F403) { if self.settings.enabled.contains(&CheckCode::F403) {
self.checks.push(Check::new( self.checks.push(Check::new(
CheckKind::ImportStarUsed(module_name.to_string()), CheckKind::ImportStarUsed(module_name.to_string()),
self.locate_check(Range::from_located(stmt)), self.locate_check(Range::from_located(stmt)),
@ -584,7 +584,7 @@ where
} }
} }
StmtKind::Raise { exc, .. } => { StmtKind::Raise { exc, .. } => {
if self.settings.select.contains(&CheckCode::F901) { if self.settings.enabled.contains(&CheckCode::F901) {
if let Some(expr) = exc { if let Some(expr) = exc {
if let Some(check) = checks::check_raise_not_implemented(expr) { if let Some(check) = checks::check_raise_not_implemented(expr) {
self.checks.push(check); self.checks.push(check);
@ -596,7 +596,7 @@ where
self.handle_node_load(target); self.handle_node_load(target);
} }
StmtKind::If { test, .. } => { StmtKind::If { test, .. } => {
if self.settings.select.contains(&CheckCode::F634) { if self.settings.enabled.contains(&CheckCode::F634) {
if let Some(check) = if let Some(check) =
checks::check_if_tuple(test, self.locate_check(Range::from_located(stmt))) checks::check_if_tuple(test, self.locate_check(Range::from_located(stmt)))
{ {
@ -605,7 +605,11 @@ where
} }
} }
StmtKind::Assert { test, .. } => { StmtKind::Assert { test, .. } => {
if self.settings.select.contains(CheckKind::AssertTuple.code()) { if self
.settings
.enabled
.contains(CheckKind::AssertTuple.code())
{
if let Some(check) = checks::check_assert_tuple( if let Some(check) = checks::check_assert_tuple(
test, test,
self.locate_check(Range::from_located(stmt)), self.locate_check(Range::from_located(stmt)),
@ -615,14 +619,14 @@ where
} }
} }
StmtKind::Try { handlers, .. } => { StmtKind::Try { handlers, .. } => {
if self.settings.select.contains(&CheckCode::F707) { if self.settings.enabled.contains(&CheckCode::F707) {
if let Some(check) = checks::check_default_except_not_last(handlers) { if let Some(check) = checks::check_default_except_not_last(handlers) {
self.checks.push(check); self.checks.push(check);
} }
} }
} }
StmtKind::Assign { targets, value, .. } => { StmtKind::Assign { targets, value, .. } => {
if self.settings.select.contains(&CheckCode::E731) { if self.settings.enabled.contains(&CheckCode::E731) {
if let Some(check) = checks::check_do_not_assign_lambda( if let Some(check) = checks::check_do_not_assign_lambda(
value, value,
self.locate_check(Range::from_located(stmt)), self.locate_check(Range::from_located(stmt)),
@ -630,7 +634,7 @@ where
self.checks.push(check); self.checks.push(check);
} }
} }
if self.settings.select.contains(&CheckCode::U001) { if self.settings.enabled.contains(&CheckCode::U001) {
if let Some(mut check) = checks::check_useless_metaclass_type( if let Some(mut check) = checks::check_useless_metaclass_type(
targets, targets,
value, value,
@ -663,7 +667,7 @@ where
} }
} }
StmtKind::AnnAssign { value, .. } => { StmtKind::AnnAssign { value, .. } => {
if self.settings.select.contains(&CheckCode::E731) { if self.settings.enabled.contains(&CheckCode::E731) {
if let Some(value) = value { if let Some(value) = value {
if let Some(check) = checks::check_do_not_assign_lambda( if let Some(check) = checks::check_do_not_assign_lambda(
value, value,
@ -743,9 +747,9 @@ where
ExprKind::Tuple { elts, ctx } | ExprKind::List { elts, ctx } => { ExprKind::Tuple { elts, ctx } | ExprKind::List { elts, ctx } => {
if matches!(ctx, ExprContext::Store) { if matches!(ctx, ExprContext::Store) {
let check_too_many_expressions = let check_too_many_expressions =
self.settings.select.contains(&CheckCode::F621); self.settings.enabled.contains(&CheckCode::F621);
let check_two_starred_expressions = let check_two_starred_expressions =
self.settings.select.contains(&CheckCode::F622); self.settings.enabled.contains(&CheckCode::F622);
if let Some(check) = checks::check_starred_expressions( if let Some(check) = checks::check_starred_expressions(
elts, elts,
check_too_many_expressions, check_too_many_expressions,
@ -759,7 +763,7 @@ where
ExprKind::Name { id, ctx } => match ctx { ExprKind::Name { id, ctx } => match ctx {
ExprContext::Load => self.handle_node_load(expr), ExprContext::Load => self.handle_node_load(expr),
ExprContext::Store => { ExprContext::Store => {
if self.settings.select.contains(&CheckCode::E741) { if self.settings.enabled.contains(&CheckCode::E741) {
if let Some(check) = checks::check_ambiguous_variable_name( if let Some(check) = checks::check_ambiguous_variable_name(
id, id,
self.locate_check(Range::from_located(expr)), self.locate_check(Range::from_located(expr)),
@ -777,14 +781,14 @@ where
ExprContext::Del => self.handle_node_delete(expr), ExprContext::Del => self.handle_node_delete(expr),
}, },
ExprKind::Call { func, args, .. } => { ExprKind::Call { func, args, .. } => {
if self.settings.select.contains(&CheckCode::R002) { if self.settings.enabled.contains(&CheckCode::R002) {
if let Some(check) = checks::check_assert_equals(func, self.autofix) { if let Some(check) = checks::check_assert_equals(func, self.autofix) {
self.checks.push(check) self.checks.push(check)
} }
} }
// flake8-super // flake8-super
if self.settings.select.contains(&CheckCode::SPR001) { if self.settings.enabled.contains(&CheckCode::SPR001) {
// Only bother going through the super check at all if we're in a `super` call. // Only bother going through the super check at all if we're in a `super` call.
// (We check this in `check_super_args` too, so this is just an optimization.) // (We check this in `check_super_args` too, so this is just an optimization.)
if checks::is_super_call_with_arguments(func, args) { if checks::is_super_call_with_arguments(func, args) {
@ -811,8 +815,8 @@ where
} }
// flake8-print // flake8-print
if self.settings.select.contains(&CheckCode::T201) if self.settings.enabled.contains(&CheckCode::T201)
|| self.settings.select.contains(&CheckCode::T203) || self.settings.enabled.contains(&CheckCode::T203)
{ {
if let Some(mut check) = checks::check_print_call(expr, func) { if let Some(mut check) = checks::check_print_call(expr, func) {
if matches!(self.autofix, fixer::Mode::Generate | fixer::Mode::Apply) { if matches!(self.autofix, fixer::Mode::Generate | fixer::Mode::Apply) {
@ -863,8 +867,8 @@ where
} }
} }
ExprKind::Dict { keys, .. } => { ExprKind::Dict { keys, .. } => {
let check_repeated_literals = self.settings.select.contains(&CheckCode::F601); let check_repeated_literals = self.settings.enabled.contains(&CheckCode::F601);
let check_repeated_variables = self.settings.select.contains(&CheckCode::F602); let check_repeated_variables = self.settings.enabled.contains(&CheckCode::F602);
if check_repeated_literals || check_repeated_variables { if check_repeated_literals || check_repeated_variables {
self.checks.extend(checks::check_repeated_keys( self.checks.extend(checks::check_repeated_keys(
keys, keys,
@ -879,7 +883,7 @@ where
&self.scopes[*(self.scope_stack.last().expect("No current scope found."))]; &self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
if self if self
.settings .settings
.select .enabled
.contains(CheckKind::YieldOutsideFunction.code()) .contains(CheckKind::YieldOutsideFunction.code())
&& matches!(scope.kind, ScopeKind::Class | ScopeKind::Module) && matches!(scope.kind, ScopeKind::Class | ScopeKind::Module)
{ {
@ -893,7 +897,7 @@ where
if self.in_f_string.is_none() if self.in_f_string.is_none()
&& self && self
.settings .settings
.select .enabled
.contains(CheckKind::FStringMissingPlaceholders.code()) .contains(CheckKind::FStringMissingPlaceholders.code())
&& !values && !values
.iter() .iter()
@ -911,7 +915,7 @@ where
op: Operator::RShift, op: Operator::RShift,
.. ..
} => { } => {
if self.settings.select.contains(&CheckCode::F633) { if self.settings.enabled.contains(&CheckCode::F633) {
if let ExprKind::Name { id, .. } = &left.node { if let ExprKind::Name { id, .. } = &left.node {
if id == "print" { if id == "print" {
let scope = &self.scopes let scope = &self.scopes
@ -931,8 +935,8 @@ where
} }
} }
ExprKind::UnaryOp { op, operand } => { ExprKind::UnaryOp { op, operand } => {
let check_not_in = self.settings.select.contains(&CheckCode::E713); let check_not_in = self.settings.enabled.contains(&CheckCode::E713);
let check_not_is = self.settings.select.contains(&CheckCode::E714); let check_not_is = self.settings.enabled.contains(&CheckCode::E714);
if check_not_in || check_not_is { if check_not_in || check_not_is {
self.checks.extend(checks::check_not_tests( self.checks.extend(checks::check_not_tests(
op, op,
@ -948,8 +952,8 @@ where
ops, ops,
comparators, comparators,
} => { } => {
let check_none_comparisons = self.settings.select.contains(&CheckCode::E711); let check_none_comparisons = self.settings.enabled.contains(&CheckCode::E711);
let check_true_false_comparisons = self.settings.select.contains(&CheckCode::E712); let check_true_false_comparisons = self.settings.enabled.contains(&CheckCode::E712);
if check_none_comparisons || check_true_false_comparisons { if check_none_comparisons || check_true_false_comparisons {
self.checks.extend(checks::check_literal_comparisons( self.checks.extend(checks::check_literal_comparisons(
left, left,
@ -961,7 +965,7 @@ where
)); ));
} }
if self.settings.select.contains(&CheckCode::F632) { if self.settings.enabled.contains(&CheckCode::F632) {
self.checks.extend(checks::check_is_literal( self.checks.extend(checks::check_is_literal(
left, left,
ops, ops,
@ -970,7 +974,7 @@ where
)); ));
} }
if self.settings.select.contains(&CheckCode::E721) { if self.settings.enabled.contains(&CheckCode::E721) {
self.checks.extend(checks::check_type_comparison( self.checks.extend(checks::check_type_comparison(
ops, ops,
comparators, comparators,
@ -1164,7 +1168,7 @@ where
fn visit_excepthandler(&mut self, excepthandler: &'b Excepthandler) { fn visit_excepthandler(&mut self, excepthandler: &'b Excepthandler) {
match &excepthandler.node { match &excepthandler.node {
ExcepthandlerKind::ExceptHandler { type_, name, .. } => { ExcepthandlerKind::ExceptHandler { type_, name, .. } => {
if self.settings.select.contains(&CheckCode::E722) && type_.is_none() { if self.settings.enabled.contains(&CheckCode::E722) && type_.is_none() {
self.checks.push(Check::new( self.checks.push(Check::new(
CheckKind::DoNotUseBareExcept, CheckKind::DoNotUseBareExcept,
Range::from_located(excepthandler), Range::from_located(excepthandler),
@ -1172,7 +1176,7 @@ where
} }
match name { match name {
Some(name) => { Some(name) => {
if self.settings.select.contains(&CheckCode::E741) { if self.settings.enabled.contains(&CheckCode::E741) {
if let Some(check) = checks::check_ambiguous_variable_name( if let Some(check) = checks::check_ambiguous_variable_name(
name, name,
self.locate_check(Range::from_located(excepthandler)), self.locate_check(Range::from_located(excepthandler)),
@ -1227,7 +1231,7 @@ where
let scope = &mut self.scopes let scope = &mut self.scopes
[*(self.scope_stack.last().expect("No current scope found."))]; [*(self.scope_stack.last().expect("No current scope found."))];
if let Some(binding) = &scope.values.remove(name) { if let Some(binding) = &scope.values.remove(name) {
if self.settings.select.contains(&CheckCode::F841) if self.settings.enabled.contains(&CheckCode::F841)
&& binding.used.is_none() && binding.used.is_none()
{ {
self.checks.push(Check::new( self.checks.push(Check::new(
@ -1248,7 +1252,7 @@ where
} }
fn visit_arguments(&mut self, arguments: &'b Arguments) { fn visit_arguments(&mut self, arguments: &'b Arguments) {
if self.settings.select.contains(&CheckCode::F831) { if self.settings.enabled.contains(&CheckCode::F831) {
self.checks self.checks
.extend(checks::check_duplicate_arguments(arguments)); .extend(checks::check_duplicate_arguments(arguments));
} }
@ -1282,7 +1286,7 @@ where
}, },
); );
if self.settings.select.contains(&CheckCode::E741) { if self.settings.enabled.contains(&CheckCode::E741) {
if let Some(check) = checks::check_ambiguous_variable_name( if let Some(check) = checks::check_ambiguous_variable_name(
&arg.node.arg, &arg.node.arg,
self.locate_check(Range::from_located(arg)), self.locate_check(Range::from_located(arg)),
@ -1368,7 +1372,7 @@ impl<'a> Checker<'a> {
let binding = match scope.values.get(&name) { let binding = match scope.values.get(&name) {
None => binding, None => binding,
Some(existing) => { Some(existing) => {
if self.settings.select.contains(&CheckCode::F402) if self.settings.enabled.contains(&CheckCode::F402)
&& matches!(binding.kind, BindingKind::LoopVar) && matches!(binding.kind, BindingKind::LoopVar)
&& matches!( && matches!(
existing.kind, existing.kind,
@ -1422,7 +1426,7 @@ impl<'a> Checker<'a> {
} }
if import_starred { if import_starred {
if self.settings.select.contains(&CheckCode::F405) { if self.settings.enabled.contains(&CheckCode::F405) {
let mut from_list = vec![]; let mut from_list = vec![];
for scope_index in self.scope_stack.iter().rev() { for scope_index in self.scope_stack.iter().rev() {
let scope = &self.scopes[*scope_index]; let scope = &self.scopes[*scope_index];
@ -1442,7 +1446,7 @@ impl<'a> Checker<'a> {
return; return;
} }
if self.settings.select.contains(&CheckCode::F821) { if self.settings.enabled.contains(&CheckCode::F821) {
// Allow __path__. // Allow __path__.
if self.path.ends_with("__init__.py") && id == "__path__" { if self.path.ends_with("__init__.py") && id == "__path__" {
return; return;
@ -1460,7 +1464,7 @@ impl<'a> Checker<'a> {
let current = let current =
&self.scopes[*(self.scope_stack.last().expect("No current scope found."))]; &self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
if self.settings.select.contains(&CheckCode::F823) if self.settings.enabled.contains(&CheckCode::F823)
&& matches!(current.kind, ScopeKind::Function(_)) && matches!(current.kind, ScopeKind::Function(_))
&& !current.values.contains_key(id) && !current.values.contains_key(id)
{ {
@ -1560,7 +1564,7 @@ impl<'a> Checker<'a> {
let scope = let scope =
&mut self.scopes[*(self.scope_stack.last().expect("No current scope found."))]; &mut self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
if scope.values.remove(id).is_none() && self.settings.select.contains(&CheckCode::F821) if scope.values.remove(id).is_none() && self.settings.enabled.contains(&CheckCode::F821)
{ {
self.checks.push(Check::new( self.checks.push(Check::new(
CheckKind::UndefinedName(id.clone()), CheckKind::UndefinedName(id.clone()),
@ -1586,7 +1590,7 @@ impl<'a> Checker<'a> {
if let Ok(mut expr) = parser::parse_expression(expression, "<filename>") { if let Ok(mut expr) = parser::parse_expression(expression, "<filename>") {
relocate_expr(&mut expr, location); relocate_expr(&mut expr, location);
allocator.push(expr); allocator.push(expr);
} else if self.settings.select.contains(&CheckCode::F722) { } else if self.settings.enabled.contains(&CheckCode::F722) {
self.checks.push(Check::new( self.checks.push(Check::new(
CheckKind::ForwardAnnotationSyntaxError(expression.to_string()), CheckKind::ForwardAnnotationSyntaxError(expression.to_string()),
self.locate_check(location), self.locate_check(location),
@ -1641,7 +1645,7 @@ impl<'a> Checker<'a> {
} }
fn check_deferred_assignments(&mut self) { fn check_deferred_assignments(&mut self) {
if self.settings.select.contains(&CheckCode::F841) { if self.settings.enabled.contains(&CheckCode::F841) {
while let Some(index) = self.deferred_assignments.pop() { while let Some(index) = self.deferred_assignments.pop() {
self.checks.extend(checks::check_unused_variables( self.checks.extend(checks::check_unused_variables(
&self.scopes[index], &self.scopes[index],
@ -1653,9 +1657,9 @@ impl<'a> Checker<'a> {
} }
fn check_dead_scopes(&mut self) { fn check_dead_scopes(&mut self) {
if !self.settings.select.contains(&CheckCode::F401) if !self.settings.enabled.contains(&CheckCode::F401)
&& !self.settings.select.contains(&CheckCode::F405) && !self.settings.enabled.contains(&CheckCode::F405)
&& !self.settings.select.contains(&CheckCode::F822) && !self.settings.enabled.contains(&CheckCode::F822)
{ {
return; return;
} }
@ -1669,7 +1673,7 @@ impl<'a> Checker<'a> {
_ => None, _ => None,
}); });
if self.settings.select.contains(&CheckCode::F822) if self.settings.enabled.contains(&CheckCode::F822)
&& !scope.import_starred && !scope.import_starred
&& !self.path.ends_with("__init__.py") && !self.path.ends_with("__init__.py")
{ {
@ -1687,7 +1691,7 @@ impl<'a> Checker<'a> {
} }
} }
if self.settings.select.contains(&CheckCode::F405) && scope.import_starred { if self.settings.enabled.contains(&CheckCode::F405) && scope.import_starred {
if let Some(all_binding) = all_binding { if let Some(all_binding) = all_binding {
if let Some(names) = all_names { if let Some(names) = all_names {
let mut from_list = vec![]; let mut from_list = vec![];
@ -1710,7 +1714,7 @@ impl<'a> Checker<'a> {
} }
} }
if self.settings.select.contains(&CheckCode::F401) { if self.settings.enabled.contains(&CheckCode::F401) {
// Collect all unused imports by location. (Multiple unused imports at the same // Collect all unused imports by location. (Multiple unused imports at the same
// location indicates an `import from`.) // location indicates an `import from`.)
let mut unused: BTreeMap<(ImportKind, usize, Option<usize>), Vec<&str>> = let mut unused: BTreeMap<(ImportKind, usize, Option<usize>), Vec<&str>> =
@ -1793,7 +1797,7 @@ impl<'a> Checker<'a> {
// flake8-builtins // flake8-builtins
if is_attribute && matches!(scope.kind, ScopeKind::Class) { if is_attribute && matches!(scope.kind, ScopeKind::Class) {
if self.settings.select.contains(&CheckCode::A003) { if self.settings.enabled.contains(&CheckCode::A003) {
if let Some(check) = checks::check_builtin_shadowing( if let Some(check) = checks::check_builtin_shadowing(
name, name,
self.locate_check(location), self.locate_check(location),
@ -1802,7 +1806,7 @@ impl<'a> Checker<'a> {
self.checks.push(check); self.checks.push(check);
} }
} }
} else if self.settings.select.contains(&CheckCode::A001) { } else if self.settings.enabled.contains(&CheckCode::A001) {
if let Some(check) = checks::check_builtin_shadowing( if let Some(check) = checks::check_builtin_shadowing(
name, name,
self.locate_check(location), self.locate_check(location),
@ -1814,7 +1818,7 @@ impl<'a> Checker<'a> {
} }
fn check_builtin_arg_shadowing(&mut self, name: &str, location: Range) { fn check_builtin_arg_shadowing(&mut self, name: &str, location: Range) {
if self.settings.select.contains(&CheckCode::A002) { if self.settings.enabled.contains(&CheckCode::A002) {
if let Some(check) = checks::check_builtin_shadowing( if let Some(check) = checks::check_builtin_shadowing(
name, name,
self.locate_check(location), self.locate_check(location),

View file

@ -32,8 +32,8 @@ pub fn check_lines(
settings: &Settings, settings: &Settings,
autofix: &fixer::Mode, autofix: &fixer::Mode,
) { ) {
let enforce_line_too_long = settings.select.contains(&CheckCode::E501); let enforce_line_too_long = settings.enabled.contains(&CheckCode::E501);
let enforce_noqa = settings.select.contains(&CheckCode::M001); let enforce_noqa = settings.enabled.contains(&CheckCode::M001);
let mut noqa_directives: BTreeMap<usize, (Directive, Vec<&str>)> = BTreeMap::new(); let mut noqa_directives: BTreeMap<usize, (Directive, Vec<&str>)> = BTreeMap::new();

View file

@ -7,7 +7,7 @@ use rustpython_parser::lexer::LexResult;
use crate::autofix::fixer::Mode; use crate::autofix::fixer::Mode;
use crate::linter::{check_path, tokenize}; use crate::linter::{check_path, tokenize};
use crate::message::Message; use crate::message::Message;
use crate::settings::Settings; use crate::settings::{RawSettings, Settings};
mod ast; mod ast;
mod autofix; mod autofix;
@ -40,7 +40,7 @@ pub fn check(path: &Path, contents: &str) -> Result<Vec<Message>> {
None => debug!("Unable to find pyproject.toml; using default settings..."), None => debug!("Unable to find pyproject.toml; using default settings..."),
}; };
let settings = Settings::from_pyproject(pyproject, project_root)?; let settings = Settings::from_raw(RawSettings::from_pyproject(pyproject, project_root)?);
// Tokenize once. // Tokenize once.
let tokens: Vec<LexResult> = tokenize(contents); let tokens: Vec<LexResult> = tokenize(contents);

View file

@ -44,7 +44,7 @@ pub(crate) fn check_path(
// Run the AST-based checks. // Run the AST-based checks.
if settings if settings
.select .enabled
.iter() .iter()
.any(|check_code| matches!(check_code.lint_source(), LintSource::AST)) .any(|check_code| matches!(check_code.lint_source(), LintSource::AST))
{ {
@ -53,7 +53,7 @@ pub(crate) fn check_path(
checks.extend(check_ast(&python_ast, contents, settings, autofix, path)) checks.extend(check_ast(&python_ast, contents, settings, autofix, path))
} }
Err(parse_error) => { Err(parse_error) => {
if settings.select.contains(&CheckCode::E999) { if settings.enabled.contains(&CheckCode::E999) {
checks.push(Check::new( checks.push(Check::new(
CheckKind::SyntaxError(parse_error.error.to_string()), CheckKind::SyntaxError(parse_error.error.to_string()),
Range { Range {

View file

@ -27,6 +27,7 @@ use ::ruff::settings::CurrentSettings;
use ::ruff::settings::{FilePattern, PerFileIgnore, Settings}; use ::ruff::settings::{FilePattern, PerFileIgnore, Settings};
use ::ruff::tell_user; use ::ruff::tell_user;
use ruff::linter::autoformat_path; use ruff::linter::autoformat_path;
use ruff::settings::RawSettings;
const CARGO_PKG_NAME: &str = env!("CARGO_PKG_NAME"); const CARGO_PKG_NAME: &str = env!("CARGO_PKG_NAME");
const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION");
@ -120,7 +121,7 @@ fn check_for_updates() {
} }
} }
fn show_settings(settings: Settings) { fn show_settings(settings: RawSettings) {
println!("{:#?}", CurrentSettings::from_settings(settings)); println!("{:#?}", CurrentSettings::from_settings(settings));
} }
@ -169,7 +170,7 @@ fn run_once(
} }
.unwrap_or_else(|(path, message)| { .unwrap_or_else(|(path, message)| {
if let Some(path) = path { if let Some(path) = path {
if settings.select.contains(&CheckCode::E902) { if settings.enabled.contains(&CheckCode::E902) {
vec![Message { vec![Message {
kind: CheckKind::IOError(message), kind: CheckKind::IOError(message),
fixed: false, fixed: false,
@ -287,7 +288,7 @@ fn inner_main() -> Result<ExitCode> {
.map(|pair| PerFileIgnore::new(pair, &project_root)) .map(|pair| PerFileIgnore::new(pair, &project_root))
.collect(); .collect();
let mut settings = Settings::from_pyproject(pyproject, project_root)?; let mut settings = RawSettings::from_pyproject(pyproject, project_root)?;
if !exclude.is_empty() { if !exclude.is_empty() {
settings.exclude = exclude; settings.exclude = exclude;
} }
@ -298,17 +299,16 @@ fn inner_main() -> Result<ExitCode> {
settings.per_file_ignores = per_file_ignores; settings.per_file_ignores = per_file_ignores;
} }
if !cli.select.is_empty() { if !cli.select.is_empty() {
settings.clear(); settings.select = cli.select;
settings.select(cli.select);
} }
if !cli.extend_select.is_empty() { if !cli.extend_select.is_empty() {
settings.select(cli.extend_select); settings.extend_select = cli.extend_select;
} }
if !cli.ignore.is_empty() { if !cli.ignore.is_empty() {
settings.ignore(&cli.ignore); settings.ignore = cli.ignore;
} }
if !cli.extend_ignore.is_empty() { if !cli.extend_ignore.is_empty() {
settings.ignore(&cli.extend_ignore); settings.extend_ignore = cli.extend_ignore;
} }
if let Some(dummy_variable_rgx) = cli.dummy_variable_rgx { if let Some(dummy_variable_rgx) = cli.dummy_variable_rgx {
settings.dummy_variable_rgx = dummy_variable_rgx; settings.dummy_variable_rgx = dummy_variable_rgx;
@ -318,15 +318,18 @@ fn inner_main() -> Result<ExitCode> {
eprintln!("Error: specify --show-settings or show-files (not both)."); eprintln!("Error: specify --show-settings or show-files (not both).");
return Ok(ExitCode::FAILURE); return Ok(ExitCode::FAILURE);
} }
if cli.show_files {
show_files(&cli.files, &settings);
return Ok(ExitCode::SUCCESS);
}
if cli.show_settings { if cli.show_settings {
show_settings(settings); show_settings(settings);
return Ok(ExitCode::SUCCESS); return Ok(ExitCode::SUCCESS);
} }
let settings = Settings::from_raw(settings);
if cli.show_files {
show_files(&cli.files, &settings);
return Ok(ExitCode::SUCCESS);
}
cache::init()?; cache::init()?;
let mut printer = Printer::new(cli.format, cli.verbose); let mut printer = Printer::new(cli.format, cli.verbose);

View file

@ -37,6 +37,8 @@ pub struct Config {
#[serde(default)] #[serde(default)]
pub ignore: Vec<CheckCode>, pub ignore: Vec<CheckCode>,
#[serde(default)] #[serde(default)]
pub extend_ignore: Vec<CheckCode>,
#[serde(default)]
pub per_file_ignores: Vec<StrCheckCodePair>, pub per_file_ignores: Vec<StrCheckCodePair>,
pub dummy_variable_rgx: Option<String>, pub dummy_variable_rgx: Option<String>,
} }
@ -184,6 +186,7 @@ mod tests {
select: None, select: None,
extend_select: vec![], extend_select: vec![],
ignore: vec![], ignore: vec![],
extend_ignore: vec![],
per_file_ignores: vec![], per_file_ignores: vec![],
dummy_variable_rgx: None, dummy_variable_rgx: None,
}) })
@ -207,6 +210,7 @@ line-length = 79
select: None, select: None,
extend_select: vec![], extend_select: vec![],
ignore: vec![], ignore: vec![],
extend_ignore: vec![],
per_file_ignores: vec![], per_file_ignores: vec![],
dummy_variable_rgx: None, dummy_variable_rgx: None,
}) })
@ -230,6 +234,7 @@ exclude = ["foo.py"]
select: None, select: None,
extend_select: vec![], extend_select: vec![],
ignore: vec![], ignore: vec![],
extend_ignore: vec![],
per_file_ignores: vec![], per_file_ignores: vec![],
dummy_variable_rgx: None, dummy_variable_rgx: None,
}) })
@ -253,6 +258,7 @@ select = ["E501"]
select: Some(vec![CheckCode::E501]), select: Some(vec![CheckCode::E501]),
extend_select: vec![], extend_select: vec![],
ignore: vec![], ignore: vec![],
extend_ignore: vec![],
per_file_ignores: vec![], per_file_ignores: vec![],
dummy_variable_rgx: None, dummy_variable_rgx: None,
}) })
@ -277,6 +283,7 @@ ignore = ["E501"]
select: None, select: None,
extend_select: vec![CheckCode::M001], extend_select: vec![CheckCode::M001],
ignore: vec![CheckCode::E501], ignore: vec![CheckCode::E501],
extend_ignore: vec![],
per_file_ignores: vec![], per_file_ignores: vec![],
dummy_variable_rgx: None, dummy_variable_rgx: None,
}) })
@ -344,6 +351,7 @@ other-attribute = 1
select: None, select: None,
extend_select: vec![], extend_select: vec![],
ignore: vec![], ignore: vec![],
extend_ignore: vec![],
per_file_ignores: vec![], per_file_ignores: vec![],
dummy_variable_rgx: None, dummy_variable_rgx: None,
} }

View file

@ -51,56 +51,18 @@ impl PerFileIgnore {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Settings { pub struct RawSettings {
pub pyproject: Option<PathBuf>, pub dummy_variable_rgx: Regex,
pub project_root: Option<PathBuf>,
pub line_length: usize,
pub exclude: Vec<FilePattern>, pub exclude: Vec<FilePattern>,
pub extend_exclude: Vec<FilePattern>, pub extend_exclude: Vec<FilePattern>,
pub select: BTreeSet<CheckCode>, pub extend_ignore: Vec<CheckCode>,
pub extend_select: Vec<CheckCode>,
pub ignore: Vec<CheckCode>,
pub line_length: usize,
pub per_file_ignores: Vec<PerFileIgnore>, pub per_file_ignores: Vec<PerFileIgnore>,
pub dummy_variable_rgx: Regex, pub project_root: Option<PathBuf>,
} pub pyproject: Option<PathBuf>,
pub select: Vec<CheckCode>,
impl Settings {
pub fn for_rule(check_code: CheckCode) -> Self {
Self {
pyproject: None,
project_root: None,
line_length: 88,
exclude: vec![],
extend_exclude: vec![],
select: BTreeSet::from([check_code]),
per_file_ignores: vec![],
dummy_variable_rgx: DEFAULT_DUMMY_VARIABLE_RGX.clone(),
}
}
pub fn for_rules(check_codes: Vec<CheckCode>) -> Self {
Self {
pyproject: None,
project_root: None,
line_length: 88,
exclude: vec![],
extend_exclude: vec![],
select: BTreeSet::from_iter(check_codes),
per_file_ignores: vec![],
dummy_variable_rgx: DEFAULT_DUMMY_VARIABLE_RGX.clone(),
}
}
}
impl Hash for Settings {
fn hash<H: Hasher>(&self, state: &mut H) {
self.line_length.hash(state);
self.dummy_variable_rgx.as_str().hash(state);
for value in self.select.iter() {
value.hash(state);
}
for value in self.per_file_ignores.iter() {
value.hash(state);
}
}
} }
static DEFAULT_EXCLUDE: Lazy<Vec<FilePattern>> = Lazy::new(|| { static DEFAULT_EXCLUDE: Lazy<Vec<FilePattern>> = Lazy::new(|| {
@ -130,14 +92,18 @@ static DEFAULT_EXCLUDE: Lazy<Vec<FilePattern>> = Lazy::new(|| {
static DEFAULT_DUMMY_VARIABLE_RGX: Lazy<Regex> = static DEFAULT_DUMMY_VARIABLE_RGX: Lazy<Regex> =
Lazy::new(|| Regex::new("^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$").unwrap()); Lazy::new(|| Regex::new("^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$").unwrap());
impl Settings { impl RawSettings {
pub fn from_pyproject( pub fn from_pyproject(
pyproject: Option<PathBuf>, pyproject: Option<PathBuf>,
project_root: Option<PathBuf>, project_root: Option<PathBuf>,
) -> Result<Self> { ) -> Result<Self> {
let config = load_config(&pyproject)?; let config = load_config(&pyproject)?;
let mut settings = Settings { Ok(RawSettings {
line_length: config.line_length.unwrap_or(88), dummy_variable_rgx: match config.dummy_variable_rgx {
Some(pattern) => Regex::new(&pattern)
.map_err(|e| anyhow!("Invalid dummy-variable-rgx value: {e}"))?,
None => DEFAULT_DUMMY_VARIABLE_RGX.clone(),
},
exclude: config exclude: config
.exclude .exclude
.map(|paths| { .map(|paths| {
@ -152,42 +118,88 @@ impl Settings {
.iter() .iter()
.map(|path| FilePattern::from_user(path, &project_root)) .map(|path| FilePattern::from_user(path, &project_root))
.collect(), .collect(),
select: if let Some(select) = config.select { extend_ignore: config.extend_ignore,
BTreeSet::from_iter(select) extend_select: config.extend_select,
} else { ignore: config.ignore,
BTreeSet::from_iter(DEFAULT_CHECK_CODES) line_length: config.line_length.unwrap_or(88),
},
per_file_ignores: config per_file_ignores: config
.per_file_ignores .per_file_ignores
.into_iter() .into_iter()
.map(|pair| PerFileIgnore::new(pair, &project_root)) .map(|pair| PerFileIgnore::new(pair, &project_root))
.collect(), .collect(),
dummy_variable_rgx: match config.dummy_variable_rgx {
Some(pattern) => Regex::new(&pattern)
.map_err(|e| anyhow!("Invalid dummy-variable-rgx value: {e}"))?,
None => DEFAULT_DUMMY_VARIABLE_RGX.clone(),
},
pyproject,
project_root, project_root,
}; pyproject,
settings.select(config.extend_select); select: config
settings.ignore(&config.ignore); .select
Ok(settings) .unwrap_or_else(|| DEFAULT_CHECK_CODES.to_vec()),
})
} }
}
pub fn clear(&mut self) { #[derive(Debug)]
self.select.clear(); pub struct Settings {
pub dummy_variable_rgx: Regex,
pub enabled: BTreeSet<CheckCode>,
pub exclude: Vec<FilePattern>,
pub extend_exclude: Vec<FilePattern>,
pub line_length: usize,
pub per_file_ignores: Vec<PerFileIgnore>,
}
impl Settings {
pub fn from_raw(settings: RawSettings) -> Self {
// Materialize the set of enabled CheckCodes.
let mut enabled: BTreeSet<CheckCode> = BTreeSet::new();
enabled.extend(settings.select);
enabled.extend(settings.extend_select);
for code in &settings.ignore {
enabled.remove(code);
} }
for code in &settings.extend_ignore {
pub fn select(&mut self, codes: Vec<CheckCode>) { enabled.remove(code);
for code in codes { }
self.select.insert(code); Self {
dummy_variable_rgx: settings.dummy_variable_rgx,
enabled,
exclude: settings.exclude,
extend_exclude: settings.extend_exclude,
line_length: settings.line_length,
per_file_ignores: settings.per_file_ignores,
} }
} }
pub fn ignore(&mut self, codes: &[CheckCode]) { pub fn for_rule(check_code: CheckCode) -> Self {
for code in codes { Self {
self.select.remove(code); dummy_variable_rgx: DEFAULT_DUMMY_VARIABLE_RGX.clone(),
enabled: BTreeSet::from([check_code]),
exclude: vec![],
extend_exclude: vec![],
line_length: 88,
per_file_ignores: vec![],
}
}
pub fn for_rules(check_codes: Vec<CheckCode>) -> Self {
Self {
dummy_variable_rgx: DEFAULT_DUMMY_VARIABLE_RGX.clone(),
enabled: BTreeSet::from_iter(check_codes),
exclude: vec![],
extend_exclude: vec![],
line_length: 88,
per_file_ignores: vec![],
}
}
}
impl Hash for Settings {
fn hash<H: Hasher>(&self, state: &mut H) {
self.line_length.hash(state);
self.dummy_variable_rgx.as_str().hash(state);
for value in self.enabled.iter() {
value.hash(state);
}
for value in self.per_file_ignores.iter() {
value.hash(state);
} }
} }
} }
@ -218,22 +230,23 @@ impl Exclusion {
/// Struct to render user-facing Settings. /// Struct to render user-facing Settings.
#[derive(Debug)] #[derive(Debug)]
pub struct CurrentSettings { pub struct CurrentSettings {
pub pyproject: Option<PathBuf>, pub dummy_variable_rgx: Regex,
pub project_root: Option<PathBuf>,
pub line_length: usize,
pub exclude: Vec<Exclusion>, pub exclude: Vec<Exclusion>,
pub extend_exclude: Vec<Exclusion>, pub extend_exclude: Vec<Exclusion>,
pub select: BTreeSet<CheckCode>, pub extend_ignore: Vec<CheckCode>,
pub extend_select: Vec<CheckCode>,
pub ignore: Vec<CheckCode>,
pub line_length: usize,
pub per_file_ignores: Vec<PerFileIgnore>, pub per_file_ignores: Vec<PerFileIgnore>,
pub dummy_variable_rgx: Regex, pub project_root: Option<PathBuf>,
pub pyproject: Option<PathBuf>,
pub select: Vec<CheckCode>,
} }
impl CurrentSettings { impl CurrentSettings {
pub fn from_settings(settings: Settings) -> Self { pub fn from_settings(settings: RawSettings) -> Self {
Self { Self {
pyproject: settings.pyproject, dummy_variable_rgx: settings.dummy_variable_rgx,
project_root: settings.project_root,
line_length: settings.line_length,
exclude: settings exclude: settings
.exclude .exclude
.into_iter() .into_iter()
@ -244,9 +257,14 @@ impl CurrentSettings {
.into_iter() .into_iter()
.map(Exclusion::from_file_pattern) .map(Exclusion::from_file_pattern)
.collect(), .collect(),
select: settings.select, extend_ignore: settings.extend_ignore,
extend_select: settings.extend_select,
ignore: settings.ignore,
line_length: settings.line_length,
per_file_ignores: settings.per_file_ignores, per_file_ignores: settings.per_file_ignores,
dummy_variable_rgx: settings.dummy_variable_rgx, project_root: settings.project_root,
pyproject: settings.pyproject,
select: settings.select,
} }
} }
} }