From b1956a999ef5edb71a7f1512d2ac8d53c5b3bcb4 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Fri, 29 Mar 2024 21:42:57 -0400 Subject: [PATCH] Always place non-relative imports after relative imports --- .../isort/separate_local_folder_imports.py | 2 ++ crates/ruff_linter/src/rules/isort/mod.rs | 25 +++++++++++++++++ ...sest_separate_local_folder_imports.py.snap | 27 +++++++++++++++++++ ...lder_separate_local_folder_imports.py.snap | 9 ++++--- ...sts__separate_local_folder_imports.py.snap | 26 ++++++++++-------- crates/ruff_linter/src/rules/isort/sorting.rs | 18 ++++++++----- 6 files changed, 86 insertions(+), 21 deletions(-) create mode 100644 crates/ruff_linter/src/rules/isort/snapshots/ruff_linter__rules__isort__tests__known_local_folder_closest_separate_local_folder_imports.py.snap diff --git a/crates/ruff_linter/resources/test/fixtures/isort/separate_local_folder_imports.py b/crates/ruff_linter/resources/test/fixtures/isort/separate_local_folder_imports.py index beed464c0ce09..2387c675e94db 100644 --- a/crates/ruff_linter/resources/test/fixtures/isort/separate_local_folder_imports.py +++ b/crates/ruff_linter/resources/test/fixtures/isort/separate_local_folder_imports.py @@ -3,3 +3,5 @@ import leading_prefix import os from . import leading_prefix +from .. import trailing_prefix +from ruff import check diff --git a/crates/ruff_linter/src/rules/isort/mod.rs b/crates/ruff_linter/src/rules/isort/mod.rs index 59bf5b4fa0a6d..d07017600b864 100644 --- a/crates/ruff_linter/src/rules/isort/mod.rs +++ b/crates/ruff_linter/src/rules/isort/mod.rs @@ -471,6 +471,31 @@ mod tests { Ok(()) } + #[test_case(Path::new("separate_local_folder_imports.py"))] + fn known_local_folder_closest(path: &Path) -> Result<()> { + let snapshot = format!("known_local_folder_closest_{}", path.to_string_lossy()); + let diagnostics = test_path( + Path::new("isort").join(path).as_path(), + &LinterSettings { + isort: super::settings::Settings { + known_modules: KnownModules::new( + vec![], + vec![], + vec![pattern("ruff")], + vec![], + FxHashMap::default(), + ), + relative_imports_order: RelativeImportsOrder::ClosestToFurthest, + ..super::settings::Settings::default() + }, + src: vec![test_resource_path("fixtures/isort")], + ..LinterSettings::for_rule(Rule::UnsortedImports) + }, + )?; + assert_messages!(snapshot, diagnostics); + Ok(()) + } + #[test_case(Path::new("case_sensitive.py"))] fn case_sensitive(path: &Path) -> Result<()> { let snapshot = format!("case_sensitive_{}", path.to_string_lossy()); diff --git a/crates/ruff_linter/src/rules/isort/snapshots/ruff_linter__rules__isort__tests__known_local_folder_closest_separate_local_folder_imports.py.snap b/crates/ruff_linter/src/rules/isort/snapshots/ruff_linter__rules__isort__tests__known_local_folder_closest_separate_local_folder_imports.py.snap new file mode 100644 index 0000000000000..8eb419a4a4739 --- /dev/null +++ b/crates/ruff_linter/src/rules/isort/snapshots/ruff_linter__rules__isort__tests__known_local_folder_closest_separate_local_folder_imports.py.snap @@ -0,0 +1,27 @@ +--- +source: crates/ruff_linter/src/rules/isort/mod.rs +--- +separate_local_folder_imports.py:1:1: I001 [*] Import block is un-sorted or un-formatted + | +1 | / import sys +2 | | import ruff +3 | | import leading_prefix +4 | | import os +5 | | from . import leading_prefix +6 | | from .. import trailing_prefix +7 | | from ruff import check + | + = help: Organize imports + +ℹ Safe fix + 1 |+import os +1 2 | import sys + 3 |+ + 4 |+import leading_prefix + 5 |+ +2 6 | import ruff +3 |-import leading_prefix +4 |-import os +5 7 | from . import leading_prefix +6 8 | from .. import trailing_prefix +7 9 | from ruff import check diff --git a/crates/ruff_linter/src/rules/isort/snapshots/ruff_linter__rules__isort__tests__known_local_folder_separate_local_folder_imports.py.snap b/crates/ruff_linter/src/rules/isort/snapshots/ruff_linter__rules__isort__tests__known_local_folder_separate_local_folder_imports.py.snap index d8a690be6bcc6..21ed77408c35c 100644 --- a/crates/ruff_linter/src/rules/isort/snapshots/ruff_linter__rules__isort__tests__known_local_folder_separate_local_folder_imports.py.snap +++ b/crates/ruff_linter/src/rules/isort/snapshots/ruff_linter__rules__isort__tests__known_local_folder_separate_local_folder_imports.py.snap @@ -8,6 +8,8 @@ separate_local_folder_imports.py:1:1: I001 [*] Import block is un-sorted or un-f 3 | | import leading_prefix 4 | | import os 5 | | from . import leading_prefix +6 | | from .. import trailing_prefix +7 | | from ruff import check | = help: Organize imports @@ -20,6 +22,7 @@ separate_local_folder_imports.py:1:1: I001 [*] Import block is un-sorted or un-f 2 6 | import ruff 3 |-import leading_prefix 4 |-import os -5 7 | from . import leading_prefix - - + 7 |+from .. import trailing_prefix +5 8 | from . import leading_prefix +6 |-from .. import trailing_prefix +7 9 | from ruff import check diff --git a/crates/ruff_linter/src/rules/isort/snapshots/ruff_linter__rules__isort__tests__separate_local_folder_imports.py.snap b/crates/ruff_linter/src/rules/isort/snapshots/ruff_linter__rules__isort__tests__separate_local_folder_imports.py.snap index 23d796602ccec..88d2f3a1bcfa0 100644 --- a/crates/ruff_linter/src/rules/isort/snapshots/ruff_linter__rules__isort__tests__separate_local_folder_imports.py.snap +++ b/crates/ruff_linter/src/rules/isort/snapshots/ruff_linter__rules__isort__tests__separate_local_folder_imports.py.snap @@ -8,18 +8,22 @@ separate_local_folder_imports.py:1:1: I001 [*] Import block is un-sorted or un-f 3 | | import leading_prefix 4 | | import os 5 | | from . import leading_prefix +6 | | from .. import trailing_prefix +7 | | from ruff import check | = help: Organize imports ℹ Safe fix - 1 |+import os -1 2 | import sys - 3 |+ -2 4 | import ruff - 5 |+ -3 6 | import leading_prefix -4 |-import os - 7 |+ -5 8 | from . import leading_prefix - - + 1 |+import os +1 2 | import sys + 3 |+ +2 4 | import ruff + 5 |+from ruff import check + 6 |+ +3 7 | import leading_prefix +4 |-import os + 8 |+ + 9 |+from .. import trailing_prefix +5 10 | from . import leading_prefix +6 |-from .. import trailing_prefix +7 |-from ruff import check diff --git a/crates/ruff_linter/src/rules/isort/sorting.rs b/crates/ruff_linter/src/rules/isort/sorting.rs index 68d899bc61a99..479b5428d6dd8 100644 --- a/crates/ruff_linter/src/rules/isort/sorting.rs +++ b/crates/ruff_linter/src/rules/isort/sorting.rs @@ -69,6 +69,7 @@ impl<'a> From for NatOrdStr<'a> { pub(crate) enum Distance { Nearest(u32), Furthest(Reverse), + None, } #[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq)] @@ -101,17 +102,20 @@ impl<'a> ModuleKey<'a> { style: ImportStyle, settings: &Settings, ) -> Self { - let level = level.unwrap_or_default(); - let force_to_top = !name.is_some_and(|name| settings.force_to_top.contains(name)); // `false` < `true` so we get forced to top first let maybe_length = (settings.length_sort || (settings.length_sort_straight && style == ImportStyle::Straight)) - .then_some(name.map(str::width).unwrap_or_default() + level as usize); - - let distance = match settings.relative_imports_order { - RelativeImportsOrder::ClosestToFurthest => Distance::Nearest(level), - RelativeImportsOrder::FurthestToClosest => Distance::Furthest(Reverse(level)), + .then_some( + name.map(str::width).unwrap_or_default() + level.unwrap_or_default() as usize, + ); + + let distance = match level { + None | Some(0) => Distance::None, + Some(level) => match settings.relative_imports_order { + RelativeImportsOrder::ClosestToFurthest => Distance::Nearest(level), + RelativeImportsOrder::FurthestToClosest => Distance::Furthest(Reverse(level)), + }, }; let maybe_lowercase_name = name.and_then(|name| {