Skip to content

Commit

Permalink
[pylint] Implement import-self (W0406) (#4154)
Browse files Browse the repository at this point in the history
  • Loading branch information
chanman3388 authored May 4, 2023
1 parent 93cfce6 commit c2921e9
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 0 deletions.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import import_self.module
from import_self import module
from . import module
18 changes: 18 additions & 0 deletions crates/ruff/src/checkers/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,13 @@ where
if self.settings.rules.enabled(Rule::ManualFromImport) {
pylint::rules::manual_from_import(self, stmt, alias, names);
}
if self.settings.rules.enabled(Rule::ImportSelf) {
if let Some(diagnostic) =
pylint::rules::import_self(alias, self.module_path.as_deref())
{
self.diagnostics.push(diagnostic);
}
}

if let Some(asname) = &alias.node.asname {
let name = alias.node.name.split('.').last().unwrap();
Expand Down Expand Up @@ -1477,6 +1484,17 @@ where
}
}

if self.settings.rules.enabled(Rule::ImportSelf) {
if let Some(diagnostic) = pylint::rules::import_from_self(
*level,
module.as_deref(),
names,
self.module_path.as_deref(),
) {
self.diagnostics.push(diagnostic);
}
}

if self.settings.rules.enabled(Rule::BannedImportFrom) {
if let Some(diagnostic) = flake8_import_conventions::rules::banned_import_from(
stmt,
Expand Down
1 change: 1 addition & 0 deletions crates/ruff/src/codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<Rule> {
(Pylint, "R5501") => Rule::CollapsibleElseIf,
(Pylint, "W0120") => Rule::UselessElseOnLoop,
(Pylint, "W0129") => Rule::AssertOnStringLiteral,
(Pylint, "W0406") => Rule::ImportSelf,
(Pylint, "W0602") => Rule::GlobalVariableNotAssigned,
(Pylint, "W0603") => Rule::GlobalStatement,
(Pylint, "W0711") => Rule::BinaryOpException,
Expand Down
1 change: 1 addition & 0 deletions crates/ruff/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ ruff_macros::register_rules!(
rules::pylint::rules::BadStringFormatType,
rules::pylint::rules::BidirectionalUnicode,
rules::pylint::rules::BinaryOpException,
rules::pylint::rules::ImportSelf,
rules::pylint::rules::InvalidCharacterBackspace,
rules::pylint::rules::InvalidCharacterSub,
rules::pylint::rules::InvalidCharacterEsc,
Expand Down
1 change: 1 addition & 0 deletions crates/ruff/src/rules/pylint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ mod tests {
#[test_case(Rule::ContinueInFinally, Path::new("continue_in_finally.py"); "PLE0116")]
#[test_case(Rule::GlobalStatement, Path::new("global_statement.py"); "PLW0603")]
#[test_case(Rule::GlobalVariableNotAssigned, Path::new("global_variable_not_assigned.py"); "PLW0602")]
#[test_case(Rule::ImportSelf, Path::new("import_self/module.py"); "PLW0406")]
#[test_case(Rule::InvalidAllFormat, Path::new("invalid_all_format.py"); "PLE0605")]
#[test_case(Rule::InvalidAllObject, Path::new("invalid_all_object.py"); "PLE0604")]
#[test_case(Rule::InvalidCharacterBackspace, Path::new("invalid_characters.py"); "PLE2510")]
Expand Down
70 changes: 70 additions & 0 deletions crates/ruff/src/rules/pylint/rules/import_self.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use rustpython_parser::ast::Alias;

use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::helpers::resolve_imported_module_path;

#[violation]
pub struct ImportSelf {
pub name: String,
}

impl Violation for ImportSelf {
#[derive_message_formats]
fn message(&self) -> String {
let Self { name } = self;
format!("Module `{name}` imports itself")
}
}

/// PLW0406
pub fn import_self(alias: &Alias, module_path: Option<&[String]>) -> Option<Diagnostic> {
let Some(module_path) = module_path else {
return None;
};

if alias.node.name.split('.').eq(module_path) {
return Some(Diagnostic::new(
ImportSelf {
name: alias.node.name.clone(),
},
alias.range(),
));
}

None
}

/// PLW0406
pub fn import_from_self(
level: Option<usize>,
module: Option<&str>,
names: &[Alias],
module_path: Option<&[String]>,
) -> Option<Diagnostic> {
let Some(module_path) = module_path else {
return None;
};
let Some(imported_module_path) = resolve_imported_module_path(level, module, Some(module_path)) else {
return None;
};

if imported_module_path
.split('.')
.eq(&module_path[..module_path.len() - 1])
{
if let Some(alias) = names
.iter()
.find(|alias| alias.node.name == module_path[module_path.len() - 1])
{
return Some(Diagnostic::new(
ImportSelf {
name: format!("{}.{}", imported_module_path, alias.node.name),
},
alias.range(),
));
}
}

None
}
2 changes: 2 additions & 0 deletions crates/ruff/src/rules/pylint/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub use comparison_of_constant::{comparison_of_constant, ComparisonOfConstant};
pub use continue_in_finally::{continue_in_finally, ContinueInFinally};
pub use global_statement::{global_statement, GlobalStatement};
pub use global_variable_not_assigned::GlobalVariableNotAssigned;
pub use import_self::{import_from_self, import_self, ImportSelf};
pub use invalid_all_format::{invalid_all_format, InvalidAllFormat};
pub use invalid_all_object::{invalid_all_object, InvalidAllObject};
pub use invalid_envvar_default::{invalid_envvar_default, InvalidEnvvarDefault};
Expand Down Expand Up @@ -57,6 +58,7 @@ mod comparison_of_constant;
mod continue_in_finally;
mod global_statement;
mod global_variable_not_assigned;
mod import_self;
mod invalid_all_format;
mod invalid_all_object;
mod invalid_envvar_default;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
source: crates/ruff/src/rules/pylint/mod.rs
---
module.py:1:8: PLW0406 Module `import_self.module` imports itself
|
1 | import import_self.module
| ^^^^^^^^^^^^^^^^^^ PLW0406
2 | from import_self import module
3 | from . import module
|

module.py:2:25: PLW0406 Module `import_self.module` imports itself
|
2 | import import_self.module
3 | from import_self import module
| ^^^^^^ PLW0406
4 | from . import module
|

module.py:3:15: PLW0406 Module `import_self.module` imports itself
|
3 | import import_self.module
4 | from import_self import module
5 | from . import module
| ^^^^^^ PLW0406
|


3 changes: 3 additions & 0 deletions ruff.schema.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c2921e9

Please sign in to comment.