diff --git a/crates/ruff_linter/resources/test/fixtures/isort/force_sort_within_sections_lines_between.py b/crates/ruff_linter/resources/test/fixtures/isort/force_sort_within_sections_lines_between.py new file mode 100644 index 0000000000000..5459d78bfd12f --- /dev/null +++ b/crates/ruff_linter/resources/test/fixtures/isort/force_sort_within_sections_lines_between.py @@ -0,0 +1,4 @@ +from a import x +import b +from c import y +import d diff --git a/crates/ruff_linter/src/rules/isort/mod.rs b/crates/ruff_linter/src/rules/isort/mod.rs index 0cb8655c13cd6..d77a818aa8fff 100644 --- a/crates/ruff_linter/src/rules/isort/mod.rs +++ b/crates/ruff_linter/src/rules/isort/mod.rs @@ -200,6 +200,7 @@ fn format_import_block( // Add a blank lines between direct and from imports. if settings.from_first && lines_between_types > 0 + && !settings.force_sort_within_sections && line_insertion == Some(LineInsertion::Necessary) { for _ in 0..lines_between_types { @@ -225,6 +226,7 @@ fn format_import_block( // Add a blank lines between direct and from imports. if !settings.from_first && lines_between_types > 0 + && !settings.force_sort_within_sections && line_insertion == Some(LineInsertion::Necessary) { for _ in 0..lines_between_types { @@ -722,6 +724,26 @@ mod tests { Ok(()) } + #[test_case(Path::new("force_sort_within_sections_lines_between.py"))] + fn force_sort_within_sections_lines_between(path: &Path) -> Result<()> { + let snapshot = format!("force_sort_within_sections_{}", path.to_string_lossy()); + let mut diagnostics = test_path( + Path::new("isort").join(path).as_path(), + &LinterSettings { + isort: super::settings::Settings { + force_sort_within_sections: true, + lines_between_types: 2, + ..super::settings::Settings::default() + }, + src: vec![test_resource_path("fixtures/isort")], + ..LinterSettings::for_rule(Rule::UnsortedImports) + }, + )?; + diagnostics.sort_by_key(Ranged::start); + assert_messages!(snapshot, diagnostics); + Ok(()) + } + #[test_case(Path::new("comment.py"))] #[test_case(Path::new("comments_and_newlines.py"))] #[test_case(Path::new("docstring.py"))] diff --git a/crates/ruff_linter/src/rules/isort/snapshots/ruff_linter__rules__isort__tests__force_sort_within_sections_force_sort_within_sections_lines_between.py.snap b/crates/ruff_linter/src/rules/isort/snapshots/ruff_linter__rules__isort__tests__force_sort_within_sections_force_sort_within_sections_lines_between.py.snap new file mode 100644 index 0000000000000..ed369f0fd61f0 --- /dev/null +++ b/crates/ruff_linter/src/rules/isort/snapshots/ruff_linter__rules__isort__tests__force_sort_within_sections_force_sort_within_sections_lines_between.py.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff_linter/src/rules/isort/mod.rs +--- + diff --git a/crates/ruff_workspace/src/options.rs b/crates/ruff_workspace/src/options.rs index 442b8d7d2e16d..1d8386d80ab1d 100644 --- a/crates/ruff_workspace/src/options.rs +++ b/crates/ruff_workspace/src/options.rs @@ -2109,6 +2109,13 @@ impl IsortOptions { warn_user_once!("`sections` is ignored when `no-sections` is set to `true`"); } + // Verify that if `force_sort_within_sections` is `True`, then `lines_between_types` is set to `0`. + let force_sort_within_sections = self.force_sort_within_sections.unwrap_or_default(); + let lines_between_types = self.lines_between_types.unwrap_or_default(); + if force_sort_within_sections && lines_between_types != 0 { + warn_user_once!("`lines-between-types` is ignored when `force-sort-within-sections` is set to `true`"); + } + // Extract any configuration options that deal with user-defined sections. let mut section_order: Vec<_> = self .section_order @@ -2240,7 +2247,7 @@ impl IsortOptions { required_imports: BTreeSet::from_iter(self.required_imports.unwrap_or_default()), combine_as_imports: self.combine_as_imports.unwrap_or(false), force_single_line: self.force_single_line.unwrap_or(false), - force_sort_within_sections: self.force_sort_within_sections.unwrap_or(false), + force_sort_within_sections, case_sensitive: self.case_sensitive.unwrap_or(false), force_wrap_aliases: self.force_wrap_aliases.unwrap_or(false), detect_same_package: self.detect_same_package.unwrap_or(true), @@ -2263,7 +2270,7 @@ impl IsortOptions { variables: BTreeSet::from_iter(self.variables.unwrap_or_default()), no_lines_before: BTreeSet::from_iter(no_lines_before), lines_after_imports: self.lines_after_imports.unwrap_or(-1), - lines_between_types: self.lines_between_types.unwrap_or_default(), + lines_between_types, forced_separate: Vec::from_iter(self.forced_separate.unwrap_or_default()), section_order, no_sections,