Consider ignore-names in all pep8 naming rules (#5079)

## Summary

This changes all remaining pep8 naming rules to consider the
`ingore-names` argument.

Closes #5050

## Test Plan

Added new tests.
This commit is contained in:
Thomas de Zeeuw 2023-06-14 16:57:09 +02:00 committed by GitHub
parent 6f10aeebaa
commit e7316c1cc6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 400 additions and 12 deletions

View file

@ -3,6 +3,7 @@ fail_fast: true
exclude: |
(?x)^(
crates/ruff/resources/.*|
crates/ruff/src/rules/.*/snapshots/.*|
crates/ruff_python_formatter/resources/.*|
crates/ruff_python_formatter/src/snapshots/.*
)$

View file

@ -8,3 +8,4 @@ whos = "whos"
spawnve = "spawnve"
ned = "ned"
poit = "poit"
BA = "BA" # acronym for "Bad Allowed", used in testing.

View file

@ -0,0 +1,11 @@
class badAllowed:
pass
class stillBad:
pass
class BAD_ALLOWED:
pass
class STILL_BAD:
pass

View file

@ -0,0 +1,13 @@
def __badAllowed__():
pass
def __stillBad__():
pass
def nested():
def __badAllowed__():
pass
def __stillBad__():
pass

View file

@ -0,0 +1,5 @@
import mod.BAD_ALLOWED as badAllowed
import mod.STILL_BAD as stillBad
from mod import BAD_ALLOWED as badAllowed
from mod import STILL_BAD as stillBad

View file

@ -0,0 +1,5 @@
import mod.badallowed as badAllowed
import mod.stillbad as stillBad
from mod import badallowed as BadAllowed
from mod import stillbad as StillBad

View file

@ -0,0 +1,8 @@
import mod.BadAllowed as badallowed
import mod.stillBad as stillbad
from mod import BadAllowed as badallowed
from mod import StillBad as stillbad
from mod import BadAllowed as bad_allowed
from mod import StillBad as still_bad

View file

@ -0,0 +1,8 @@
import mod.BadAllowed as BADALLOWED
import mod.StillBad as STILLBAD
from mod import BadAllowed as BADALLOWED
from mod import StillBad as STILLBAD
from mod import BadAllowed as BAD_ALLOWED
from mod import StillBad as STILL_BAD

View file

@ -0,0 +1,5 @@
import mod.BadAllowed as BA
import mod.StillBad as SB
from mod import BadAllowed as BA
from mod import StillBad as SB

View file

@ -0,0 +1,11 @@
class BadAllowed(Exception):
pass
class StillBad(Exception):
pass
class BadAllowed(AnotherError):
pass
class StillBad(AnotherError):
pass

View file

@ -457,6 +457,7 @@ where
self.semantic_model.scope(),
stmt,
name,
&self.settings.pep8_naming.ignore_names,
self.locator,
) {
self.diagnostics.push(diagnostic);
@ -703,9 +704,12 @@ where
}
}
if self.enabled(Rule::InvalidClassName) {
if let Some(diagnostic) =
pep8_naming::rules::invalid_class_name(stmt, name, self.locator)
{
if let Some(diagnostic) = pep8_naming::rules::invalid_class_name(
stmt,
name,
&self.settings.pep8_naming.ignore_names,
self.locator,
) {
self.diagnostics.push(diagnostic);
}
}
@ -715,6 +719,7 @@ where
bases,
name,
self.locator,
&self.settings.pep8_naming.ignore_names,
) {
self.diagnostics.push(diagnostic);
}
@ -898,7 +903,11 @@ where
if self.enabled(Rule::ConstantImportedAsNonConstant) {
if let Some(diagnostic) =
pep8_naming::rules::constant_imported_as_non_constant(
name, asname, alias, stmt,
name,
asname,
alias,
stmt,
&self.settings.pep8_naming.ignore_names,
)
{
self.diagnostics.push(diagnostic);
@ -908,7 +917,11 @@ where
if self.enabled(Rule::LowercaseImportedAsNonLowercase) {
if let Some(diagnostic) =
pep8_naming::rules::lowercase_imported_as_non_lowercase(
name, asname, alias, stmt,
name,
asname,
alias,
stmt,
&self.settings.pep8_naming.ignore_names,
)
{
self.diagnostics.push(diagnostic);
@ -918,7 +931,11 @@ where
if self.enabled(Rule::CamelcaseImportedAsLowercase) {
if let Some(diagnostic) =
pep8_naming::rules::camelcase_imported_as_lowercase(
name, asname, alias, stmt,
name,
asname,
alias,
stmt,
&self.settings.pep8_naming.ignore_names,
)
{
self.diagnostics.push(diagnostic);
@ -928,7 +945,11 @@ where
if self.enabled(Rule::CamelcaseImportedAsConstant) {
if let Some(diagnostic) =
pep8_naming::rules::camelcase_imported_as_constant(
name, asname, alias, stmt,
name,
asname,
alias,
stmt,
&self.settings.pep8_naming.ignore_names,
)
{
self.diagnostics.push(diagnostic);
@ -938,7 +959,11 @@ where
if self.enabled(Rule::CamelcaseImportedAsAcronym) {
if let Some(diagnostic) =
pep8_naming::rules::camelcase_imported_as_acronym(
name, asname, alias, stmt,
name,
asname,
alias,
stmt,
&self.settings.pep8_naming.ignore_names,
)
{
self.diagnostics.push(diagnostic);
@ -1197,6 +1222,7 @@ where
asname,
alias,
stmt,
&self.settings.pep8_naming.ignore_names,
)
{
self.diagnostics.push(diagnostic);
@ -1210,6 +1236,7 @@ where
asname,
alias,
stmt,
&self.settings.pep8_naming.ignore_names,
)
{
self.diagnostics.push(diagnostic);
@ -1223,6 +1250,7 @@ where
asname,
alias,
stmt,
&self.settings.pep8_naming.ignore_names,
)
{
self.diagnostics.push(diagnostic);
@ -1236,6 +1264,7 @@ where
asname,
alias,
stmt,
&self.settings.pep8_naming.ignore_names,
)
{
self.diagnostics.push(diagnostic);
@ -1249,6 +1278,7 @@ where
asname,
alias,
stmt,
&self.settings.pep8_naming.ignore_names,
)
{
self.diagnostics.push(diagnostic);

View file

@ -25,7 +25,9 @@ pub(crate) fn check_file_path(
// pep8-naming
if settings.rules.enabled(Rule::InvalidModuleName) {
if let Some(diagnostic) = invalid_module_name(path, package) {
if let Some(diagnostic) =
invalid_module_name(path, package, &settings.pep8_naming.ignore_names)
{
diagnostics.push(diagnostic);
}
}

View file

@ -106,13 +106,22 @@ mod tests {
Ok(())
}
#[test_case(Rule::InvalidClassName, "N801.py")]
#[test_case(Rule::InvalidFunctionName, "N802.py")]
#[test_case(Rule::InvalidArgumentName, "N803.py")]
#[test_case(Rule::InvalidFirstArgumentNameForClassMethod, "N804.py")]
#[test_case(Rule::InvalidFirstArgumentNameForMethod, "N805.py")]
#[test_case(Rule::NonLowercaseVariableInFunction, "N806.py")]
#[test_case(Rule::DunderFunctionName, "N807.py")]
#[test_case(Rule::ConstantImportedAsNonConstant, "N811.py")]
#[test_case(Rule::LowercaseImportedAsNonLowercase, "N812.py")]
#[test_case(Rule::CamelcaseImportedAsLowercase, "N813.py")]
#[test_case(Rule::CamelcaseImportedAsConstant, "N814.py")]
#[test_case(Rule::MixedCaseVariableInClassScope, "N815.py")]
#[test_case(Rule::MixedCaseVariableInGlobalScope, "N816.py")]
#[test_case(Rule::CamelcaseImportedAsAcronym, "N817.py")]
#[test_case(Rule::ErrorSuffixOnExceptionName, "N818.py")]
#[test_case(Rule::InvalidModuleName, "N999/badAllowed/__init__.py")]
fn ignore_names(rule_code: Rule, path: &str) -> Result<()> {
let snapshot = format!("ignore_names_{}_{path}", rule_code.noqa_code());
let diagnostics = test_path(
@ -120,8 +129,10 @@ mod tests {
&settings::Settings {
pep8_naming: pep8_naming::settings::Settings {
ignore_names: vec![
IdentifierPattern::new("*Allowed").unwrap(),
IdentifierPattern::new("*ALLOWED").unwrap(),
IdentifierPattern::new("*allowed*").unwrap(),
IdentifierPattern::new("*Allowed*").unwrap(),
IdentifierPattern::new("*ALLOWED*").unwrap(),
IdentifierPattern::new("BA").unwrap(), // For N817.
],
..Default::default()
},

View file

@ -5,6 +5,7 @@ use ruff_macros::{derive_message_formats, violation};
use ruff_python_stdlib::str::{self};
use crate::rules::pep8_naming::helpers;
use crate::settings::types::IdentifierPattern;
/// ## What it does
/// Checks for `CamelCase` imports that are aliased as acronyms.
@ -52,7 +53,15 @@ pub(crate) fn camelcase_imported_as_acronym(
asname: &str,
alias: &Alias,
stmt: &Stmt,
ignore_names: &[IdentifierPattern],
) -> Option<Diagnostic> {
if ignore_names
.iter()
.any(|ignore_name| ignore_name.matches(asname))
{
return None;
}
if helpers::is_camelcase(name)
&& !str::is_lower(asname)
&& str::is_upper(asname)

View file

@ -5,6 +5,7 @@ use ruff_macros::{derive_message_formats, violation};
use ruff_python_stdlib::str::{self};
use crate::rules::pep8_naming::helpers;
use crate::settings::types::IdentifierPattern;
/// ## What it does
/// Checks for `CamelCase` imports that are aliased to constant-style names.
@ -49,7 +50,15 @@ pub(crate) fn camelcase_imported_as_constant(
asname: &str,
alias: &Alias,
stmt: &Stmt,
ignore_names: &[IdentifierPattern],
) -> Option<Diagnostic> {
if ignore_names
.iter()
.any(|ignore_name| ignore_name.matches(name))
{
return None;
}
if helpers::is_camelcase(name)
&& !str::is_lower(asname)
&& str::is_upper(asname)

View file

@ -4,6 +4,7 @@ use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use crate::rules::pep8_naming::helpers;
use crate::settings::types::IdentifierPattern;
/// ## What it does
/// Checks for `CamelCase` imports that are aliased to lowercase names.
@ -48,7 +49,15 @@ pub(crate) fn camelcase_imported_as_lowercase(
asname: &str,
alias: &Alias,
stmt: &Stmt,
ignore_names: &[IdentifierPattern],
) -> Option<Diagnostic> {
if ignore_names
.iter()
.any(|ignore_name| ignore_name.matches(asname))
{
return None;
}
if helpers::is_camelcase(name) && ruff_python_stdlib::str::is_lower(asname) {
let mut diagnostic = Diagnostic::new(
CamelcaseImportedAsLowercase {

View file

@ -4,6 +4,8 @@ use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_stdlib::str;
use crate::settings::types::IdentifierPattern;
/// ## What it does
/// Checks for constant imports that are aliased to non-constant-style
/// names.
@ -48,7 +50,15 @@ pub(crate) fn constant_imported_as_non_constant(
asname: &str,
alias: &Alias,
stmt: &Stmt,
ignore_names: &[IdentifierPattern],
) -> Option<Diagnostic> {
if ignore_names
.iter()
.any(|ignore_name| ignore_name.matches(name))
{
return None;
}
if str::is_upper(name) && !str::is_upper(asname) {
let mut diagnostic = Diagnostic::new(
ConstantImportedAsNonConstant {

View file

@ -6,6 +6,8 @@ use ruff_python_ast::helpers::identifier_range;
use ruff_python_ast::source_code::Locator;
use ruff_python_semantic::scope::{Scope, ScopeKind};
use crate::settings::types::IdentifierPattern;
/// ## What it does
/// Checks for functions with "dunder" names (that is, names with two
/// leading and trailing underscores) that are not documented.
@ -45,6 +47,7 @@ pub(crate) fn dunder_function_name(
scope: &Scope,
stmt: &Stmt,
name: &str,
ignore_names: &[IdentifierPattern],
locator: &Locator,
) -> Option<Diagnostic> {
if matches!(scope.kind, ScopeKind::Class(_)) {
@ -57,6 +60,12 @@ pub(crate) fn dunder_function_name(
if matches!(scope.kind, ScopeKind::Module) && (name == "__getattr__" || name == "__dir__") {
return None;
}
if ignore_names
.iter()
.any(|ignore_name| ignore_name.matches(name))
{
return None;
}
Some(Diagnostic::new(
DunderFunctionName,

View file

@ -5,6 +5,8 @@ use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::helpers::identifier_range;
use ruff_python_ast::source_code::Locator;
use crate::settings::types::IdentifierPattern;
/// ## What it does
/// Checks for custom exception definitions that omit the `Error` suffix.
///
@ -47,7 +49,15 @@ pub(crate) fn error_suffix_on_exception_name(
bases: &[Expr],
name: &str,
locator: &Locator,
ignore_names: &[IdentifierPattern],
) -> Option<Diagnostic> {
if ignore_names
.iter()
.any(|ignore_name| ignore_name.matches(name))
{
return None;
}
if !bases.iter().any(|base| {
if let Expr::Name(ast::ExprName { id, .. }) = &base {
id == "Exception" || id.ends_with("Error")

View file

@ -5,6 +5,8 @@ use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::helpers::identifier_range;
use ruff_python_ast::source_code::Locator;
use crate::settings::types::IdentifierPattern;
/// ## What it does
/// Checks for class names that do not follow the `CamelCase` convention.
///
@ -51,8 +53,16 @@ impl Violation for InvalidClassName {
pub(crate) fn invalid_class_name(
class_def: &Stmt,
name: &str,
ignore_names: &[IdentifierPattern],
locator: &Locator,
) -> Option<Diagnostic> {
if ignore_names
.iter()
.any(|ignore_name| ignore_name.matches(name))
{
return None;
}
let stripped = name.strip_prefix('_').unwrap_or(name);
if !stripped.chars().next().map_or(false, char::is_uppercase) || stripped.contains('_') {
return Some(Diagnostic::new(

View file

@ -7,6 +7,8 @@ use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_stdlib::identifiers::{is_migration_name, is_module_name};
use crate::settings::types::IdentifierPattern;
/// ## What it does
/// Checks for module names that do not follow the `snake_case` naming
/// convention or are otherwise invalid.
@ -46,7 +48,11 @@ impl Violation for InvalidModuleName {
}
/// N999
pub(crate) fn invalid_module_name(path: &Path, package: Option<&Path>) -> Option<Diagnostic> {
pub(crate) fn invalid_module_name(
path: &Path,
package: Option<&Path>,
ignore_names: &[IdentifierPattern],
) -> Option<Diagnostic> {
if !path
.extension()
.map_or(false, |ext| ext == "py" || ext == "pyi")
@ -61,6 +67,13 @@ pub(crate) fn invalid_module_name(path: &Path, package: Option<&Path>) -> Option
path.file_stem().unwrap().to_string_lossy()
};
if ignore_names
.iter()
.any(|ignore_name| ignore_name.matches(&module_name))
{
return None;
}
// As a special case, we allow files in `versions` and `migrations` directories to start
// with a digit (e.g., `0001_initial.py`), to support common conventions used by Django
// and other frameworks.

View file

@ -4,6 +4,8 @@ use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_stdlib::str;
use crate::settings::types::IdentifierPattern;
/// ## What it does
/// Checks for lowercase imports that are aliased to non-lowercase names.
///
@ -47,7 +49,15 @@ pub(crate) fn lowercase_imported_as_non_lowercase(
asname: &str,
alias: &Alias,
stmt: &Stmt,
ignore_names: &[IdentifierPattern],
) -> Option<Diagnostic> {
if ignore_names
.iter()
.any(|ignore_name| ignore_name.matches(asname))
{
return None;
}
if !str::is_upper(name) && str::is_lower(name) && asname.to_lowercase() != asname {
let mut diagnostic = Diagnostic::new(
LowercaseImportedAsNonLowercase {

View file

@ -0,0 +1,22 @@
---
source: crates/ruff/src/rules/pep8_naming/mod.rs
---
N801.py:4:7: N801 Class name `stillBad` should use CapWords convention
|
2 | pass
3 |
4 | class stillBad:
| ^^^^^^^^ N801
5 | pass
|
N801.py:10:7: N801 Class name `STILL_BAD` should use CapWords convention
|
8 | pass
9 |
10 | class STILL_BAD:
| ^^^^^^^^^ N801
11 | pass
|

View file

@ -0,0 +1,22 @@
---
source: crates/ruff/src/rules/pep8_naming/mod.rs
---
N807.py:4:5: N807 Function name should not start and end with `__`
|
2 | pass
3 |
4 | def __stillBad__():
| ^^^^^^^^^^^^ N807
5 | pass
|
N807.py:12:9: N807 Function name should not start and end with `__`
|
10 | pass
11 |
12 | def __stillBad__():
| ^^^^^^^^^^^^ N807
13 | pass
|

View file

@ -0,0 +1,20 @@
---
source: crates/ruff/src/rules/pep8_naming/mod.rs
---
N811.py:2:8: N811 Constant `STILL_BAD` imported as non-constant `stillBad`
|
1 | import mod.BAD_ALLOWED as badAllowed
2 | import mod.STILL_BAD as stillBad
| ^^^^^^^^^^^^^^^^^^^^^^^^^ N811
3 |
4 | from mod import BAD_ALLOWED as badAllowed
|
N811.py:5:17: N811 Constant `STILL_BAD` imported as non-constant `stillBad`
|
4 | from mod import BAD_ALLOWED as badAllowed
5 | from mod import STILL_BAD as stillBad
| ^^^^^^^^^^^^^^^^^^^^^ N811
|

View file

@ -0,0 +1,20 @@
---
source: crates/ruff/src/rules/pep8_naming/mod.rs
---
N812.py:2:8: N812 Lowercase `stillbad` imported as non-lowercase `stillBad`
|
1 | import mod.badallowed as badAllowed
2 | import mod.stillbad as stillBad
| ^^^^^^^^^^^^^^^^^^^^^^^^ N812
3 |
4 | from mod import badallowed as BadAllowed
|
N812.py:5:17: N812 Lowercase `stillbad` imported as non-lowercase `StillBad`
|
4 | from mod import badallowed as BadAllowed
5 | from mod import stillbad as StillBad
| ^^^^^^^^^^^^^^^^^^^^ N812
|

View file

@ -0,0 +1,29 @@
---
source: crates/ruff/src/rules/pep8_naming/mod.rs
---
N813.py:2:8: N813 Camelcase `stillBad` imported as lowercase `stillbad`
|
1 | import mod.BadAllowed as badallowed
2 | import mod.stillBad as stillbad
| ^^^^^^^^^^^^^^^^^^^^^^^^ N813
3 |
4 | from mod import BadAllowed as badallowed
|
N813.py:5:17: N813 Camelcase `StillBad` imported as lowercase `stillbad`
|
4 | from mod import BadAllowed as badallowed
5 | from mod import StillBad as stillbad
| ^^^^^^^^^^^^^^^^^^^^ N813
6 |
7 | from mod import BadAllowed as bad_allowed
|
N813.py:8:17: N813 Camelcase `StillBad` imported as lowercase `still_bad`
|
7 | from mod import BadAllowed as bad_allowed
8 | from mod import StillBad as still_bad
| ^^^^^^^^^^^^^^^^^^^^^ N813
|

View file

@ -0,0 +1,29 @@
---
source: crates/ruff/src/rules/pep8_naming/mod.rs
---
N814.py:2:8: N814 Camelcase `StillBad` imported as constant `STILLBAD`
|
1 | import mod.BadAllowed as BADALLOWED
2 | import mod.StillBad as STILLBAD
| ^^^^^^^^^^^^^^^^^^^^^^^^ N814
3 |
4 | from mod import BadAllowed as BADALLOWED
|
N814.py:5:17: N814 Camelcase `StillBad` imported as constant `STILLBAD`
|
4 | from mod import BadAllowed as BADALLOWED
5 | from mod import StillBad as STILLBAD
| ^^^^^^^^^^^^^^^^^^^^ N814
6 |
7 | from mod import BadAllowed as BAD_ALLOWED
|
N814.py:8:17: N814 Camelcase `StillBad` imported as constant `STILL_BAD`
|
7 | from mod import BadAllowed as BAD_ALLOWED
8 | from mod import StillBad as STILL_BAD
| ^^^^^^^^^^^^^^^^^^^^^ N814
|

View file

@ -0,0 +1,20 @@
---
source: crates/ruff/src/rules/pep8_naming/mod.rs
---
N817.py:2:8: N817 CamelCase `StillBad` imported as acronym `SB`
|
1 | import mod.BadAllowed as BA
2 | import mod.StillBad as SB
| ^^^^^^^^^^^^^^^^^^ N817
3 |
4 | from mod import BadAllowed as BA
|
N817.py:5:17: N817 CamelCase `StillBad` imported as acronym `SB`
|
4 | from mod import BadAllowed as BA
5 | from mod import StillBad as SB
| ^^^^^^^^^^^^^^ N817
|

View file

@ -0,0 +1,22 @@
---
source: crates/ruff/src/rules/pep8_naming/mod.rs
---
N818.py:4:7: N818 Exception name `StillBad` should be named with an Error suffix
|
2 | pass
3 |
4 | class StillBad(Exception):
| ^^^^^^^^ N818
5 | pass
|
N818.py:10:7: N818 Exception name `StillBad` should be named with an Error suffix
|
8 | pass
9 |
10 | class StillBad(AnotherError):
| ^^^^^^^^ N818
11 | pass
|

View file

@ -0,0 +1,4 @@
---
source: crates/ruff/src/rules/pep8_naming/mod.rs
---