mirror of
https://github.com/astral-sh/ruff
synced 2026-01-22 05:51:03 -05:00
feat: Add isort option lines-after-imports (#2440)
Fixes https://github.com/charliermarsh/ruff/issues/2243 Adds support for the isort option [lines_after_imports](https://pycqa.github.io/isort/docs/configuration/options.html#lines-after-imports) to insert blank lines between imports and the follow up code.
This commit is contained in:
@@ -3,11 +3,12 @@
|
||||
use std::collections::BTreeSet;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use itertools::Either::{Left, Right};
|
||||
|
||||
use annotate::annotate_imports;
|
||||
use categorize::categorize_imports;
|
||||
pub use categorize::{categorize, ImportType};
|
||||
use comments::Comment;
|
||||
use itertools::Either::{Left, Right};
|
||||
use normalize::normalize_imports;
|
||||
use order::order_imports;
|
||||
use settings::RelativeImportsOrder;
|
||||
@@ -127,6 +128,7 @@ pub fn format_imports(
|
||||
constants: &BTreeSet<String>,
|
||||
variables: &BTreeSet<String>,
|
||||
no_lines_before: &BTreeSet<ImportType>,
|
||||
lines_after_imports: isize,
|
||||
) -> String {
|
||||
let trailer = &block.trailer;
|
||||
let block = annotate_imports(&block.imports, comments, locator, split_on_trailing_comma);
|
||||
@@ -214,11 +216,23 @@ pub fn format_imports(
|
||||
match trailer {
|
||||
None => {}
|
||||
Some(Trailer::Sibling) => {
|
||||
output.push_str(stylist.line_ending());
|
||||
if lines_after_imports >= 0 {
|
||||
for _ in 0..lines_after_imports {
|
||||
output.push_str(stylist.line_ending());
|
||||
}
|
||||
} else {
|
||||
output.push_str(stylist.line_ending());
|
||||
}
|
||||
}
|
||||
Some(Trailer::FunctionDef | Trailer::ClassDef) => {
|
||||
output.push_str(stylist.line_ending());
|
||||
output.push_str(stylist.line_ending());
|
||||
if lines_after_imports >= 0 {
|
||||
for _ in 0..lines_after_imports {
|
||||
output.push_str(stylist.line_ending());
|
||||
}
|
||||
} else {
|
||||
output.push_str(stylist.line_ending());
|
||||
output.push_str(stylist.line_ending());
|
||||
}
|
||||
}
|
||||
}
|
||||
output
|
||||
@@ -232,13 +246,14 @@ mod tests {
|
||||
use anyhow::Result;
|
||||
use test_case::test_case;
|
||||
|
||||
use super::categorize::ImportType;
|
||||
use super::settings::RelativeImportsOrder;
|
||||
use crate::assert_yaml_snapshot;
|
||||
use crate::registry::Rule;
|
||||
use crate::settings::Settings;
|
||||
use crate::test::{test_path, test_resource_path};
|
||||
|
||||
use super::categorize::ImportType;
|
||||
use super::settings::RelativeImportsOrder;
|
||||
|
||||
#[test_case(Path::new("add_newline_before_comments.py"))]
|
||||
#[test_case(Path::new("combine_as_imports.py"))]
|
||||
#[test_case(Path::new("combine_import_from.py"))]
|
||||
@@ -641,4 +656,25 @@ mod tests {
|
||||
assert_yaml_snapshot!(snapshot, diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case(Path::new("lines_after_imports_nothing_after.py"))]
|
||||
#[test_case(Path::new("lines_after_imports_func_after.py"))]
|
||||
#[test_case(Path::new("lines_after_imports_class_after.py"))]
|
||||
fn lines_after_imports(path: &Path) -> Result<()> {
|
||||
let snapshot = format!("lines_after_imports_{}", path.to_string_lossy());
|
||||
let mut diagnostics = test_path(
|
||||
Path::new("isort").join(path).as_path(),
|
||||
&Settings {
|
||||
isort: super::settings::Settings {
|
||||
lines_after_imports: 3,
|
||||
..super::settings::Settings::default()
|
||||
},
|
||||
src: vec![test_resource_path("fixtures/isort")],
|
||||
..Settings::for_rule(Rule::UnsortedImports)
|
||||
},
|
||||
)?;
|
||||
diagnostics.sort_by_key(|diagnostic| diagnostic.location);
|
||||
assert_yaml_snapshot!(snapshot, diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ fn matches_ignoring_indentation(val1: &str, val2: &str) -> bool {
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_sign_loss)]
|
||||
/// I001
|
||||
pub fn organize_imports(
|
||||
block: &Block,
|
||||
@@ -117,6 +118,7 @@ pub fn organize_imports(
|
||||
&settings.isort.constants,
|
||||
&settings.isort.variables,
|
||||
&settings.isort.no_lines_before,
|
||||
settings.isort.lines_after_imports,
|
||||
);
|
||||
|
||||
// Expand the span the entire range, including leading and trailing space.
|
||||
|
||||
@@ -213,6 +213,17 @@ pub struct Options {
|
||||
/// A list of sections that should _not_ be delineated from the previous
|
||||
/// section via empty lines.
|
||||
pub no_lines_before: Option<Vec<ImportType>>,
|
||||
#[option(
|
||||
default = r#"-1"#,
|
||||
value_type = "int",
|
||||
example = r#"
|
||||
# Use a single line after each import block.
|
||||
lines-after-imports = 1
|
||||
"#
|
||||
)]
|
||||
/// The number of blank lines to place after imports.
|
||||
/// -1 for automatic determination.
|
||||
pub lines_after_imports: Option<isize>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash)]
|
||||
@@ -234,6 +245,7 @@ pub struct Settings {
|
||||
pub constants: BTreeSet<String>,
|
||||
pub variables: BTreeSet<String>,
|
||||
pub no_lines_before: BTreeSet<ImportType>,
|
||||
pub lines_after_imports: isize,
|
||||
}
|
||||
|
||||
impl Default for Settings {
|
||||
@@ -255,6 +267,7 @@ impl Default for Settings {
|
||||
constants: BTreeSet::new(),
|
||||
variables: BTreeSet::new(),
|
||||
no_lines_before: BTreeSet::new(),
|
||||
lines_after_imports: -1,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,6 +295,7 @@ impl From<Options> for Settings {
|
||||
constants: BTreeSet::from_iter(options.constants.unwrap_or_default()),
|
||||
variables: BTreeSet::from_iter(options.variables.unwrap_or_default()),
|
||||
no_lines_before: BTreeSet::from_iter(options.no_lines_before.unwrap_or_default()),
|
||||
lines_after_imports: options.lines_after_imports.unwrap_or(-1),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -305,6 +319,7 @@ impl From<Settings> for Options {
|
||||
constants: Some(settings.constants.into_iter().collect()),
|
||||
variables: Some(settings.variables.into_iter().collect()),
|
||||
no_lines_before: Some(settings.no_lines_before.into_iter().collect()),
|
||||
lines_after_imports: Some(settings.lines_after_imports),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
source: src/rules/isort/mod.rs
|
||||
expression: diagnostics
|
||||
---
|
||||
- kind:
|
||||
UnsortedImports: ~
|
||||
location:
|
||||
row: 1
|
||||
column: 0
|
||||
end_location:
|
||||
row: 10
|
||||
column: 0
|
||||
fix:
|
||||
content:
|
||||
- from __future__ import annotations
|
||||
- ""
|
||||
- from typing import Any
|
||||
- ""
|
||||
- from my_first_party import my_first_party_object
|
||||
- from requests import Session
|
||||
- ""
|
||||
- from . import my_local_folder_object
|
||||
- ""
|
||||
- ""
|
||||
- ""
|
||||
- ""
|
||||
location:
|
||||
row: 1
|
||||
column: 0
|
||||
end_location:
|
||||
row: 10
|
||||
column: 0
|
||||
parent: ~
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
source: src/rules/isort/mod.rs
|
||||
expression: diagnostics
|
||||
---
|
||||
- kind:
|
||||
UnsortedImports: ~
|
||||
location:
|
||||
row: 1
|
||||
column: 0
|
||||
end_location:
|
||||
row: 21
|
||||
column: 0
|
||||
fix:
|
||||
content:
|
||||
- from __future__ import annotations
|
||||
- ""
|
||||
- from typing import Any
|
||||
- ""
|
||||
- from my_first_party import my_first_party_object
|
||||
- from requests import Session
|
||||
- ""
|
||||
- from . import my_local_folder_object
|
||||
- ""
|
||||
- ""
|
||||
- ""
|
||||
- ""
|
||||
location:
|
||||
row: 1
|
||||
column: 0
|
||||
end_location:
|
||||
row: 21
|
||||
column: 0
|
||||
parent: ~
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
source: src/rules/isort/mod.rs
|
||||
expression: diagnostics
|
||||
---
|
||||
- kind:
|
||||
UnsortedImports: ~
|
||||
location:
|
||||
row: 1
|
||||
column: 0
|
||||
end_location:
|
||||
row: 10
|
||||
column: 0
|
||||
fix:
|
||||
content:
|
||||
- from __future__ import annotations
|
||||
- ""
|
||||
- from typing import Any
|
||||
- ""
|
||||
- from my_first_party import my_first_party_object
|
||||
- from requests import Session
|
||||
- ""
|
||||
- from . import my_local_folder_object
|
||||
- ""
|
||||
location:
|
||||
row: 1
|
||||
column: 0
|
||||
end_location:
|
||||
row: 10
|
||||
column: 0
|
||||
parent: ~
|
||||
|
||||
Reference in New Issue
Block a user