mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-03 07:04:53 +00:00
[pycodestyle] Exempt sys.path += ...
calls (E402) (#15980)
## Summary The PR addresses issue #15886 .
This commit is contained in:
parent
d0555f7b5c
commit
24bab7e82e
4 changed files with 40 additions and 25 deletions
7
crates/ruff_linter/resources/test/fixtures/pycodestyle/E402_4.py
vendored
Normal file
7
crates/ruff_linter/resources/test/fixtures/pycodestyle/E402_4.py
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path += [os.path.dirname(__file__)]
|
||||||
|
sys.path += ["../"]
|
||||||
|
|
||||||
|
from package import module
|
|
@ -44,6 +44,7 @@ mod tests {
|
||||||
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402_1.py"))]
|
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402_1.py"))]
|
||||||
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402_2.py"))]
|
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402_2.py"))]
|
||||||
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402_3.py"))]
|
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402_3.py"))]
|
||||||
|
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402_4.py"))]
|
||||||
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402.ipynb"))]
|
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402.ipynb"))]
|
||||||
#[test_case(Rule::MultipleImportsOnOneLine, Path::new("E40.py"))]
|
#[test_case(Rule::MultipleImportsOnOneLine, Path::new("E40.py"))]
|
||||||
#[test_case(Rule::MultipleStatementsOnOneLineColon, Path::new("E70.py"))]
|
#[test_case(Rule::MultipleStatementsOnOneLineColon, Path::new("E70.py"))]
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/pycodestyle/mod.rs
|
||||||
|
---
|
|
@ -8,33 +8,37 @@ use crate::SemanticModel;
|
||||||
/// import sys
|
/// import sys
|
||||||
///
|
///
|
||||||
/// sys.path.append("../")
|
/// sys.path.append("../")
|
||||||
|
/// sys.path += ["../"]
|
||||||
/// ```
|
/// ```
|
||||||
pub fn is_sys_path_modification(stmt: &Stmt, semantic: &SemanticModel) -> bool {
|
pub fn is_sys_path_modification(stmt: &Stmt, semantic: &SemanticModel) -> bool {
|
||||||
let Stmt::Expr(ast::StmtExpr { value, range: _ }) = stmt else {
|
match stmt {
|
||||||
return false;
|
Stmt::Expr(ast::StmtExpr { value, range: _ }) => match value.as_ref() {
|
||||||
};
|
Expr::Call(ast::ExprCall { func, .. }) => semantic
|
||||||
let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else {
|
.resolve_qualified_name(func.as_ref())
|
||||||
return false;
|
.is_some_and(|qualified_name| {
|
||||||
};
|
matches!(
|
||||||
semantic
|
qualified_name.segments(),
|
||||||
.resolve_qualified_name(func.as_ref())
|
[
|
||||||
.is_some_and(|qualified_name| {
|
"sys",
|
||||||
matches!(
|
"path",
|
||||||
qualified_name.segments(),
|
"append"
|
||||||
[
|
| "insert"
|
||||||
"sys",
|
| "extend"
|
||||||
"path",
|
| "remove"
|
||||||
"append"
|
| "pop"
|
||||||
| "insert"
|
| "clear"
|
||||||
| "extend"
|
| "reverse"
|
||||||
| "remove"
|
| "sort"
|
||||||
| "pop"
|
]
|
||||||
| "clear"
|
)
|
||||||
| "reverse"
|
}),
|
||||||
| "sort"
|
_ => false,
|
||||||
]
|
},
|
||||||
)
|
Stmt::AugAssign(ast::StmtAugAssign { target, .. }) => semantic
|
||||||
})
|
.resolve_qualified_name(map_subscript(target))
|
||||||
|
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["sys", "path"])),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if a [`Stmt`] is an `os.environ` modification, as in:
|
/// Returns `true` if a [`Stmt`] is an `os.environ` modification, as in:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue