Skip to content

Commit aba0d83

Browse files
authored
[flake8-naming]: Respect import conventions (N817) (#12922)
1 parent c319414 commit aba0d83

File tree

5 files changed

+75
-11
lines changed

5 files changed

+75
-11
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
import mod.CaMel as CM
22
from mod import CamelCase as CC
3+
4+
5+
# OK depending on configured import convention
6+
import xml.etree.ElementTree as ET

crates/ruff_linter/src/checkers/ast/analyze/statement.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -707,11 +707,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
707707
}
708708
if checker.enabled(Rule::CamelcaseImportedAsAcronym) {
709709
if let Some(diagnostic) = pep8_naming::rules::camelcase_imported_as_acronym(
710-
name,
711-
asname,
712-
alias,
713-
stmt,
714-
&checker.settings.pep8_naming.ignore_names,
710+
name, asname, alias, stmt, checker,
715711
) {
716712
checker.diagnostics.push(diagnostic);
717713
}
@@ -1026,7 +1022,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
10261022
asname,
10271023
alias,
10281024
stmt,
1029-
&checker.settings.pep8_naming.ignore_names,
1025+
checker,
10301026
) {
10311027
checker.diagnostics.push(diagnostic);
10321028
}

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

+21-1
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ mod tests {
88
use std::path::{Path, PathBuf};
99

1010
use anyhow::Result;
11+
use rustc_hash::FxHashMap;
1112
use test_case::test_case;
1213

1314
use crate::registry::Rule;
14-
use crate::rules::pep8_naming;
1515
use crate::rules::pep8_naming::settings::IgnoreNames;
16+
use crate::rules::{flake8_import_conventions, pep8_naming};
1617
use crate::test::test_path;
1718
use crate::{assert_messages, settings};
1819

@@ -87,6 +88,25 @@ mod tests {
8788
Ok(())
8889
}
8990

91+
#[test]
92+
fn camelcase_imported_as_incorrect_convention() -> Result<()> {
93+
let diagnostics = test_path(
94+
Path::new("pep8_naming").join("N817.py").as_path(),
95+
&settings::LinterSettings {
96+
flake8_import_conventions: flake8_import_conventions::settings::Settings {
97+
aliases: FxHashMap::from_iter([(
98+
"xml.etree.ElementTree".to_string(),
99+
"XET".to_string(),
100+
)]),
101+
..Default::default()
102+
},
103+
..settings::LinterSettings::for_rule(Rule::CamelcaseImportedAsAcronym)
104+
},
105+
)?;
106+
assert_messages!(diagnostics);
107+
Ok(())
108+
}
109+
90110
#[test]
91111
fn classmethod_decorators() -> Result<()> {
92112
let diagnostics = test_path(

crates/ruff_linter/src/rules/pep8_naming/rules/camelcase_imported_as_acronym.rs

+25-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
use ruff_python_ast::{Alias, Stmt};
2-
31
use ruff_diagnostics::{Diagnostic, Violation};
42
use ruff_macros::{derive_message_formats, violation};
3+
use ruff_python_ast::{Alias, Stmt};
54
use ruff_python_stdlib::str::{self};
65
use ruff_text_size::Ranged;
76

7+
use crate::checkers::ast::Checker;
88
use crate::rules::pep8_naming::helpers;
9-
use crate::rules::pep8_naming::settings::IgnoreNames;
109

1110
/// ## What it does
1211
/// Checks for `CamelCase` imports that are aliased as acronyms.
@@ -23,6 +22,10 @@ use crate::rules::pep8_naming::settings::IgnoreNames;
2322
/// Note that this rule is distinct from `camelcase-imported-as-constant`
2423
/// to accommodate selective enforcement.
2524
///
25+
/// Also note that import aliases following an import convention according to the
26+
/// [`lint.flake8-boolean-trap.extend-allowed-calls`] option are allowed.
27+
///
28+
///
2629
/// ## Example
2730
/// ```python
2831
/// from example import MyClassName as MCN
@@ -34,6 +37,9 @@ use crate::rules::pep8_naming::settings::IgnoreNames;
3437
/// ```
3538
///
3639
/// [PEP 8]: https://peps.python.org/pep-0008/
40+
///
41+
/// ## Options
42+
/// - `lint.flake8-import-conventions.banned-aliases`
3743
#[violation]
3844
pub struct CamelcaseImportedAsAcronym {
3945
name: String,
@@ -54,17 +60,32 @@ pub(crate) fn camelcase_imported_as_acronym(
5460
asname: &str,
5561
alias: &Alias,
5662
stmt: &Stmt,
57-
ignore_names: &IgnoreNames,
63+
checker: &Checker,
5864
) -> Option<Diagnostic> {
5965
if helpers::is_camelcase(name)
6066
&& !str::is_cased_lowercase(asname)
6167
&& str::is_cased_uppercase(asname)
6268
&& helpers::is_acronym(name, asname)
6369
{
70+
let ignore_names = &checker.settings.pep8_naming.ignore_names;
71+
6472
// Ignore any explicitly-allowed names.
6573
if ignore_names.matches(name) || ignore_names.matches(asname) {
6674
return None;
6775
}
76+
77+
// Ignore names that follow a community-agreed import convention.
78+
if checker
79+
.settings
80+
.flake8_import_conventions
81+
.aliases
82+
.get(&*alias.name)
83+
.map(String::as_str)
84+
== Some(asname)
85+
{
86+
return None;
87+
}
88+
6889
let mut diagnostic = Diagnostic::new(
6990
CamelcaseImportedAsAcronym {
7091
name: name.to_string(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
source: crates/ruff_linter/src/rules/pep8_naming/mod.rs
3+
---
4+
N817.py:1:8: N817 CamelCase `CaMel` imported as acronym `CM`
5+
|
6+
1 | import mod.CaMel as CM
7+
| ^^^^^^^^^^^^^^^ N817
8+
2 | from mod import CamelCase as CC
9+
|
10+
11+
N817.py:2:17: N817 CamelCase `CamelCase` imported as acronym `CC`
12+
|
13+
1 | import mod.CaMel as CM
14+
2 | from mod import CamelCase as CC
15+
| ^^^^^^^^^^^^^^^ N817
16+
|
17+
18+
N817.py:6:8: N817 CamelCase `ElementTree` imported as acronym `ET`
19+
|
20+
5 | # OK depending on configured import convention
21+
6 | import xml.etree.ElementTree as ET
22+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ N817
23+
|

0 commit comments

Comments
 (0)