Skip to content

Commit 61b7982

Browse files
Respect Unicode characters in import sorting (#10529)
## Summary Ensures that we use the raw identifier as provided in the source code, rather than the normalized Unicode identifier. This _does_ mean that we treat these as two separate identifiers, and _don't_ merge them, even though Python will treat them as the same symbol: ```python import numpy as ℂℇℊℋℌℍℎℐℑℒℓℕℤΩℨKÅℬℭℯℰℱℹℴ import numpy as CƐgHHHhIILlNZΩZKÅBCeEFio ``` I think that's fine, this is super rare anyway and would likely be confusing for users. Closes #10528. ## Test Plan `cargo test`
1 parent 594b232 commit 61b7982

File tree

4 files changed

+37
-6
lines changed

4 files changed

+37
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from astropy.constants import hbar as
2+
from numpy import pi as π
3+
import numpy as ℂℇℊℋℌℍℎℐℑℒℓℕℤΩℨKÅℬℭℯℰℱℹℴ
4+
import numpy as CƐgHHHhIILlNZΩZKÅBCeEFio
5+
6+
h = 2 * π *

crates/ruff_linter/src/rules/isort/annotate.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use super::{AnnotatedAliasData, AnnotatedImport};
1111
pub(crate) fn annotate_imports<'a>(
1212
imports: &'a [&'a Stmt],
1313
comments: Vec<Comment<'a>>,
14-
locator: &Locator,
14+
locator: &Locator<'a>,
1515
split_on_trailing_comma: bool,
1616
source_type: PySourceType,
1717
) -> Vec<AnnotatedImport<'a>> {
@@ -44,8 +44,8 @@ pub(crate) fn annotate_imports<'a>(
4444
names: names
4545
.iter()
4646
.map(|alias| AliasData {
47-
name: &alias.name,
48-
asname: alias.asname.as_deref(),
47+
name: locator.slice(&alias.name),
48+
asname: alias.asname.as_ref().map(|asname| locator.slice(asname)),
4949
})
5050
.collect(),
5151
atop,
@@ -107,16 +107,16 @@ pub(crate) fn annotate_imports<'a>(
107107
}
108108

109109
AnnotatedAliasData {
110-
name: &alias.name,
111-
asname: alias.asname.as_deref(),
110+
name: locator.slice(&alias.name),
111+
asname: alias.asname.as_ref().map(|asname| locator.slice(asname)),
112112
atop: alias_atop,
113113
inline: alias_inline,
114114
}
115115
})
116116
.collect();
117117

118118
AnnotatedImport::ImportFrom {
119-
module: module.as_deref(),
119+
module: module.as_ref().map(|module| locator.slice(module)),
120120
names: aliases,
121121
level: *level,
122122
trailing_comma: if split_on_trailing_comma {

crates/ruff_linter/src/rules/isort/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ mod tests {
342342
#[test_case(Path::new("star_before_others.py"))]
343343
#[test_case(Path::new("trailing_suffix.py"))]
344344
#[test_case(Path::new("type_comments.py"))]
345+
#[test_case(Path::new("unicode.py"))]
345346
fn default(path: &Path) -> Result<()> {
346347
let snapshot = format!("{}", path.to_string_lossy());
347348
let diagnostics = test_path(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
source: crates/ruff_linter/src/rules/isort/mod.rs
3+
---
4+
unicode.py:1:1: I001 [*] Import block is un-sorted or un-formatted
5+
|
6+
1 | / from astropy.constants import hbar as
7+
2 | | from numpy import pi as π
8+
3 | | import numpy as ℂℇℊℋℌℍℎℐℑℒℓℕℤΩℨKÅℬℭℯℰℱℹℴ
9+
4 | | import numpy as CƐgHHHhIILlNZΩZKÅBCeEFio
10+
5 | |
11+
6 | | h = 2 * π *
12+
| |_^ I001
13+
|
14+
= help: Organize imports
15+
16+
Safe fix
17+
1 |+import numpy as CƐgHHHhIILlNZΩZKÅBCeEFio
18+
2 |+import numpy as ℂℇℊℋℌℍℎℐℑℒℓℕℤΩℨKÅℬℭℯℰℱℹℴ
19+
1 3 | from astropy.constants import hbar as
20+
2 4 | from numpy import pi as π
21+
3 |-import numpy as ℂℇℊℋℌℍℎℐℑℒℓℕℤΩℨKÅℬℭℯℰℱℹℴ
22+
4 |-import numpy as CƐgHHHhIILlNZΩZKÅBCeEFio
23+
5 5 |
24+
6 6 | h = 2 * π *

0 commit comments

Comments
 (0)