Skip to content

Commit d056a9f

Browse files
Alex-ley-scrubntBreamyreese
authored
[isort] support for configurable import section heading comments (#23151)
<!-- Thank you for contributing to Ruff/ty! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? (Please prefix with `[ty]` for ty pull requests.) - Does this pull request include references to any relevant issues? --> ## Summary fixes #6371 - `settings.rs` - Added import_headings: FxHashMap<ImportSection, String> field to Settings struct with default and display support - `options.rs` - Added import_heading configuration option with #[option] metadata, documentation, and TOML table syntax. Added validation for unknown sections and mapping to Settings - `mod.rs` - Core logic in format_import_block: - Collects all configured heading values as "# {heading}" strings - Strips matching heading comments from ALL imports in each section (handles reordering) - Inserts heading comments above each section after blank line logic - `organize_imports.rs` - Extended fix range backward to include heading comment lines above the first import, preventing duplication on fix application ## Test Plan Test Coverage (9 new tests, 156 total passing) ``` cargo test -p ruff_linter -- isort::tests cargo test -p ruff_linter -- isort::tests::import_heading ``` | Test | Scenario | |-------------------------------------------|------------------------------------------------------| | import_heading.py | Basic unsorted imports get headings added | | import_heading_already_present.py | Existing headings stripped and re-added correctly | | import_heading_already_correct.py | Properly sorted+headed imports produce NO diagnostic | | import_heading_unsorted.py | Completely unsorted imports get sorted with headings | | import_heading_with_no_lines_before.py | Interaction with no_lines_before setting | | import_heading_partial.py | Headings configured for only some sections | | import_heading_wrong_heading.py | Non-matching comments preserved as regular comments | | import_heading_single_section.py | Only one section present gets its heading | | import_heading_force_sort_within_sections.py | Works with force_sort_within_sections | --------- Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com> Co-authored-by: Amethyst Reese <amethyst@n7.gg>
1 parent e22fa4f commit d056a9f

36 files changed

Lines changed: 684 additions & 4 deletions

File tree

crates/ruff/tests/cli/snapshots/cli__lint__requires_python_extend_from_shared_config.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ linter.isort.classes = []
208208
linter.isort.constants = []
209209
linter.isort.variables = []
210210
linter.isort.no_lines_before = []
211+
linter.isort.import_headings = {}
211212
linter.isort.lines_after_imports = -1
212213
linter.isort.lines_between_types = 0
213214
linter.isort.forced_separate = []

crates/ruff/tests/cli/snapshots/cli__lint__requires_python_no_tool.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ linter.isort.classes = []
210210
linter.isort.constants = []
211211
linter.isort.variables = []
212212
linter.isort.no_lines_before = []
213+
linter.isort.import_headings = {}
213214
linter.isort.lines_after_imports = -1
214215
linter.isort.lines_between_types = 0
215216
linter.isort.forced_separate = []

crates/ruff/tests/cli/snapshots/cli__lint__requires_python_no_tool_preview_enabled.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ linter.isort.classes = []
212212
linter.isort.constants = []
213213
linter.isort.variables = []
214214
linter.isort.no_lines_before = []
215+
linter.isort.import_headings = {}
215216
linter.isort.lines_after_imports = -1
216217
linter.isort.lines_between_types = 0
217218
linter.isort.forced_separate = []

crates/ruff/tests/cli/snapshots/cli__lint__requires_python_no_tool_target_version_override.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ linter.isort.classes = []
212212
linter.isort.constants = []
213213
linter.isort.variables = []
214214
linter.isort.no_lines_before = []
215+
linter.isort.import_headings = {}
215216
linter.isort.lines_after_imports = -1
216217
linter.isort.lines_between_types = 0
217218
linter.isort.forced_separate = []

crates/ruff/tests/cli/snapshots/cli__lint__requires_python_pyproject_toml_above.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ linter.isort.classes = []
209209
linter.isort.constants = []
210210
linter.isort.variables = []
211211
linter.isort.no_lines_before = []
212+
linter.isort.import_headings = {}
212213
linter.isort.lines_after_imports = -1
213214
linter.isort.lines_between_types = 0
214215
linter.isort.forced_separate = []

crates/ruff/tests/cli/snapshots/cli__lint__requires_python_pyproject_toml_above_with_tool.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ linter.isort.classes = []
210210
linter.isort.constants = []
211211
linter.isort.variables = []
212212
linter.isort.no_lines_before = []
213+
linter.isort.import_headings = {}
213214
linter.isort.lines_after_imports = -1
214215
linter.isort.lines_between_types = 0
215216
linter.isort.forced_separate = []

crates/ruff/tests/cli/snapshots/cli__lint__requires_python_ruff_toml_above-2.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ linter.isort.classes = []
208208
linter.isort.constants = []
209209
linter.isort.variables = []
210210
linter.isort.no_lines_before = []
211+
linter.isort.import_headings = {}
211212
linter.isort.lines_after_imports = -1
212213
linter.isort.lines_between_types = 0
213214
linter.isort.forced_separate = []

crates/ruff/tests/cli/snapshots/cli__lint__requires_python_ruff_toml_above.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ linter.isort.classes = []
208208
linter.isort.constants = []
209209
linter.isort.variables = []
210210
linter.isort.no_lines_before = []
211+
linter.isort.import_headings = {}
211212
linter.isort.lines_after_imports = -1
212213
linter.isort.lines_between_types = 0
213214
linter.isort.forced_separate = []

crates/ruff/tests/cli/snapshots/cli__lint__requires_python_ruff_toml_no_target_fallback.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ linter.isort.classes = []
208208
linter.isort.constants = []
209209
linter.isort.variables = []
210210
linter.isort.no_lines_before = []
211+
linter.isort.import_headings = {}
211212
linter.isort.lines_after_imports = -1
212213
linter.isort.lines_between_types = 0
213214
linter.isort.forced_separate = []

crates/ruff/tests/snapshots/show_settings__display_default_settings.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ linter.isort.classes = []
321321
linter.isort.constants = []
322322
linter.isort.variables = []
323323
linter.isort.no_lines_before = []
324+
linter.isort.import_headings = {}
324325
linter.isort.lines_after_imports = -1
325326
linter.isort.lines_between_types = 0
326327
linter.isort.forced_separate = []

0 commit comments

Comments
 (0)