diff --git a/resources/test/fixtures/isort/pyproject.toml b/resources/test/fixtures/isort/pyproject.toml new file mode 100644 index 0000000000..97fda9d62e --- /dev/null +++ b/resources/test/fixtures/isort/pyproject.toml @@ -0,0 +1,2 @@ +[tool.ruff] +line-length = 88 diff --git a/resources/test/fixtures/isort/separate_local_folder_imports.py b/resources/test/fixtures/isort/separate_local_folder_imports.py new file mode 100644 index 0000000000..6eb9966811 --- /dev/null +++ b/resources/test/fixtures/isort/separate_local_folder_imports.py @@ -0,0 +1,4 @@ +import sys +import leading_prefix +import os +from . import leading_prefix diff --git a/src/isort/categorize.rs b/src/isort/categorize.rs index 11ffd4f101..ed71054c0a 100644 --- a/src/isort/categorize.rs +++ b/src/isort/categorize.rs @@ -12,16 +12,20 @@ pub enum ImportType { StandardLibrary, ThirdParty, FirstParty, + LocalFolder, } pub fn categorize( module_base: &str, + level: &Option, src: &[PathBuf], known_first_party: &BTreeSet, known_third_party: &BTreeSet, extra_standard_library: &BTreeSet, ) -> ImportType { - if known_first_party.contains(module_base) { + if level.map(|level| level > 0).unwrap_or(false) { + ImportType::LocalFolder + } else if known_first_party.contains(module_base) { ImportType::FirstParty } else if known_third_party.contains(module_base) { ImportType::ThirdParty @@ -31,12 +35,10 @@ pub fn categorize( import_type.clone() } else if KNOWN_STANDARD_LIBRARY.contains(module_base) { ImportType::StandardLibrary + } else if find_local(src, module_base) { + ImportType::FirstParty } else { - if find_local(src, module_base) { - ImportType::FirstParty - } else { - ImportType::ThirdParty - } + ImportType::ThirdParty } } diff --git a/src/isort/mod.rs b/src/isort/mod.rs index efeb733a7f..e637bf6751 100644 --- a/src/isort/mod.rs +++ b/src/isort/mod.rs @@ -62,6 +62,7 @@ fn categorize_imports<'a>( for alias in block.import { let import_type = categorize( &alias.module_base(), + &None, src, known_first_party, known_third_party, @@ -77,6 +78,7 @@ fn categorize_imports<'a>( for (import_from, aliases) in block.import_from { let classification = categorize( &import_from.module_base(), + import_from.level, src, known_first_party, known_third_party, @@ -119,6 +121,7 @@ pub fn sort_imports( ImportType::StandardLibrary, ImportType::ThirdParty, ImportType::FirstParty, + ImportType::LocalFolder, ] { if let Some(import_block) = block_by_type.get(&import_type) { // Add a blank line between every section. @@ -218,6 +221,7 @@ mod tests { #[test_case(Path::new("reorder_within_section.py"))] #[test_case(Path::new("separate_first_party_imports.py"))] #[test_case(Path::new("separate_future_imports.py"))] + #[test_case(Path::new("separate_local_folder_imports.py"))] #[test_case(Path::new("separate_third_party_imports.py"))] #[test_case(Path::new("skip.py"))] #[test_case(Path::new("trailing_suffix.py"))] diff --git a/src/isort/snapshots/ruff__isort__tests__separate_local_folder_imports.py.snap b/src/isort/snapshots/ruff__isort__tests__separate_local_folder_imports.py.snap new file mode 100644 index 0000000000..9653981217 --- /dev/null +++ b/src/isort/snapshots/ruff__isort__tests__separate_local_folder_imports.py.snap @@ -0,0 +1,22 @@ +--- +source: src/isort/mod.rs +expression: checks +--- +- kind: UnsortedImports + location: + row: 1 + column: 0 + end_location: + row: 5 + column: 0 + fix: + patch: + content: "import os\nimport sys\n\nimport leading_prefix\n\nfrom . import leading_prefix\n" + location: + row: 1 + column: 0 + end_location: + row: 5 + column: 0 + applied: false +