Skip to content

Commit

Permalink
Respect Unicode characters in import sorting (#10529)
Browse files Browse the repository at this point in the history
## 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`
  • Loading branch information
charliermarsh committed Mar 22, 2024
1 parent 594b232 commit 61b7982
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 6 deletions.
6 changes: 6 additions & 0 deletions crates/ruff_linter/resources/test/fixtures/isort/unicode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from astropy.constants import hbar as
from numpy import pi as π
import numpy as ℂℇℊℋℌℍℎℐℑℒℓℕℤΩℨKÅℬℭℯℰℱℹℴ
import numpy as CƐgHHHhIILlNZΩZKÅBCeEFio

h = 2 * π *
12 changes: 6 additions & 6 deletions crates/ruff_linter/src/rules/isort/annotate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::{AnnotatedAliasData, AnnotatedImport};
pub(crate) fn annotate_imports<'a>(
imports: &'a [&'a Stmt],
comments: Vec<Comment<'a>>,
locator: &Locator,
locator: &Locator<'a>,
split_on_trailing_comma: bool,
source_type: PySourceType,
) -> Vec<AnnotatedImport<'a>> {
Expand Down Expand Up @@ -44,8 +44,8 @@ pub(crate) fn annotate_imports<'a>(
names: names
.iter()
.map(|alias| AliasData {
name: &alias.name,
asname: alias.asname.as_deref(),
name: locator.slice(&alias.name),
asname: alias.asname.as_ref().map(|asname| locator.slice(asname)),
})
.collect(),
atop,
Expand Down Expand Up @@ -107,16 +107,16 @@ pub(crate) fn annotate_imports<'a>(
}

AnnotatedAliasData {
name: &alias.name,
asname: alias.asname.as_deref(),
name: locator.slice(&alias.name),
asname: alias.asname.as_ref().map(|asname| locator.slice(asname)),
atop: alias_atop,
inline: alias_inline,
}
})
.collect();

AnnotatedImport::ImportFrom {
module: module.as_deref(),
module: module.as_ref().map(|module| locator.slice(module)),
names: aliases,
level: *level,
trailing_comma: if split_on_trailing_comma {
Expand Down
1 change: 1 addition & 0 deletions crates/ruff_linter/src/rules/isort/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ mod tests {
#[test_case(Path::new("star_before_others.py"))]
#[test_case(Path::new("trailing_suffix.py"))]
#[test_case(Path::new("type_comments.py"))]
#[test_case(Path::new("unicode.py"))]
fn default(path: &Path) -> Result<()> {
let snapshot = format!("{}", path.to_string_lossy());
let diagnostics = test_path(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
source: crates/ruff_linter/src/rules/isort/mod.rs
---
unicode.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
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 * π *
| |_^ I001
|
= help: Organize imports

Safe fix
1 |+import numpy as CƐgHHHhIILlNZΩZKÅBCeEFio
2 |+import numpy as ℂℇℊℋℌℍℎℐℑℒℓℕℤΩℨKÅℬℭℯℰℱℹℴ
1 3 | from astropy.constants import hbar as
2 4 | from numpy import pi as π
3 |-import numpy as ℂℇℊℋℌℍℎℐℑℒℓℕℤΩℨKÅℬℭℯℰℱℹℴ
4 |-import numpy as CƐgHHHhIILlNZΩZKÅBCeEFio
5 5 |
6 6 | h = 2 * π *

0 comments on commit 61b7982

Please sign in to comment.