Exempt unittest context methods for SIM115 rule (#16439)

This commit is contained in:
Adam Johnson 2025-02-28 16:29:50 +00:00 committed by GitHub
parent 9bb63495dd
commit 5ca6cc2cc8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 46 additions and 0 deletions

View File

@ -264,3 +264,22 @@ def func(filepath, encoding):
# OK
def func(filepath, 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"))

View File

@ -114,6 +114,28 @@ fn match_exit_stack(semantic: &SemanticModel) -> bool {
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()`,
/// or a call to some other standard-library function that opens a file.
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;
}
// Ex) `self.enterContext(open("foo.txt"))`
if match_unittest_context_methods(semantic) {
return;
}
// Ex) `def __enter__(self): ...`
if let ScopeKind::Function(ast::StmtFunctionDef { name, .. }) =
&checker.semantic().current_scope().kind