mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 18:58:04 +00:00
[pycodestyle] Exempt site.addsitedir(...)
calls (E402) (#16251)
This commit is contained in:
parent
3ea32e2cdd
commit
3032867603
5 changed files with 45 additions and 1 deletions
19
crates/ruff_linter/resources/test/fixtures/pycodestyle/E402_5.py
vendored
Normal file
19
crates/ruff_linter/resources/test/fixtures/pycodestyle/E402_5.py
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Issue: https://github.com/astral-sh/ruff/issues/16247#event-16362806498
|
||||
|
||||
import os
|
||||
import site
|
||||
import sys
|
||||
import sysconfig
|
||||
|
||||
site.addsitedir(
|
||||
os.path.join(
|
||||
os.path.dirname(os.path.dirname(__file__)),
|
||||
sysconfig.get_path("purelib", vars={"base": "."}),
|
||||
)
|
||||
)
|
||||
|
||||
from mypkg.__main__ import main
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.argv[0] = sys.argv[0].removesuffix(".py")
|
||||
sys.exit(main())
|
|
@ -556,7 +556,8 @@ impl<'a> Visitor<'a> for Checker<'a> {
|
|||
|| imports::is_matplotlib_activation(stmt, self.semantic())
|
||||
|| imports::is_sys_path_modification(stmt, self.semantic())
|
||||
|| imports::is_os_environ_modification(stmt, self.semantic())
|
||||
|| imports::is_pytest_importorskip(stmt, self.semantic()))
|
||||
|| imports::is_pytest_importorskip(stmt, self.semantic())
|
||||
|| imports::is_site_sys_path_modification(stmt, self.semantic()))
|
||||
{
|
||||
self.semantic.flags |= SemanticModelFlags::IMPORT_BOUNDARY;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ mod tests {
|
|||
#[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_4.py"))]
|
||||
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402_5.py"))]
|
||||
#[test_case(Rule::ModuleImportNotAtTopOfFile, Path::new("E402.ipynb"))]
|
||||
#[test_case(Rule::MultipleImportsOnOneLine, Path::new("E40.py"))]
|
||||
#[test_case(Rule::MultipleStatementsOnOneLineColon, Path::new("E70.py"))]
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pycodestyle/mod.rs
|
||||
---
|
|
@ -127,3 +127,23 @@ pub fn is_pytest_importorskip(stmt: &Stmt, semantic: &SemanticModel) -> bool {
|
|||
matches!(qualified_name.segments(), ["pytest", "importorskip"])
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns `true` if a [`Stmt`] is a dynamic modification of the Python
|
||||
/// module search path, e.g.,
|
||||
/// ```python
|
||||
/// import site
|
||||
///
|
||||
/// site.addsitedir(...)
|
||||
/// ```
|
||||
pub fn is_site_sys_path_modification(stmt: &Stmt, semantic: &SemanticModel) -> bool {
|
||||
if let Stmt::Expr(ast::StmtExpr { value, .. }) = stmt {
|
||||
if let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() {
|
||||
return semantic
|
||||
.resolve_qualified_name(func.as_ref())
|
||||
.is_some_and(|qualified_name| {
|
||||
matches!(qualified_name.segments(), ["site", "addsitedir"])
|
||||
});
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue