From 9fef1628002a7369d2316be6faab3b2831ada16d Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Mon, 19 Aug 2024 18:14:28 +0100 Subject: [PATCH] Pass a boolean `is_relative` argument to `isort::categorize`, rather than a u32 `level` argument --- .../rules/typing_only_runtime_import.rs | 2 +- .../ruff_linter/src/rules/isort/categorize.rs | 16 +++++++------- .../src/rules/pyflakes/rules/unused_import.rs | 21 ++++++------------- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/crates/ruff_linter/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs b/crates/ruff_linter/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs index 3470430384f57..32bdb7046f7a3 100644 --- a/crates/ruff_linter/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs +++ b/crates/ruff_linter/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs @@ -300,7 +300,7 @@ pub(crate) fn typing_only_runtime_import( // Categorize the import, using coarse-grained categorization. let import_type = match categorize( &qualified_name.to_string(), - 0, + qualified_name.is_unresolved_import(), &checker.settings.src, checker.package(), checker.settings.isort.detect_same_package, diff --git a/crates/ruff_linter/src/rules/isort/categorize.rs b/crates/ruff_linter/src/rules/isort/categorize.rs index 3c0eef1deaa08..4c8212261115a 100644 --- a/crates/ruff_linter/src/rules/isort/categorize.rs +++ b/crates/ruff_linter/src/rules/isort/categorize.rs @@ -91,7 +91,7 @@ enum Reason<'a> { #[allow(clippy::too_many_arguments)] pub(crate) fn categorize<'a>( module_name: &str, - level: u32, + is_relative: bool, src: &[PathBuf], package: Option<&Path>, detect_same_package: bool, @@ -103,14 +103,14 @@ pub(crate) fn categorize<'a>( ) -> &'a ImportSection { let module_base = module_name.split('.').next().unwrap(); let (mut import_type, mut reason) = { - if level == 0 && module_base == "__future__" { + if !is_relative && module_base == "__future__" { (&ImportSection::Known(ImportType::Future), Reason::Future) } else if no_sections { ( &ImportSection::Known(ImportType::FirstParty), Reason::NoSections, ) - } else if level > 0 { + } else if is_relative { ( &ImportSection::Known(ImportType::LocalFolder), Reason::NonZeroLevel, @@ -132,7 +132,7 @@ pub(crate) fn categorize<'a>( &ImportSection::Known(ImportType::FirstParty), Reason::SourceMatch(src), ) - } else if level == 0 && module_name == "__main__" { + } else if !is_relative && module_name == "__main__" { ( &ImportSection::Known(ImportType::FirstParty), Reason::KnownFirstParty, @@ -190,7 +190,7 @@ pub(crate) fn categorize_imports<'a>( for (alias, comments) in block.import { let import_type = categorize( &alias.module_name(), - 0, + false, src, package, detect_same_package, @@ -210,7 +210,7 @@ pub(crate) fn categorize_imports<'a>( for (import_from, aliases) in block.import_from { let classification = categorize( &import_from.module_name(), - import_from.level, + import_from.level > 0, src, package, detect_same_package, @@ -230,7 +230,7 @@ pub(crate) fn categorize_imports<'a>( for ((import_from, alias), aliases) in block.import_from_as { let classification = categorize( &import_from.module_name(), - import_from.level, + import_from.level > 0, src, package, detect_same_package, @@ -250,7 +250,7 @@ pub(crate) fn categorize_imports<'a>( for (import_from, comments) in block.import_from_star { let classification = categorize( &import_from.module_name(), - import_from.level, + import_from.level > 0, src, package, detect_same_package, diff --git a/crates/ruff_linter/src/rules/pyflakes/rules/unused_import.rs b/crates/ruff_linter/src/rules/pyflakes/rules/unused_import.rs index ef134f2c42dfd..57ce105454168 100644 --- a/crates/ruff_linter/src/rules/pyflakes/rules/unused_import.rs +++ b/crates/ruff_linter/src/rules/pyflakes/rules/unused_import.rs @@ -6,8 +6,7 @@ use std::collections::BTreeMap; use ruff_diagnostics::{Applicability, Diagnostic, Fix, FixAvailability, Violation}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast as ast; -use ruff_python_ast::{Stmt, StmtImportFrom}; +use ruff_python_ast::{self as ast, Stmt}; use ruff_python_semantic::{ AnyImport, BindingKind, Exceptions, Imported, NodeId, Scope, SemanticModel, SubmoduleImport, }; @@ -218,10 +217,11 @@ enum UnusedImportContext { Other, } -fn is_first_party(qualified_name: &str, level: u32, checker: &Checker) -> bool { +fn is_first_party(import: &AnyImport, checker: &Checker) -> bool { + let qualified_name = import.qualified_name(); let category = isort::categorize( - qualified_name, - level, + &qualified_name.to_string(), + qualified_name.is_unresolved_import(), &checker.settings.src, checker.package(), checker.settings.isort.detect_same_package, @@ -343,13 +343,6 @@ pub(crate) fn unused_import(checker: &Checker, scope: &Scope, diagnostics: &mut let in_except_handler = exceptions.intersects(Exceptions::MODULE_NOT_FOUND_ERROR | Exceptions::IMPORT_ERROR); let multiple = bindings.len() > 1; - let level = match checker.semantic().statement(import_statement) { - Stmt::Import(_) => 0, - Stmt::ImportFrom(StmtImportFrom { level, .. }) => *level, - _ => { - continue; - } - }; // pair each binding with context; divide them by how we want to fix them let (to_reexport, to_remove): (Vec<_>, Vec<_>) = bindings @@ -357,9 +350,7 @@ pub(crate) fn unused_import(checker: &Checker, scope: &Scope, diagnostics: &mut .map(|binding| { let context = if in_except_handler { UnusedImportContext::ExceptHandler - } else if in_init - && is_first_party(&binding.import.qualified_name().to_string(), level, checker) - { + } else if in_init && is_first_party(&binding.import, checker) { UnusedImportContext::DunderInitFirstParty { dunder_all_count: DunderAllCount::from(dunder_all_exprs.len()), submodule_import: binding.import.is_submodule_import(),