mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-01 17:32:25 +00:00
[flake8-builtins
] Implement import, lambda, and module shadowing (#12546)
## Summary <!-- What's the purpose of the change? What does it do, and why? --> Extend `flake8-builtins` to imports, lambda-arguments, and modules to be consistent with original checker [flake8_builtins](https://github.com/gforcada/flake8-builtins/blob/main/flake8_builtins.py). closes #12540 ## Details - Implement builtin-import-shadowing (A004) - Stop tracking imports shadowing in builtin-variable-shadowing (A001) in preview mode. - Implement builtin-lambda-argument-shadowing (A005) - Implement builtin-module-shadowing (A006) - Add new option `linter.flake8_builtins.builtins_allowed_modules` ## Test Plan cargo test
This commit is contained in:
parent
665c75f7ab
commit
9cdc578dd9
41 changed files with 589 additions and 24 deletions
|
@ -232,6 +232,7 @@ linter.flake8_bandit.hardcoded_tmp_directory = [
|
|||
]
|
||||
linter.flake8_bandit.check_typed_exception = false
|
||||
linter.flake8_bugbear.extend_immutable_calls = []
|
||||
linter.flake8_builtins.builtins_allowed_modules = []
|
||||
linter.flake8_builtins.builtins_ignorelist = []
|
||||
linter.flake8_comprehensions.allow_dict_calls_with_keyword_arguments = false
|
||||
linter.flake8_copyright.notice_rgx = (?i)Copyright\s+((?:\(C\)|©)\s+)?\d{4}((-|,\s)\d{4})*
|
||||
|
|
5
crates/ruff_linter/resources/test/fixtures/flake8_builtins/A004.py
vendored
Normal file
5
crates/ruff_linter/resources/test/fixtures/flake8_builtins/A004.py
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
import some as sum
|
||||
import float
|
||||
from some import other as int
|
||||
from some import input, exec
|
||||
from directory import new as dir
|
0
crates/ruff_linter/resources/test/fixtures/flake8_builtins/A005/modules/logging/__init__.py
vendored
Normal file
0
crates/ruff_linter/resources/test/fixtures/flake8_builtins/A005/modules/logging/__init__.py
vendored
Normal file
0
crates/ruff_linter/resources/test/fixtures/flake8_builtins/A005/modules/package/__init__.py
vendored
Normal file
0
crates/ruff_linter/resources/test/fixtures/flake8_builtins/A005/modules/package/__init__.py
vendored
Normal file
0
crates/ruff_linter/resources/test/fixtures/flake8_builtins/A005/modules/package/bisect.py
vendored
Normal file
0
crates/ruff_linter/resources/test/fixtures/flake8_builtins/A005/modules/package/bisect.py
vendored
Normal file
0
crates/ruff_linter/resources/test/fixtures/flake8_builtins/A005/modules/package/xml.py
vendored
Normal file
0
crates/ruff_linter/resources/test/fixtures/flake8_builtins/A005/modules/package/xml.py
vendored
Normal file
0
crates/ruff_linter/resources/test/fixtures/flake8_builtins/A005/modules/string/__init__.py
vendored
Normal file
0
crates/ruff_linter/resources/test/fixtures/flake8_builtins/A005/modules/string/__init__.py
vendored
Normal file
5
crates/ruff_linter/resources/test/fixtures/flake8_builtins/A006.py
vendored
Normal file
5
crates/ruff_linter/resources/test/fixtures/flake8_builtins/A006.py
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
lambda print, copyright: print
|
||||
lambda x, float, y: x + y
|
||||
lambda min, max: min
|
||||
lambda id: id
|
||||
lambda dir: dir
|
|
@ -2,7 +2,7 @@ use ruff_python_ast::Expr;
|
|||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::codes::Rule;
|
||||
use crate::rules::{flake8_pie, pylint, refurb};
|
||||
use crate::rules::{flake8_builtins, flake8_pie, pylint, refurb};
|
||||
|
||||
/// Run lint rules over all deferred lambdas in the [`SemanticModel`].
|
||||
pub(crate) fn deferred_lambdas(checker: &mut Checker) {
|
||||
|
@ -24,6 +24,9 @@ pub(crate) fn deferred_lambdas(checker: &mut Checker) {
|
|||
if checker.enabled(Rule::ReimplementedOperator) {
|
||||
refurb::rules::reimplemented_operator(checker, &lambda.into());
|
||||
}
|
||||
if checker.enabled(Rule::BuiltinLambdaArgumentShadowing) {
|
||||
flake8_builtins::rules::builtin_lambda_argument_shadowing(checker, lambda);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -597,8 +597,11 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
if checker.enabled(Rule::NonAsciiImportName) {
|
||||
pylint::rules::non_ascii_module_import(checker, alias);
|
||||
}
|
||||
// TODO(charlie): Remove when stabilizing A004.
|
||||
if let Some(asname) = &alias.asname {
|
||||
if checker.enabled(Rule::BuiltinVariableShadowing) {
|
||||
if checker.settings.preview.is_disabled()
|
||||
&& checker.enabled(Rule::BuiltinVariableShadowing)
|
||||
{
|
||||
flake8_builtins::rules::builtin_variable_shadowing(
|
||||
checker,
|
||||
asname,
|
||||
|
@ -739,6 +742,9 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
checker.diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::BuiltinImportShadowing) {
|
||||
flake8_builtins::rules::builtin_import_shadowing(checker, alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
Stmt::ImportFrom(
|
||||
|
@ -917,8 +923,11 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
));
|
||||
}
|
||||
} else {
|
||||
// TODO(charlie): Remove when stabilizing A004.
|
||||
if let Some(asname) = &alias.asname {
|
||||
if checker.enabled(Rule::BuiltinVariableShadowing) {
|
||||
if checker.settings.preview.is_disabled()
|
||||
&& checker.enabled(Rule::BuiltinVariableShadowing)
|
||||
{
|
||||
flake8_builtins::rules::builtin_variable_shadowing(
|
||||
checker,
|
||||
asname,
|
||||
|
@ -1030,6 +1039,9 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::BuiltinImportShadowing) {
|
||||
flake8_builtins::rules::builtin_import_shadowing(checker, alias);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::ImportSelf) {
|
||||
if let Some(diagnostic) = pylint::rules::import_from_self(
|
||||
|
|
|
@ -5,6 +5,7 @@ use ruff_python_trivia::CommentRanges;
|
|||
use ruff_source_file::Locator;
|
||||
|
||||
use crate::registry::Rule;
|
||||
use crate::rules::flake8_builtins::rules::builtin_module_shadowing;
|
||||
use crate::rules::flake8_no_pep420::rules::implicit_namespace_package;
|
||||
use crate::rules::pep8_naming::rules::invalid_module_name;
|
||||
use crate::settings::LinterSettings;
|
||||
|
@ -41,5 +42,17 @@ pub(crate) fn check_file_path(
|
|||
}
|
||||
}
|
||||
|
||||
// flake8-builtins
|
||||
if settings.rules.enabled(Rule::BuiltinModuleShadowing) {
|
||||
if let Some(diagnostic) = builtin_module_shadowing(
|
||||
path,
|
||||
package,
|
||||
&settings.flake8_builtins.builtins_allowed_modules,
|
||||
settings.target_version,
|
||||
) {
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
diagnostics
|
||||
}
|
||||
|
|
|
@ -310,6 +310,10 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
|||
(Flake8Builtins, "001") => (RuleGroup::Stable, rules::flake8_builtins::rules::BuiltinVariableShadowing),
|
||||
(Flake8Builtins, "002") => (RuleGroup::Stable, rules::flake8_builtins::rules::BuiltinArgumentShadowing),
|
||||
(Flake8Builtins, "003") => (RuleGroup::Stable, rules::flake8_builtins::rules::BuiltinAttributeShadowing),
|
||||
// TODO(charlie): When stabilizing, remove preview gating for A001's treatment of imports.
|
||||
(Flake8Builtins, "004") => (RuleGroup::Preview, rules::flake8_builtins::rules::BuiltinImportShadowing),
|
||||
(Flake8Builtins, "005") => (RuleGroup::Preview, rules::flake8_builtins::rules::BuiltinModuleShadowing),
|
||||
(Flake8Builtins, "006") => (RuleGroup::Preview, rules::flake8_builtins::rules::BuiltinLambdaArgumentShadowing),
|
||||
|
||||
// flake8-bugbear
|
||||
(Flake8Bugbear, "002") => (RuleGroup::Stable, rules::flake8_bugbear::rules::UnaryPrefixIncrementDecrement),
|
||||
|
|
|
@ -304,7 +304,9 @@ impl Rule {
|
|||
| Rule::UTF8EncodingDeclaration => LintSource::Tokens,
|
||||
Rule::IOError => LintSource::Io,
|
||||
Rule::UnsortedImports | Rule::MissingRequiredImport => LintSource::Imports,
|
||||
Rule::ImplicitNamespacePackage | Rule::InvalidModuleName => LintSource::Filesystem,
|
||||
Rule::ImplicitNamespacePackage
|
||||
| Rule::InvalidModuleName
|
||||
| Rule::BuiltinModuleShadowing => LintSource::Filesystem,
|
||||
Rule::IndentationWithInvalidMultiple
|
||||
| Rule::IndentationWithInvalidMultipleComment
|
||||
| Rule::MissingWhitespace
|
||||
|
|
|
@ -18,6 +18,25 @@ mod tests {
|
|||
#[test_case(Rule::BuiltinVariableShadowing, Path::new("A001.py"))]
|
||||
#[test_case(Rule::BuiltinArgumentShadowing, Path::new("A002.py"))]
|
||||
#[test_case(Rule::BuiltinAttributeShadowing, Path::new("A003.py"))]
|
||||
#[test_case(Rule::BuiltinImportShadowing, Path::new("A004.py"))]
|
||||
#[test_case(
|
||||
Rule::BuiltinModuleShadowing,
|
||||
Path::new("A005/modules/non_builtin/__init__.py")
|
||||
)]
|
||||
#[test_case(
|
||||
Rule::BuiltinModuleShadowing,
|
||||
Path::new("A005/modules/logging/__init__.py")
|
||||
)]
|
||||
#[test_case(
|
||||
Rule::BuiltinModuleShadowing,
|
||||
Path::new("A005/modules/string/__init__.py")
|
||||
)]
|
||||
#[test_case(
|
||||
Rule::BuiltinModuleShadowing,
|
||||
Path::new("A005/modules/package/bisect.py")
|
||||
)]
|
||||
#[test_case(Rule::BuiltinModuleShadowing, Path::new("A005/modules/package/xml.py"))]
|
||||
#[test_case(Rule::BuiltinLambdaArgumentShadowing, Path::new("A006.py"))]
|
||||
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
|
||||
let diagnostics = test_path(
|
||||
|
@ -31,6 +50,8 @@ mod tests {
|
|||
#[test_case(Rule::BuiltinVariableShadowing, Path::new("A001.py"))]
|
||||
#[test_case(Rule::BuiltinArgumentShadowing, Path::new("A002.py"))]
|
||||
#[test_case(Rule::BuiltinAttributeShadowing, Path::new("A003.py"))]
|
||||
#[test_case(Rule::BuiltinImportShadowing, Path::new("A004.py"))]
|
||||
#[test_case(Rule::BuiltinLambdaArgumentShadowing, Path::new("A006.py"))]
|
||||
fn builtins_ignorelist(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!(
|
||||
"{}_{}_builtins_ignorelist",
|
||||
|
@ -43,6 +64,46 @@ mod tests {
|
|||
&LinterSettings {
|
||||
flake8_builtins: super::settings::Settings {
|
||||
builtins_ignorelist: vec!["id".to_string(), "dir".to_string()],
|
||||
..Default::default()
|
||||
},
|
||||
..LinterSettings::for_rules(vec![rule_code])
|
||||
},
|
||||
)?;
|
||||
|
||||
assert_messages!(snapshot, diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case(
|
||||
Rule::BuiltinModuleShadowing,
|
||||
Path::new("A005/modules/non_builtin/__init__.py")
|
||||
)]
|
||||
#[test_case(
|
||||
Rule::BuiltinModuleShadowing,
|
||||
Path::new("A005/modules/logging/__init__.py")
|
||||
)]
|
||||
#[test_case(
|
||||
Rule::BuiltinModuleShadowing,
|
||||
Path::new("A005/modules/string/__init__.py")
|
||||
)]
|
||||
#[test_case(
|
||||
Rule::BuiltinModuleShadowing,
|
||||
Path::new("A005/modules/package/bisect.py")
|
||||
)]
|
||||
#[test_case(Rule::BuiltinModuleShadowing, Path::new("A005/modules/package/xml.py"))]
|
||||
fn builtins_allowed_modules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!(
|
||||
"{}_{}_builtins_allowed_modules",
|
||||
rule_code.noqa_code(),
|
||||
path.to_string_lossy()
|
||||
);
|
||||
|
||||
let diagnostics = test_path(
|
||||
Path::new("flake8_builtins").join(path).as_path(),
|
||||
&LinterSettings {
|
||||
flake8_builtins: super::settings::Settings {
|
||||
builtins_allowed_modules: vec!["xml".to_string(), "logging".to_string()],
|
||||
..Default::default()
|
||||
},
|
||||
..LinterSettings::for_rules(vec![rule_code])
|
||||
},
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use ruff_python_ast::Parameter;
|
||||
|
||||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_diagnostics::Violation;
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::Parameter;
|
||||
use ruff_python_semantic::analyze::visibility::{is_overload, is_override};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
|
@ -11,7 +10,7 @@ use crate::checkers::ast::Checker;
|
|||
use super::super::helpers::shadows_builtin;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for any function arguments that use the same name as a builtin.
|
||||
/// Checks for function arguments that use the same names as builtins.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Reusing a builtin name for the name of an argument increases the
|
||||
|
|
|
@ -10,8 +10,8 @@ use crate::checkers::ast::Checker;
|
|||
use crate::rules::flake8_builtins::helpers::shadows_builtin;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for any class attributes or methods that use the same name as a
|
||||
/// builtin.
|
||||
/// Checks for class attributes and methods that use the same names as
|
||||
/// Python builtins.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Reusing a builtin name for the name of an attribute increases the
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::Alias;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::rules::flake8_builtins::helpers::shadows_builtin;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for imports that use the same names as builtins.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Reusing a builtin for the name of an import increases the difficulty
|
||||
/// of reading and maintaining the code, and can cause non-obvious errors,
|
||||
/// as readers may mistake the variable for the builtin and vice versa.
|
||||
///
|
||||
/// Builtins can be marked as exceptions to this rule via the
|
||||
/// [`lint.flake8-builtins.builtins-ignorelist`] configuration option.
|
||||
///
|
||||
/// ## Options
|
||||
/// - `lint.flake8-builtins.builtins-ignorelist`
|
||||
#[violation]
|
||||
pub struct BuiltinImportShadowing {
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl Violation for BuiltinImportShadowing {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let BuiltinImportShadowing { name } = self;
|
||||
format!("Import `{name}` is shadowing a Python builtin")
|
||||
}
|
||||
}
|
||||
|
||||
/// A004
|
||||
pub(crate) fn builtin_import_shadowing(checker: &mut Checker, alias: &Alias) {
|
||||
let name = alias.asname.as_ref().unwrap_or(&alias.name);
|
||||
if shadows_builtin(
|
||||
name.as_str(),
|
||||
&checker.settings.flake8_builtins.builtins_ignorelist,
|
||||
checker.source_type,
|
||||
) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
BuiltinImportShadowing {
|
||||
name: name.to_string(),
|
||||
},
|
||||
name.range,
|
||||
));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::ExprLambda;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::rules::flake8_builtins::helpers::shadows_builtin;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for lambda arguments that use the same names as Python builtins.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Reusing a builtin name for the name of a lambda argument increases the
|
||||
/// difficulty of reading and maintaining the code, and can cause
|
||||
/// non-obvious errors, as readers may mistake the variable for the
|
||||
/// builtin and vice versa.
|
||||
///
|
||||
/// Builtins can be marked as exceptions to this rule via the
|
||||
/// [`lint.flake8-builtins.builtins-ignorelist`] configuration option.
|
||||
///
|
||||
/// ## Options
|
||||
/// - `lint.flake8-builtins.builtins-ignorelist`
|
||||
#[violation]
|
||||
pub struct BuiltinLambdaArgumentShadowing {
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl Violation for BuiltinLambdaArgumentShadowing {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let BuiltinLambdaArgumentShadowing { name } = self;
|
||||
format!("Lambda argument `{name}` is shadowing a Python builtin")
|
||||
}
|
||||
}
|
||||
|
||||
/// A006
|
||||
pub(crate) fn builtin_lambda_argument_shadowing(checker: &mut Checker, lambda: &ExprLambda) {
|
||||
let Some(parameters) = lambda.parameters.as_ref() else {
|
||||
return;
|
||||
};
|
||||
for param in parameters.iter_non_variadic_params() {
|
||||
let name = ¶m.parameter.name;
|
||||
if shadows_builtin(
|
||||
name.as_ref(),
|
||||
&checker.settings.flake8_builtins.builtins_ignorelist,
|
||||
checker.source_type,
|
||||
) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
BuiltinLambdaArgumentShadowing {
|
||||
name: name.to_string(),
|
||||
},
|
||||
name.range(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
use std::path::Path;
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_stdlib::path::is_module_file;
|
||||
use ruff_python_stdlib::sys::is_known_standard_library;
|
||||
use ruff_text_size::TextRange;
|
||||
|
||||
use crate::settings::types::PythonVersion;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for modules that use the same names as Python builtin modules.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Reusing a builtin module name for the name of a module increases the
|
||||
/// difficulty of reading and maintaining the code, and can cause
|
||||
/// non-obvious errors, as readers may mistake the variable for the
|
||||
/// builtin and vice versa.
|
||||
///
|
||||
/// Builtin modules can be marked as exceptions to this rule via the
|
||||
/// [`lint.flake8-builtins.builtins-allowed-modules`] configuration option.
|
||||
///
|
||||
/// ## Options
|
||||
/// - `lint.flake8-builtins.builtins-allowed-modules`
|
||||
#[violation]
|
||||
pub struct BuiltinModuleShadowing {
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl Violation for BuiltinModuleShadowing {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let BuiltinModuleShadowing { name } = self;
|
||||
format!("Module `{name}` is shadowing a Python builtin module")
|
||||
}
|
||||
}
|
||||
|
||||
/// A005
|
||||
pub(crate) fn builtin_module_shadowing(
|
||||
path: &Path,
|
||||
package: Option<&Path>,
|
||||
allowed_modules: &[String],
|
||||
target_version: PythonVersion,
|
||||
) -> Option<Diagnostic> {
|
||||
if !path
|
||||
.extension()
|
||||
.is_some_and(|ext| ext == "py" || ext == "pyi")
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
if let Some(package) = package {
|
||||
let module_name = if is_module_file(path) {
|
||||
package.file_name().unwrap().to_string_lossy()
|
||||
} else {
|
||||
path.file_stem().unwrap().to_string_lossy()
|
||||
};
|
||||
|
||||
if is_known_standard_library(target_version.minor(), &module_name)
|
||||
&& allowed_modules
|
||||
.iter()
|
||||
.all(|allowed_module| allowed_module != &module_name)
|
||||
{
|
||||
return Some(Diagnostic::new(
|
||||
BuiltinModuleShadowing {
|
||||
name: module_name.to_string(),
|
||||
},
|
||||
TextRange::default(),
|
||||
));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
|
@ -1,15 +1,14 @@
|
|||
use ruff_text_size::TextRange;
|
||||
|
||||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_diagnostics::Violation;
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_text_size::TextRange;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::rules::flake8_builtins::helpers::shadows_builtin;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for variable (and function) assignments that use the same name
|
||||
/// as a builtin.
|
||||
/// Checks for variable (and function) assignments that use the same names
|
||||
/// as builtins.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Reusing a builtin name for the name of a variable increases the
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
pub(crate) use builtin_argument_shadowing::*;
|
||||
pub(crate) use builtin_attribute_shadowing::*;
|
||||
pub(crate) use builtin_import_shadowing::*;
|
||||
pub(crate) use builtin_lambda_argument_shadowing::*;
|
||||
pub(crate) use builtin_module_shadowing::*;
|
||||
pub(crate) use builtin_variable_shadowing::*;
|
||||
|
||||
mod builtin_argument_shadowing;
|
||||
mod builtin_attribute_shadowing;
|
||||
mod builtin_import_shadowing;
|
||||
mod builtin_lambda_argument_shadowing;
|
||||
mod builtin_module_shadowing;
|
||||
mod builtin_variable_shadowing;
|
||||
|
|
|
@ -7,6 +7,7 @@ use std::fmt::{Display, Formatter};
|
|||
#[derive(Debug, Clone, Default, CacheKey)]
|
||||
pub struct Settings {
|
||||
pub builtins_ignorelist: Vec<String>,
|
||||
pub builtins_allowed_modules: Vec<String>,
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
|
@ -15,7 +16,8 @@ impl Display for Settings {
|
|||
formatter = f,
|
||||
namespace = "linter.flake8_builtins",
|
||||
fields = [
|
||||
self.builtins_ignorelist | array
|
||||
self.builtins_allowed_modules | array,
|
||||
self.builtins_ignorelist | array,
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
|
||||
---
|
||||
A004.py:1:16: A004 Import `sum` is shadowing a Python builtin
|
||||
|
|
||||
1 | import some as sum
|
||||
| ^^^ A004
|
||||
2 | import float
|
||||
3 | from some import other as int
|
||||
|
|
||||
|
||||
A004.py:2:8: A004 Import `float` is shadowing a Python builtin
|
||||
|
|
||||
1 | import some as sum
|
||||
2 | import float
|
||||
| ^^^^^ A004
|
||||
3 | from some import other as int
|
||||
4 | from some import input, exec
|
||||
|
|
||||
|
||||
A004.py:3:27: A004 Import `int` is shadowing a Python builtin
|
||||
|
|
||||
1 | import some as sum
|
||||
2 | import float
|
||||
3 | from some import other as int
|
||||
| ^^^ A004
|
||||
4 | from some import input, exec
|
||||
5 | from directory import new as dir
|
||||
|
|
||||
|
||||
A004.py:4:18: A004 Import `input` is shadowing a Python builtin
|
||||
|
|
||||
2 | import float
|
||||
3 | from some import other as int
|
||||
4 | from some import input, exec
|
||||
| ^^^^^ A004
|
||||
5 | from directory import new as dir
|
||||
|
|
||||
|
||||
A004.py:4:25: A004 Import `exec` is shadowing a Python builtin
|
||||
|
|
||||
2 | import float
|
||||
3 | from some import other as int
|
||||
4 | from some import input, exec
|
||||
| ^^^^ A004
|
||||
5 | from directory import new as dir
|
||||
|
|
||||
|
||||
A004.py:5:30: A004 Import `dir` is shadowing a Python builtin
|
||||
|
|
||||
3 | from some import other as int
|
||||
4 | from some import input, exec
|
||||
5 | from directory import new as dir
|
||||
| ^^^ A004
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
|
||||
---
|
||||
A004.py:1:16: A004 Import `sum` is shadowing a Python builtin
|
||||
|
|
||||
1 | import some as sum
|
||||
| ^^^ A004
|
||||
2 | import float
|
||||
3 | from some import other as int
|
||||
|
|
||||
|
||||
A004.py:2:8: A004 Import `float` is shadowing a Python builtin
|
||||
|
|
||||
1 | import some as sum
|
||||
2 | import float
|
||||
| ^^^^^ A004
|
||||
3 | from some import other as int
|
||||
4 | from some import input, exec
|
||||
|
|
||||
|
||||
A004.py:3:27: A004 Import `int` is shadowing a Python builtin
|
||||
|
|
||||
1 | import some as sum
|
||||
2 | import float
|
||||
3 | from some import other as int
|
||||
| ^^^ A004
|
||||
4 | from some import input, exec
|
||||
5 | from directory import new as dir
|
||||
|
|
||||
|
||||
A004.py:4:18: A004 Import `input` is shadowing a Python builtin
|
||||
|
|
||||
2 | import float
|
||||
3 | from some import other as int
|
||||
4 | from some import input, exec
|
||||
| ^^^^^ A004
|
||||
5 | from directory import new as dir
|
||||
|
|
||||
|
||||
A004.py:4:25: A004 Import `exec` is shadowing a Python builtin
|
||||
|
|
||||
2 | import float
|
||||
3 | from some import other as int
|
||||
4 | from some import input, exec
|
||||
| ^^^^ A004
|
||||
5 | from directory import new as dir
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
|
||||
---
|
||||
__init__.py:1:1: A005 Module `logging` is shadowing a Python builtin module
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
|
||||
---
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
|
||||
---
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
|
||||
---
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
|
||||
---
|
||||
bisect.py:1:1: A005 Module `bisect` is shadowing a Python builtin module
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
|
||||
---
|
||||
bisect.py:1:1: A005 Module `bisect` is shadowing a Python builtin module
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
|
||||
---
|
||||
xml.py:1:1: A005 Module `xml` is shadowing a Python builtin module
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
|
||||
---
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
|
||||
---
|
||||
__init__.py:1:1: A005 Module `string` is shadowing a Python builtin module
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
|
||||
---
|
||||
__init__.py:1:1: A005 Module `string` is shadowing a Python builtin module
|
|
@ -0,0 +1,64 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
|
||||
---
|
||||
A006.py:1:8: A006 Lambda argument `print` is shadowing a Python builtin
|
||||
|
|
||||
1 | lambda print, copyright: print
|
||||
| ^^^^^ A006
|
||||
2 | lambda x, float, y: x + y
|
||||
3 | lambda min, max: min
|
||||
|
|
||||
|
||||
A006.py:1:15: A006 Lambda argument `copyright` is shadowing a Python builtin
|
||||
|
|
||||
1 | lambda print, copyright: print
|
||||
| ^^^^^^^^^ A006
|
||||
2 | lambda x, float, y: x + y
|
||||
3 | lambda min, max: min
|
||||
|
|
||||
|
||||
A006.py:2:11: A006 Lambda argument `float` is shadowing a Python builtin
|
||||
|
|
||||
1 | lambda print, copyright: print
|
||||
2 | lambda x, float, y: x + y
|
||||
| ^^^^^ A006
|
||||
3 | lambda min, max: min
|
||||
4 | lambda id: id
|
||||
|
|
||||
|
||||
A006.py:3:8: A006 Lambda argument `min` is shadowing a Python builtin
|
||||
|
|
||||
1 | lambda print, copyright: print
|
||||
2 | lambda x, float, y: x + y
|
||||
3 | lambda min, max: min
|
||||
| ^^^ A006
|
||||
4 | lambda id: id
|
||||
5 | lambda dir: dir
|
||||
|
|
||||
|
||||
A006.py:3:13: A006 Lambda argument `max` is shadowing a Python builtin
|
||||
|
|
||||
1 | lambda print, copyright: print
|
||||
2 | lambda x, float, y: x + y
|
||||
3 | lambda min, max: min
|
||||
| ^^^ A006
|
||||
4 | lambda id: id
|
||||
5 | lambda dir: dir
|
||||
|
|
||||
|
||||
A006.py:4:8: A006 Lambda argument `id` is shadowing a Python builtin
|
||||
|
|
||||
2 | lambda x, float, y: x + y
|
||||
3 | lambda min, max: min
|
||||
4 | lambda id: id
|
||||
| ^^ A006
|
||||
5 | lambda dir: dir
|
||||
|
|
||||
|
||||
A006.py:5:8: A006 Lambda argument `dir` is shadowing a Python builtin
|
||||
|
|
||||
3 | lambda min, max: min
|
||||
4 | lambda id: id
|
||||
5 | lambda dir: dir
|
||||
| ^^^ A006
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
|
||||
---
|
||||
A006.py:1:8: A006 Lambda argument `print` is shadowing a Python builtin
|
||||
|
|
||||
1 | lambda print, copyright: print
|
||||
| ^^^^^ A006
|
||||
2 | lambda x, float, y: x + y
|
||||
3 | lambda min, max: min
|
||||
|
|
||||
|
||||
A006.py:1:15: A006 Lambda argument `copyright` is shadowing a Python builtin
|
||||
|
|
||||
1 | lambda print, copyright: print
|
||||
| ^^^^^^^^^ A006
|
||||
2 | lambda x, float, y: x + y
|
||||
3 | lambda min, max: min
|
||||
|
|
||||
|
||||
A006.py:2:11: A006 Lambda argument `float` is shadowing a Python builtin
|
||||
|
|
||||
1 | lambda print, copyright: print
|
||||
2 | lambda x, float, y: x + y
|
||||
| ^^^^^ A006
|
||||
3 | lambda min, max: min
|
||||
4 | lambda id: id
|
||||
|
|
||||
|
||||
A006.py:3:8: A006 Lambda argument `min` is shadowing a Python builtin
|
||||
|
|
||||
1 | lambda print, copyright: print
|
||||
2 | lambda x, float, y: x + y
|
||||
3 | lambda min, max: min
|
||||
| ^^^ A006
|
||||
4 | lambda id: id
|
||||
5 | lambda dir: dir
|
||||
|
|
||||
|
||||
A006.py:3:13: A006 Lambda argument `max` is shadowing a Python builtin
|
||||
|
|
||||
1 | lambda print, copyright: print
|
||||
2 | lambda x, float, y: x + y
|
||||
3 | lambda min, max: min
|
||||
| ^^^ A006
|
||||
4 | lambda id: id
|
||||
5 | lambda dir: dir
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::path::Path;
|
|||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_stdlib::identifiers::{is_migration_name, is_module_name};
|
||||
use ruff_python_stdlib::path::is_module_file;
|
||||
use ruff_text_size::TextRange;
|
||||
|
||||
use crate::rules::pep8_naming::settings::IgnoreNames;
|
||||
|
@ -92,16 +93,6 @@ pub(crate) fn invalid_module_name(
|
|||
None
|
||||
}
|
||||
|
||||
/// Return `true` if a [`Path`] should use the name of its parent directory as its module name.
|
||||
fn is_module_file(path: &Path) -> bool {
|
||||
path.file_name().is_some_and(|file_name| {
|
||||
file_name == "__init__.py"
|
||||
|| file_name == "__init__.pyi"
|
||||
|| file_name == "__main__.py"
|
||||
|| file_name == "__main__.pyi"
|
||||
})
|
||||
}
|
||||
|
||||
/// Return `true` if a [`Path`] refers to a migration file.
|
||||
fn is_migration_file(path: &Path) -> bool {
|
||||
path.parent()
|
||||
|
|
|
@ -16,6 +16,16 @@ pub fn is_jupyter_notebook(path: &Path) -> bool {
|
|||
path.extension().is_some_and(|ext| ext == "ipynb")
|
||||
}
|
||||
|
||||
/// Return `true` if a [`Path`] should use the name of its parent directory as its module name.
|
||||
pub fn is_module_file(path: &Path) -> bool {
|
||||
path.file_name().is_some_and(|file_name| {
|
||||
file_name == "__init__.py"
|
||||
|| file_name == "__init__.pyi"
|
||||
|| file_name == "__main__.py"
|
||||
|| file_name == "__main__.pyi"
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::Path;
|
||||
|
|
|
@ -1104,12 +1104,20 @@ pub struct Flake8BuiltinsOptions {
|
|||
)]
|
||||
/// Ignore list of builtins.
|
||||
pub builtins_ignorelist: Option<Vec<String>>,
|
||||
#[option(
|
||||
default = r#"[]"#,
|
||||
value_type = "list[str]",
|
||||
example = "builtins-allowed-modules = [\"id\"]"
|
||||
)]
|
||||
/// List of builtin module names to allow.
|
||||
pub builtins_allowed_modules: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
impl Flake8BuiltinsOptions {
|
||||
pub fn into_settings(self) -> ruff_linter::rules::flake8_builtins::settings::Settings {
|
||||
ruff_linter::rules::flake8_builtins::settings::Settings {
|
||||
builtins_ignorelist: self.builtins_ignorelist.unwrap_or_default(),
|
||||
builtins_allowed_modules: self.builtins_allowed_modules.unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
13
ruff.schema.json
generated
13
ruff.schema.json
generated
|
@ -933,6 +933,16 @@
|
|||
"Flake8BuiltinsOptions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"builtins-allowed-modules": {
|
||||
"description": "List of builtin module names to allow.",
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"builtins-ignorelist": {
|
||||
"description": "Ignore list of builtins.",
|
||||
"type": [
|
||||
|
@ -2669,6 +2679,9 @@
|
|||
"A001",
|
||||
"A002",
|
||||
"A003",
|
||||
"A004",
|
||||
"A005",
|
||||
"A006",
|
||||
"AIR",
|
||||
"AIR0",
|
||||
"AIR00",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue