mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-30 23:27:38 +00:00
Add isort.order-by-type boolean setting (#1607)
This commit is contained in:
parent
8d99e317b8
commit
03275c9c98
7 changed files with 99 additions and 8 deletions
18
README.md
18
README.md
|
@ -2851,6 +2851,24 @@ known-third-party = ["src"]
|
|||
|
||||
---
|
||||
|
||||
#### [`order-by-type`](#order-by-type)
|
||||
|
||||
Order imports by type, which is determined by case, in addition to
|
||||
alphabetically.
|
||||
|
||||
**Default value**: `true`
|
||||
|
||||
**Type**: `bool`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff.isort]
|
||||
order-by-type = true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`single-line-exclusions`](#single-line-exclusions)
|
||||
|
||||
One or more modules to exclude from the single line rule.
|
||||
|
|
|
@ -1324,6 +1324,13 @@
|
|||
"type": "string"
|
||||
}
|
||||
},
|
||||
"order-by-type": {
|
||||
"description": "Order imports by type, which is determined by case, in addition to alphabetically.",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"single-line-exclusions": {
|
||||
"description": "One or more modules to exclude from the single line rule.",
|
||||
"type": [
|
||||
|
|
|
@ -399,7 +399,7 @@ fn categorize_imports<'a>(
|
|||
block_by_type
|
||||
}
|
||||
|
||||
fn sort_imports(block: ImportBlock) -> OrderedImportBlock {
|
||||
fn sort_imports(block: ImportBlock, order_by_type: bool) -> OrderedImportBlock {
|
||||
let mut ordered = OrderedImportBlock::default();
|
||||
|
||||
// Sort `StmtKind::Import`.
|
||||
|
@ -477,7 +477,9 @@ fn sort_imports(block: ImportBlock) -> OrderedImportBlock {
|
|||
locations,
|
||||
aliases
|
||||
.into_iter()
|
||||
.sorted_by(|(alias1, _), (alias2, _)| cmp_members(alias1, alias2))
|
||||
.sorted_by(|(alias1, _), (alias2, _)| {
|
||||
cmp_members(alias1, alias2, order_by_type)
|
||||
})
|
||||
.collect::<Vec<(AliasData, CommentSet)>>(),
|
||||
)
|
||||
})
|
||||
|
@ -488,7 +490,9 @@ fn sort_imports(block: ImportBlock) -> OrderedImportBlock {
|
|||
(None, None) => Ordering::Equal,
|
||||
(None, Some(_)) => Ordering::Less,
|
||||
(Some(_), None) => Ordering::Greater,
|
||||
(Some((alias1, _)), Some((alias2, _))) => cmp_members(alias1, alias2),
|
||||
(Some((alias1, _)), Some((alias2, _))) => {
|
||||
cmp_members(alias1, alias2, order_by_type)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
@ -561,6 +565,7 @@ pub fn format_imports(
|
|||
split_on_trailing_comma: bool,
|
||||
force_single_line: bool,
|
||||
single_line_exclusions: &BTreeSet<String>,
|
||||
order_by_type: bool,
|
||||
) -> String {
|
||||
let trailer = &block.trailer;
|
||||
let block = annotate_imports(&block.imports, comments, locator, split_on_trailing_comma);
|
||||
|
@ -583,7 +588,7 @@ pub fn format_imports(
|
|||
// Generate replacement source code.
|
||||
let mut is_first_block = true;
|
||||
for import_block in block_by_type.into_values() {
|
||||
let mut import_block = sort_imports(import_block);
|
||||
let mut import_block = sort_imports(import_block, order_by_type);
|
||||
if force_single_line {
|
||||
import_block = force_single_line_imports(import_block, single_line_exclusions);
|
||||
}
|
||||
|
@ -781,4 +786,25 @@ mod tests {
|
|||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case(Path::new("order_by_type.py"))]
|
||||
fn order_by_type(path: &Path) -> Result<()> {
|
||||
let snapshot = format!("order_by_type_false_{}", path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
Path::new("./resources/test/fixtures/isort")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&Settings {
|
||||
isort: isort::settings::Settings {
|
||||
order_by_type: false,
|
||||
..isort::settings::Settings::default()
|
||||
},
|
||||
src: vec![Path::new("resources/test/fixtures/isort").to_path_buf()],
|
||||
..Settings::for_rule(CheckCode::I001)
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@ pub fn check_imports(
|
|||
settings.isort.split_on_trailing_comma,
|
||||
settings.isort.force_single_line,
|
||||
&settings.isort.single_line_exclusions,
|
||||
settings.isort.order_by_type,
|
||||
);
|
||||
|
||||
// Expand the span the entire range, including leading and trailing space.
|
||||
|
|
|
@ -78,6 +78,16 @@ pub struct Options {
|
|||
///
|
||||
/// See isort's [`split-on-trailing-comma`](https://pycqa.github.io/isort/docs/configuration/options.html#split-on-trailing-comma) option.
|
||||
pub split_on_trailing_comma: Option<bool>,
|
||||
#[option(
|
||||
default = r#"true"#,
|
||||
value_type = "bool",
|
||||
example = r#"
|
||||
order-by-type = true
|
||||
"#
|
||||
)]
|
||||
/// Order imports by type, which is determined by case, in addition to
|
||||
/// alphabetically.
|
||||
pub order_by_type: Option<bool>,
|
||||
#[option(
|
||||
default = r#"[]"#,
|
||||
value_type = "Vec<String>",
|
||||
|
@ -120,6 +130,7 @@ pub struct Settings {
|
|||
pub single_line_exclusions: BTreeSet<String>,
|
||||
pub known_first_party: BTreeSet<String>,
|
||||
pub known_third_party: BTreeSet<String>,
|
||||
pub order_by_type: bool,
|
||||
pub extra_standard_library: BTreeSet<String>,
|
||||
}
|
||||
|
||||
|
@ -130,6 +141,7 @@ impl Default for Settings {
|
|||
force_wrap_aliases: false,
|
||||
split_on_trailing_comma: true,
|
||||
force_single_line: false,
|
||||
order_by_type: true,
|
||||
single_line_exclusions: BTreeSet::new(),
|
||||
known_first_party: BTreeSet::new(),
|
||||
known_third_party: BTreeSet::new(),
|
||||
|
@ -145,6 +157,7 @@ impl From<Options> for Settings {
|
|||
force_wrap_aliases: options.force_wrap_aliases.unwrap_or(false),
|
||||
split_on_trailing_comma: options.split_on_trailing_comma.unwrap_or(true),
|
||||
force_single_line: options.force_single_line.unwrap_or(false),
|
||||
order_by_type: options.order_by_type.unwrap_or(true),
|
||||
single_line_exclusions: BTreeSet::from_iter(
|
||||
options.single_line_exclusions.unwrap_or_default(),
|
||||
),
|
||||
|
@ -164,6 +177,7 @@ impl From<Settings> for Options {
|
|||
force_wrap_aliases: Some(settings.force_wrap_aliases),
|
||||
split_on_trailing_comma: Some(settings.split_on_trailing_comma),
|
||||
force_single_line: Some(settings.force_single_line),
|
||||
order_by_type: Some(settings.order_by_type),
|
||||
single_line_exclusions: Some(settings.single_line_exclusions.into_iter().collect()),
|
||||
known_first_party: Some(settings.known_first_party.into_iter().collect()),
|
||||
known_third_party: Some(settings.known_third_party.into_iter().collect()),
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
source: src/isort/mod.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: UnsortedImports
|
||||
location:
|
||||
row: 1
|
||||
column: 0
|
||||
end_location:
|
||||
row: 13
|
||||
column: 0
|
||||
fix:
|
||||
content: "import glob\nimport os\nimport shutil\nimport tempfile\nimport time\nfrom subprocess import PIPE, Popen, STDOUT\n\nimport BAR\nimport bar\nimport FOO\nimport foo\nimport StringIO\nfrom module import Apple, BASIC, Class, CONSTANT, function\n"
|
||||
location:
|
||||
row: 1
|
||||
column: 0
|
||||
end_location:
|
||||
row: 13
|
||||
column: 0
|
||||
parent: ~
|
||||
|
|
@ -37,10 +37,14 @@ pub fn cmp_modules(alias1: &AliasData, alias2: &AliasData) -> Ordering {
|
|||
}
|
||||
|
||||
/// Compare two member imports within `StmtKind::ImportFrom` blocks.
|
||||
pub fn cmp_members(alias1: &AliasData, alias2: &AliasData) -> Ordering {
|
||||
prefix(alias1.name)
|
||||
.cmp(&prefix(alias2.name))
|
||||
.then_with(|| cmp_modules(alias1, alias2))
|
||||
pub fn cmp_members(alias1: &AliasData, alias2: &AliasData, order_by_type: bool) -> Ordering {
|
||||
if order_by_type {
|
||||
prefix(alias1.name)
|
||||
.cmp(&prefix(alias2.name))
|
||||
.then_with(|| cmp_modules(alias1, alias2))
|
||||
} else {
|
||||
cmp_modules(alias1, alias2)
|
||||
}
|
||||
}
|
||||
|
||||
/// Compare two relative import levels.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue