mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 13:25:17 +00:00
[flake8-simplify
] Extend open-file-with-context-handler to work with other standard-library IO modules (SIM115
) (#12959)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
This commit is contained in:
parent
d1d067896c
commit
d37e2e5d33
6 changed files with 602 additions and 22 deletions
|
@ -47,7 +47,6 @@ with contextlib.ExitStack() as exit_stack:
|
||||||
open("filename", "w").close()
|
open("filename", "w").close()
|
||||||
pathlib.Path("filename").open("w").close()
|
pathlib.Path("filename").open("w").close()
|
||||||
|
|
||||||
|
|
||||||
# OK (custom context manager)
|
# OK (custom context manager)
|
||||||
class MyFile:
|
class MyFile:
|
||||||
def __init__(self, filename: str):
|
def __init__(self, filename: str):
|
||||||
|
@ -58,3 +57,189 @@ class MyFile:
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
self.file.close()
|
self.file.close()
|
||||||
|
|
||||||
|
|
||||||
|
import tempfile
|
||||||
|
import tarfile
|
||||||
|
from tarfile import TarFile
|
||||||
|
import zipfile
|
||||||
|
import io
|
||||||
|
import codecs
|
||||||
|
import bz2
|
||||||
|
import gzip
|
||||||
|
import dbm
|
||||||
|
import dbm.gnu
|
||||||
|
import dbm.ndbm
|
||||||
|
import dbm.dumb
|
||||||
|
import lzma
|
||||||
|
import shelve
|
||||||
|
import tokenize
|
||||||
|
import wave
|
||||||
|
import fileinput
|
||||||
|
|
||||||
|
f = tempfile.NamedTemporaryFile()
|
||||||
|
f = tempfile.TemporaryFile()
|
||||||
|
f = tempfile.SpooledTemporaryFile()
|
||||||
|
f = tarfile.open("foo.tar")
|
||||||
|
f = TarFile("foo.tar").open()
|
||||||
|
f = tarfile.TarFile("foo.tar").open()
|
||||||
|
f = tarfile.TarFile().open()
|
||||||
|
f = zipfile.ZipFile("foo.zip").open("foo.txt")
|
||||||
|
f = io.open("foo.txt")
|
||||||
|
f = io.open_code("foo.txt")
|
||||||
|
f = codecs.open("foo.txt")
|
||||||
|
f = bz2.open("foo.txt")
|
||||||
|
f = gzip.open("foo.txt")
|
||||||
|
f = dbm.open("foo.db")
|
||||||
|
f = dbm.gnu.open("foo.db")
|
||||||
|
f = dbm.ndbm.open("foo.db")
|
||||||
|
f = dbm.dumb.open("foo.db")
|
||||||
|
f = lzma.open("foo.xz")
|
||||||
|
f = lzma.LZMAFile("foo.xz")
|
||||||
|
f = shelve.open("foo.db")
|
||||||
|
f = tokenize.open("foo.py")
|
||||||
|
f = wave.open("foo.wav")
|
||||||
|
f = tarfile.TarFile.taropen("foo.tar")
|
||||||
|
f = fileinput.input("foo.txt")
|
||||||
|
f = fileinput.FileInput("foo.txt")
|
||||||
|
|
||||||
|
with contextlib.suppress(Exception):
|
||||||
|
# The following line is for example's sake.
|
||||||
|
# For some f's above, this would raise an error (since it'd be f.readline() etc.)
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with tempfile.TemporaryFile() as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with tarfile.open("foo.tar") as f:
|
||||||
|
data = f.add("foo.txt")
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with tarfile.TarFile("foo.tar") as f:
|
||||||
|
data = f.add("foo.txt")
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with tarfile.TarFile("foo.tar").open() as f:
|
||||||
|
data = f.add("foo.txt")
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with zipfile.ZipFile("foo.zip") as f:
|
||||||
|
data = f.read("foo.txt")
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with zipfile.ZipFile("foo.zip").open("foo.txt") as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with zipfile.ZipFile("foo.zip") as zf:
|
||||||
|
with zf.open("foo.txt") as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with io.open("foo.txt") as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with io.open_code("foo.txt") as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with codecs.open("foo.txt") as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with bz2.open("foo.txt") as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with gzip.open("foo.txt") as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with dbm.open("foo.db") as f:
|
||||||
|
data = f.get("foo")
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with dbm.gnu.open("foo.db") as f:
|
||||||
|
data = f.get("foo")
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with dbm.ndbm.open("foo.db") as f:
|
||||||
|
data = f.get("foo")
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with dbm.dumb.open("foo.db") as f:
|
||||||
|
data = f.get("foo")
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with lzma.open("foo.xz") as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with lzma.LZMAFile("foo.xz") as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with shelve.open("foo.db") as f:
|
||||||
|
data = f["foo"]
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with tokenize.open("foo.py") as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with wave.open("foo.wav") as f:
|
||||||
|
data = f.readframes(1024)
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with tarfile.TarFile.taropen("foo.tar") as f:
|
||||||
|
data = f.add("foo.txt")
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with fileinput.input("foo.txt") as f:
|
||||||
|
data = f.readline()
|
||||||
|
|
||||||
|
# OK
|
||||||
|
with fileinput.FileInput("foo.txt") as f:
|
||||||
|
data = f.readline()
|
||||||
|
|
||||||
|
# OK (quick one-liner to clear file contents)
|
||||||
|
tempfile.NamedTemporaryFile().close()
|
||||||
|
tempfile.TemporaryFile().close()
|
||||||
|
tempfile.SpooledTemporaryFile().close()
|
||||||
|
tarfile.open("foo.tar").close()
|
||||||
|
tarfile.TarFile("foo.tar").close()
|
||||||
|
tarfile.TarFile("foo.tar").open().close()
|
||||||
|
tarfile.TarFile.open("foo.tar").close()
|
||||||
|
zipfile.ZipFile("foo.zip").close()
|
||||||
|
zipfile.ZipFile("foo.zip").open("foo.txt").close()
|
||||||
|
io.open("foo.txt").close()
|
||||||
|
io.open_code("foo.txt").close()
|
||||||
|
codecs.open("foo.txt").close()
|
||||||
|
bz2.open("foo.txt").close()
|
||||||
|
gzip.open("foo.txt").close()
|
||||||
|
dbm.open("foo.db").close()
|
||||||
|
dbm.gnu.open("foo.db").close()
|
||||||
|
dbm.ndbm.open("foo.db").close()
|
||||||
|
dbm.dumb.open("foo.db").close()
|
||||||
|
lzma.open("foo.xz").close()
|
||||||
|
lzma.LZMAFile("foo.xz").close()
|
||||||
|
shelve.open("foo.db").close()
|
||||||
|
tokenize.open("foo.py").close()
|
||||||
|
wave.open("foo.wav").close()
|
||||||
|
tarfile.TarFile.taropen("foo.tar").close()
|
||||||
|
fileinput.input("foo.txt").close()
|
||||||
|
fileinput.FileInput("foo.txt").close()
|
||||||
|
|
||||||
|
def aliased():
|
||||||
|
from shelve import open as open_shelf
|
||||||
|
x = open_shelf("foo.dbm")
|
||||||
|
x.close()
|
||||||
|
|
||||||
|
from tarfile import TarFile as TF
|
||||||
|
f = TF("foo").open()
|
||||||
|
f.close()
|
||||||
|
|
|
@ -883,7 +883,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
||||||
flake8_simplify::rules::use_capital_environment_variables(checker, expr);
|
flake8_simplify::rules::use_capital_environment_variables(checker, expr);
|
||||||
}
|
}
|
||||||
if checker.enabled(Rule::OpenFileWithContextHandler) {
|
if checker.enabled(Rule::OpenFileWithContextHandler) {
|
||||||
flake8_simplify::rules::open_file_with_context_handler(checker, func);
|
flake8_simplify::rules::open_file_with_context_handler(checker, call);
|
||||||
}
|
}
|
||||||
if checker.enabled(Rule::DictGetWithNoneDefault) {
|
if checker.enabled(Rule::DictGetWithNoneDefault) {
|
||||||
flake8_simplify::rules::dict_get_with_none_default(checker, expr);
|
flake8_simplify::rules::dict_get_with_none_default(checker, expr);
|
||||||
|
|
|
@ -58,6 +58,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test_case(Rule::IfElseBlockInsteadOfIfExp, Path::new("SIM108.py"))]
|
#[test_case(Rule::IfElseBlockInsteadOfIfExp, Path::new("SIM108.py"))]
|
||||||
|
#[test_case(Rule::OpenFileWithContextHandler, Path::new("SIM115.py"))]
|
||||||
fn preview_rules(rule_code: Rule, path: &Path) -> Result<()> {
|
fn preview_rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||||
let snapshot = format!(
|
let snapshot = format!(
|
||||||
"preview__{}_{}",
|
"preview__{}_{}",
|
||||||
|
|
|
@ -8,14 +8,20 @@ use ruff_text_size::Ranged;
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
||||||
/// ## What it does
|
/// ## What it does
|
||||||
/// Checks for uses of the builtin `open()` function without an associated context
|
/// Checks for cases where files are opened (e.g., using the builtin `open()` function)
|
||||||
/// manager.
|
/// without using a context manager.
|
||||||
///
|
///
|
||||||
/// ## Why is this bad?
|
/// ## Why is this bad?
|
||||||
/// If a file is opened without a context manager, it is not guaranteed that
|
/// If a file is opened without a context manager, it is not guaranteed that
|
||||||
/// the file will be closed (e.g., if an exception is raised), which can cause
|
/// the file will be closed (e.g., if an exception is raised), which can cause
|
||||||
/// resource leaks.
|
/// resource leaks.
|
||||||
///
|
///
|
||||||
|
/// ## Preview-mode behavior
|
||||||
|
/// If [preview] mode is enabled, this rule will detect a wide array of IO calls where
|
||||||
|
/// context managers could be used, such as `tempfile.TemporaryFile()` or
|
||||||
|
/// `tarfile.TarFile(...).gzopen()`. If preview mode is not enabled, only `open()`,
|
||||||
|
/// `builtins.open()` and `pathlib.Path(...).open()` are detected.
|
||||||
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
/// ```python
|
/// ```python
|
||||||
/// file = open("foo.txt")
|
/// file = open("foo.txt")
|
||||||
|
@ -37,7 +43,7 @@ pub struct OpenFileWithContextHandler;
|
||||||
impl Violation for OpenFileWithContextHandler {
|
impl Violation for OpenFileWithContextHandler {
|
||||||
#[derive_message_formats]
|
#[derive_message_formats]
|
||||||
fn message(&self) -> String {
|
fn message(&self) -> String {
|
||||||
format!("Use context handler for opening files")
|
format!("Use a context manager for opening files")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,14 +119,14 @@ fn match_exit_stack(semantic: &SemanticModel) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` if `func` is the builtin `open` or `pathlib.Path(...).open`.
|
/// Return `true` if `func` is the builtin `open` or `pathlib.Path(...).open`.
|
||||||
fn is_open(semantic: &SemanticModel, func: &Expr) -> bool {
|
fn is_open(semantic: &SemanticModel, call: &ast::ExprCall) -> bool {
|
||||||
// Ex) `open(...)`
|
// Ex) `open(...)`
|
||||||
if semantic.match_builtin_expr(func, "open") {
|
if semantic.match_builtin_expr(&call.func, "open") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ex) `pathlib.Path(...).open()`
|
// Ex) `pathlib.Path(...).open()`
|
||||||
let Expr::Attribute(ast::ExprAttribute { attr, value, .. }) = func else {
|
let Expr::Attribute(ast::ExprAttribute { attr, value, .. }) = &*call.func else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -140,6 +146,63 @@ fn is_open(semantic: &SemanticModel, func: &Expr) -> bool {
|
||||||
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["pathlib", "Path"]))
|
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["pathlib", "Path"]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return `true` if the expression is an `open` call or temporary file constructor.
|
||||||
|
fn is_open_preview(semantic: &SemanticModel, call: &ast::ExprCall) -> bool {
|
||||||
|
let func = &*call.func;
|
||||||
|
|
||||||
|
// Ex) `open(...)`
|
||||||
|
if let Some(qualified_name) = semantic.resolve_qualified_name(func) {
|
||||||
|
return matches!(
|
||||||
|
qualified_name.segments(),
|
||||||
|
[
|
||||||
|
"" | "builtins"
|
||||||
|
| "bz2"
|
||||||
|
| "codecs"
|
||||||
|
| "dbm"
|
||||||
|
| "gzip"
|
||||||
|
| "tarfile"
|
||||||
|
| "shelve"
|
||||||
|
| "tokenize"
|
||||||
|
| "wave",
|
||||||
|
"open"
|
||||||
|
] | ["dbm", "gnu" | "ndbm" | "dumb", "open"]
|
||||||
|
| ["fileinput", "FileInput" | "input"]
|
||||||
|
| ["io", "open" | "open_code"]
|
||||||
|
| ["lzma", "LZMAFile" | "open"]
|
||||||
|
| ["tarfile", "TarFile", "taropen"]
|
||||||
|
| [
|
||||||
|
"tempfile",
|
||||||
|
"TemporaryFile" | "NamedTemporaryFile" | "SpooledTemporaryFile"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ex) `pathlib.Path(...).open()`
|
||||||
|
let Expr::Attribute(ast::ExprAttribute { attr, value, .. }) = func else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Expr::Call(ast::ExprCall { func, .. }) = &**value else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// E.g. for `pathlib.Path(...).open()`, `qualified_name_of_instance.segments() == ["pathlib", "Path"]`
|
||||||
|
let Some(qualified_name_of_instance) = semantic.resolve_qualified_name(func) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
matches!(
|
||||||
|
(qualified_name_of_instance.segments(), &**attr),
|
||||||
|
(
|
||||||
|
["pathlib", "Path"] | ["zipfile", "ZipFile"] | ["lzma", "LZMAFile"],
|
||||||
|
"open"
|
||||||
|
) | (
|
||||||
|
["tarfile", "TarFile"],
|
||||||
|
"open" | "taropen" | "gzopen" | "bz2open" | "xzopen"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Return `true` if the current expression is followed by a `close` call.
|
/// Return `true` if the current expression is followed by a `close` call.
|
||||||
fn is_closed(semantic: &SemanticModel) -> bool {
|
fn is_closed(semantic: &SemanticModel) -> bool {
|
||||||
let Some(expr) = semantic.current_expression_grandparent() else {
|
let Some(expr) = semantic.current_expression_grandparent() else {
|
||||||
|
@ -165,11 +228,17 @@ fn is_closed(semantic: &SemanticModel) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SIM115
|
/// SIM115
|
||||||
pub(crate) fn open_file_with_context_handler(checker: &mut Checker, func: &Expr) {
|
pub(crate) fn open_file_with_context_handler(checker: &mut Checker, call: &ast::ExprCall) {
|
||||||
let semantic = checker.semantic();
|
let semantic = checker.semantic();
|
||||||
|
|
||||||
if !is_open(semantic, func) {
|
if checker.settings.preview.is_disabled() {
|
||||||
return;
|
if !is_open(semantic, call) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !is_open_preview(semantic, call) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ex) `open("foo.txt").close()`
|
// Ex) `open("foo.txt").close()`
|
||||||
|
@ -201,7 +270,8 @@ pub(crate) fn open_file_with_context_handler(checker: &mut Checker, func: &Expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checker
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
.diagnostics
|
OpenFileWithContextHandler,
|
||||||
.push(Diagnostic::new(OpenFileWithContextHandler, func.range()));
|
call.func.range(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff_linter/src/rules/flake8_simplify/mod.rs
|
source: crates/ruff_linter/src/rules/flake8_simplify/mod.rs
|
||||||
---
|
---
|
||||||
SIM115.py:8:5: SIM115 Use context handler for opening files
|
SIM115.py:8:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
|
||||||
7 | # SIM115
|
7 | # SIM115
|
||||||
8 | f = open("foo.txt")
|
8 | f = open("foo.txt")
|
||||||
|
@ -10,7 +10,7 @@ SIM115.py:8:5: SIM115 Use context handler for opening files
|
||||||
10 | f = pathlib.Path("foo.txt").open()
|
10 | f = pathlib.Path("foo.txt").open()
|
||||||
|
|
|
|
||||||
|
|
||||||
SIM115.py:9:5: SIM115 Use context handler for opening files
|
SIM115.py:9:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
|
||||||
7 | # SIM115
|
7 | # SIM115
|
||||||
8 | f = open("foo.txt")
|
8 | f = open("foo.txt")
|
||||||
|
@ -20,7 +20,7 @@ SIM115.py:9:5: SIM115 Use context handler for opening files
|
||||||
11 | f = pl.Path("foo.txt").open()
|
11 | f = pl.Path("foo.txt").open()
|
||||||
|
|
|
|
||||||
|
|
||||||
SIM115.py:10:5: SIM115 Use context handler for opening files
|
SIM115.py:10:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
|
||||||
8 | f = open("foo.txt")
|
8 | f = open("foo.txt")
|
||||||
9 | f = Path("foo.txt").open()
|
9 | f = Path("foo.txt").open()
|
||||||
|
@ -30,7 +30,7 @@ SIM115.py:10:5: SIM115 Use context handler for opening files
|
||||||
12 | f = P("foo.txt").open()
|
12 | f = P("foo.txt").open()
|
||||||
|
|
|
|
||||||
|
|
||||||
SIM115.py:11:5: SIM115 Use context handler for opening files
|
SIM115.py:11:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
|
||||||
9 | f = Path("foo.txt").open()
|
9 | f = Path("foo.txt").open()
|
||||||
10 | f = pathlib.Path("foo.txt").open()
|
10 | f = pathlib.Path("foo.txt").open()
|
||||||
|
@ -40,7 +40,7 @@ SIM115.py:11:5: SIM115 Use context handler for opening files
|
||||||
13 | data = f.read()
|
13 | data = f.read()
|
||||||
|
|
|
|
||||||
|
|
||||||
SIM115.py:12:5: SIM115 Use context handler for opening files
|
SIM115.py:12:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
|
||||||
10 | f = pathlib.Path("foo.txt").open()
|
10 | f = pathlib.Path("foo.txt").open()
|
||||||
11 | f = pl.Path("foo.txt").open()
|
11 | f = pl.Path("foo.txt").open()
|
||||||
|
@ -50,7 +50,7 @@ SIM115.py:12:5: SIM115 Use context handler for opening files
|
||||||
14 | f.close()
|
14 | f.close()
|
||||||
|
|
|
|
||||||
|
|
||||||
SIM115.py:39:9: SIM115 Use context handler for opening files
|
SIM115.py:39:9: SIM115 Use a context manager for opening files
|
||||||
|
|
|
|
||||||
37 | # SIM115
|
37 | # SIM115
|
||||||
38 | with contextlib.ExitStack():
|
38 | with contextlib.ExitStack():
|
||||||
|
@ -59,5 +59,3 @@ SIM115.py:39:9: SIM115 Use context handler for opening files
|
||||||
40 |
|
40 |
|
||||||
41 | # OK
|
41 | # OK
|
||||||
|
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,326 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_linter/src/rules/flake8_simplify/mod.rs
|
||||||
|
---
|
||||||
|
SIM115.py:8:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
7 | # SIM115
|
||||||
|
8 | f = open("foo.txt")
|
||||||
|
| ^^^^ SIM115
|
||||||
|
9 | f = Path("foo.txt").open()
|
||||||
|
10 | f = pathlib.Path("foo.txt").open()
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:9:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
7 | # SIM115
|
||||||
|
8 | f = open("foo.txt")
|
||||||
|
9 | f = Path("foo.txt").open()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^ SIM115
|
||||||
|
10 | f = pathlib.Path("foo.txt").open()
|
||||||
|
11 | f = pl.Path("foo.txt").open()
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:10:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
8 | f = open("foo.txt")
|
||||||
|
9 | f = Path("foo.txt").open()
|
||||||
|
10 | f = pathlib.Path("foo.txt").open()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SIM115
|
||||||
|
11 | f = pl.Path("foo.txt").open()
|
||||||
|
12 | f = P("foo.txt").open()
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:11:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
9 | f = Path("foo.txt").open()
|
||||||
|
10 | f = pathlib.Path("foo.txt").open()
|
||||||
|
11 | f = pl.Path("foo.txt").open()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^ SIM115
|
||||||
|
12 | f = P("foo.txt").open()
|
||||||
|
13 | data = f.read()
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:12:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
10 | f = pathlib.Path("foo.txt").open()
|
||||||
|
11 | f = pl.Path("foo.txt").open()
|
||||||
|
12 | f = P("foo.txt").open()
|
||||||
|
| ^^^^^^^^^^^^^^^^^ SIM115
|
||||||
|
13 | data = f.read()
|
||||||
|
14 | f.close()
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:39:9: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
37 | # SIM115
|
||||||
|
38 | with contextlib.ExitStack():
|
||||||
|
39 | f = open("filename")
|
||||||
|
| ^^^^ SIM115
|
||||||
|
40 |
|
||||||
|
41 | # OK
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:80:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
78 | import fileinput
|
||||||
|
79 |
|
||||||
|
80 | f = tempfile.NamedTemporaryFile()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ SIM115
|
||||||
|
81 | f = tempfile.TemporaryFile()
|
||||||
|
82 | f = tempfile.SpooledTemporaryFile()
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:81:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
80 | f = tempfile.NamedTemporaryFile()
|
||||||
|
81 | f = tempfile.TemporaryFile()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^ SIM115
|
||||||
|
82 | f = tempfile.SpooledTemporaryFile()
|
||||||
|
83 | f = tarfile.open("foo.tar")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:82:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
80 | f = tempfile.NamedTemporaryFile()
|
||||||
|
81 | f = tempfile.TemporaryFile()
|
||||||
|
82 | f = tempfile.SpooledTemporaryFile()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SIM115
|
||||||
|
83 | f = tarfile.open("foo.tar")
|
||||||
|
84 | f = TarFile("foo.tar").open()
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:83:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
81 | f = tempfile.TemporaryFile()
|
||||||
|
82 | f = tempfile.SpooledTemporaryFile()
|
||||||
|
83 | f = tarfile.open("foo.tar")
|
||||||
|
| ^^^^^^^^^^^^ SIM115
|
||||||
|
84 | f = TarFile("foo.tar").open()
|
||||||
|
85 | f = tarfile.TarFile("foo.tar").open()
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:84:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
82 | f = tempfile.SpooledTemporaryFile()
|
||||||
|
83 | f = tarfile.open("foo.tar")
|
||||||
|
84 | f = TarFile("foo.tar").open()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^ SIM115
|
||||||
|
85 | f = tarfile.TarFile("foo.tar").open()
|
||||||
|
86 | f = tarfile.TarFile().open()
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:85:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
83 | f = tarfile.open("foo.tar")
|
||||||
|
84 | f = TarFile("foo.tar").open()
|
||||||
|
85 | f = tarfile.TarFile("foo.tar").open()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SIM115
|
||||||
|
86 | f = tarfile.TarFile().open()
|
||||||
|
87 | f = zipfile.ZipFile("foo.zip").open("foo.txt")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:86:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
84 | f = TarFile("foo.tar").open()
|
||||||
|
85 | f = tarfile.TarFile("foo.tar").open()
|
||||||
|
86 | f = tarfile.TarFile().open()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^ SIM115
|
||||||
|
87 | f = zipfile.ZipFile("foo.zip").open("foo.txt")
|
||||||
|
88 | f = io.open("foo.txt")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:87:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
85 | f = tarfile.TarFile("foo.tar").open()
|
||||||
|
86 | f = tarfile.TarFile().open()
|
||||||
|
87 | f = zipfile.ZipFile("foo.zip").open("foo.txt")
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SIM115
|
||||||
|
88 | f = io.open("foo.txt")
|
||||||
|
89 | f = io.open_code("foo.txt")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:88:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
86 | f = tarfile.TarFile().open()
|
||||||
|
87 | f = zipfile.ZipFile("foo.zip").open("foo.txt")
|
||||||
|
88 | f = io.open("foo.txt")
|
||||||
|
| ^^^^^^^ SIM115
|
||||||
|
89 | f = io.open_code("foo.txt")
|
||||||
|
90 | f = codecs.open("foo.txt")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:89:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
87 | f = zipfile.ZipFile("foo.zip").open("foo.txt")
|
||||||
|
88 | f = io.open("foo.txt")
|
||||||
|
89 | f = io.open_code("foo.txt")
|
||||||
|
| ^^^^^^^^^^^^ SIM115
|
||||||
|
90 | f = codecs.open("foo.txt")
|
||||||
|
91 | f = bz2.open("foo.txt")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:90:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
88 | f = io.open("foo.txt")
|
||||||
|
89 | f = io.open_code("foo.txt")
|
||||||
|
90 | f = codecs.open("foo.txt")
|
||||||
|
| ^^^^^^^^^^^ SIM115
|
||||||
|
91 | f = bz2.open("foo.txt")
|
||||||
|
92 | f = gzip.open("foo.txt")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:91:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
89 | f = io.open_code("foo.txt")
|
||||||
|
90 | f = codecs.open("foo.txt")
|
||||||
|
91 | f = bz2.open("foo.txt")
|
||||||
|
| ^^^^^^^^ SIM115
|
||||||
|
92 | f = gzip.open("foo.txt")
|
||||||
|
93 | f = dbm.open("foo.db")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:92:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
90 | f = codecs.open("foo.txt")
|
||||||
|
91 | f = bz2.open("foo.txt")
|
||||||
|
92 | f = gzip.open("foo.txt")
|
||||||
|
| ^^^^^^^^^ SIM115
|
||||||
|
93 | f = dbm.open("foo.db")
|
||||||
|
94 | f = dbm.gnu.open("foo.db")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:93:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
91 | f = bz2.open("foo.txt")
|
||||||
|
92 | f = gzip.open("foo.txt")
|
||||||
|
93 | f = dbm.open("foo.db")
|
||||||
|
| ^^^^^^^^ SIM115
|
||||||
|
94 | f = dbm.gnu.open("foo.db")
|
||||||
|
95 | f = dbm.ndbm.open("foo.db")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:94:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
92 | f = gzip.open("foo.txt")
|
||||||
|
93 | f = dbm.open("foo.db")
|
||||||
|
94 | f = dbm.gnu.open("foo.db")
|
||||||
|
| ^^^^^^^^^^^^ SIM115
|
||||||
|
95 | f = dbm.ndbm.open("foo.db")
|
||||||
|
96 | f = dbm.dumb.open("foo.db")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:95:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
93 | f = dbm.open("foo.db")
|
||||||
|
94 | f = dbm.gnu.open("foo.db")
|
||||||
|
95 | f = dbm.ndbm.open("foo.db")
|
||||||
|
| ^^^^^^^^^^^^^ SIM115
|
||||||
|
96 | f = dbm.dumb.open("foo.db")
|
||||||
|
97 | f = lzma.open("foo.xz")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:96:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
94 | f = dbm.gnu.open("foo.db")
|
||||||
|
95 | f = dbm.ndbm.open("foo.db")
|
||||||
|
96 | f = dbm.dumb.open("foo.db")
|
||||||
|
| ^^^^^^^^^^^^^ SIM115
|
||||||
|
97 | f = lzma.open("foo.xz")
|
||||||
|
98 | f = lzma.LZMAFile("foo.xz")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:97:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
95 | f = dbm.ndbm.open("foo.db")
|
||||||
|
96 | f = dbm.dumb.open("foo.db")
|
||||||
|
97 | f = lzma.open("foo.xz")
|
||||||
|
| ^^^^^^^^^ SIM115
|
||||||
|
98 | f = lzma.LZMAFile("foo.xz")
|
||||||
|
99 | f = shelve.open("foo.db")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:98:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
96 | f = dbm.dumb.open("foo.db")
|
||||||
|
97 | f = lzma.open("foo.xz")
|
||||||
|
98 | f = lzma.LZMAFile("foo.xz")
|
||||||
|
| ^^^^^^^^^^^^^ SIM115
|
||||||
|
99 | f = shelve.open("foo.db")
|
||||||
|
100 | f = tokenize.open("foo.py")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:99:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
97 | f = lzma.open("foo.xz")
|
||||||
|
98 | f = lzma.LZMAFile("foo.xz")
|
||||||
|
99 | f = shelve.open("foo.db")
|
||||||
|
| ^^^^^^^^^^^ SIM115
|
||||||
|
100 | f = tokenize.open("foo.py")
|
||||||
|
101 | f = wave.open("foo.wav")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:100:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
98 | f = lzma.LZMAFile("foo.xz")
|
||||||
|
99 | f = shelve.open("foo.db")
|
||||||
|
100 | f = tokenize.open("foo.py")
|
||||||
|
| ^^^^^^^^^^^^^ SIM115
|
||||||
|
101 | f = wave.open("foo.wav")
|
||||||
|
102 | f = tarfile.TarFile.taropen("foo.tar")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:101:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
99 | f = shelve.open("foo.db")
|
||||||
|
100 | f = tokenize.open("foo.py")
|
||||||
|
101 | f = wave.open("foo.wav")
|
||||||
|
| ^^^^^^^^^ SIM115
|
||||||
|
102 | f = tarfile.TarFile.taropen("foo.tar")
|
||||||
|
103 | f = fileinput.input("foo.txt")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:102:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
100 | f = tokenize.open("foo.py")
|
||||||
|
101 | f = wave.open("foo.wav")
|
||||||
|
102 | f = tarfile.TarFile.taropen("foo.tar")
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^ SIM115
|
||||||
|
103 | f = fileinput.input("foo.txt")
|
||||||
|
104 | f = fileinput.FileInput("foo.txt")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:103:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
101 | f = wave.open("foo.wav")
|
||||||
|
102 | f = tarfile.TarFile.taropen("foo.tar")
|
||||||
|
103 | f = fileinput.input("foo.txt")
|
||||||
|
| ^^^^^^^^^^^^^^^ SIM115
|
||||||
|
104 | f = fileinput.FileInput("foo.txt")
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:104:5: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
102 | f = tarfile.TarFile.taropen("foo.tar")
|
||||||
|
103 | f = fileinput.input("foo.txt")
|
||||||
|
104 | f = fileinput.FileInput("foo.txt")
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^ SIM115
|
||||||
|
105 |
|
||||||
|
106 | with contextlib.suppress(Exception):
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:240:9: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
238 | def aliased():
|
||||||
|
239 | from shelve import open as open_shelf
|
||||||
|
240 | x = open_shelf("foo.dbm")
|
||||||
|
| ^^^^^^^^^^ SIM115
|
||||||
|
241 | x.close()
|
||||||
|
|
|
||||||
|
|
||||||
|
SIM115.py:244:9: SIM115 Use a context manager for opening files
|
||||||
|
|
|
||||||
|
243 | from tarfile import TarFile as TF
|
||||||
|
244 | f = TF("foo").open()
|
||||||
|
| ^^^^^^^^^^^^^^ SIM115
|
||||||
|
245 | f.close()
|
||||||
|
|
|
Loading…
Add table
Add a link
Reference in a new issue