mirror of https://github.com/astral-sh/ruff
Exempt unittest context methods for SIM115 rule (#16439)
This commit is contained in:
parent
9bb63495dd
commit
5ca6cc2cc8
|
|
@ -264,3 +264,22 @@ def func(filepath, encoding):
|
||||||
# OK
|
# OK
|
||||||
def func(filepath, encoding):
|
def func(filepath, encoding):
|
||||||
return f(open(filepath, mode="rt", encoding=encoding))
|
return f(open(filepath, mode="rt", encoding=encoding))
|
||||||
|
|
||||||
|
|
||||||
|
from unittest import IsolatedAsyncioTestCase, TestCase
|
||||||
|
|
||||||
|
# OK
|
||||||
|
class ExampleClassTests(TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.enterClassContext(open("filename"))
|
||||||
|
|
||||||
|
# OK
|
||||||
|
class ExampleAsyncTests(IsolatedAsyncioTestCase):
|
||||||
|
async def test_something(self):
|
||||||
|
await self.enterAsyncContext(open("filename"))
|
||||||
|
|
||||||
|
# OK
|
||||||
|
class ExampleTests(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.enterContext(open("filename"))
|
||||||
|
|
@ -114,6 +114,28 @@ fn match_exit_stack(semantic: &SemanticModel) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return `true` if the current expression is nested in a call to one of the
|
||||||
|
/// unittest context manager methods: `cls.enterClassContext()`,
|
||||||
|
/// `self.enterContext()`, or `self.enterAsyncContext()`.
|
||||||
|
fn match_unittest_context_methods(semantic: &SemanticModel) -> bool {
|
||||||
|
let Some(expr) = semantic.current_expression_parent() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let Expr::Call(ast::ExprCall { func, .. }) = expr else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let Expr::Attribute(ast::ExprAttribute { attr, value, .. }) = func.as_ref() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
matches!(
|
||||||
|
(id.as_str(), attr.as_str()),
|
||||||
|
("cls", "enterClassContext") | ("self", "enterContext" | "enterAsyncContext")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Return `true` if the expression is a call to `open()`,
|
/// Return `true` if the expression is a call to `open()`,
|
||||||
/// or a call to some other standard-library function that opens a file.
|
/// or a call to some other standard-library function that opens a file.
|
||||||
fn is_open_call(semantic: &SemanticModel, call: &ast::ExprCall) -> bool {
|
fn is_open_call(semantic: &SemanticModel, call: &ast::ExprCall) -> bool {
|
||||||
|
|
@ -229,6 +251,11 @@ pub(crate) fn open_file_with_context_handler(checker: &Checker, call: &ast::Expr
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ex) `self.enterContext(open("foo.txt"))`
|
||||||
|
if match_unittest_context_methods(semantic) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Ex) `def __enter__(self): ...`
|
// Ex) `def __enter__(self): ...`
|
||||||
if let ScopeKind::Function(ast::StmtFunctionDef { name, .. }) =
|
if let ScopeKind::Function(ast::StmtFunctionDef { name, .. }) =
|
||||||
&checker.semantic().current_scope().kind
|
&checker.semantic().current_scope().kind
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue