mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-01 20:31:57 +00:00
[refurb] Add fixes for FURB101, FURB103 (#20520)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks instrumented (ruff) (push) Blocked by required conditions
CI / benchmarks instrumented (ty) (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks instrumented (ruff) (push) Blocked by required conditions
CI / benchmarks instrumented (ty) (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions
## Summary Part of `PTH-*` fixes: https://github.com/astral-sh/ruff/pull/19404#issuecomment-3089639686 ## Test Plan `cargo nextest run furb`
This commit is contained in:
parent
70f51e9648
commit
b66a3e7451
10 changed files with 698 additions and 34 deletions
|
|
@ -259,3 +259,13 @@ pub(crate) const fn is_b006_unsafe_fix_preserve_assignment_expr_enabled(
|
|||
) -> bool {
|
||||
settings.preview.is_enabled()
|
||||
}
|
||||
|
||||
// https://github.com/astral-sh/ruff/pull/20520
|
||||
pub(crate) const fn is_fix_read_whole_file_enabled(settings: &LinterSettings) -> bool {
|
||||
settings.preview.is_enabled()
|
||||
}
|
||||
|
||||
// https://github.com/astral-sh/ruff/pull/20520
|
||||
pub(crate) const fn is_fix_write_whole_file_enabled(settings: &LinterSettings) -> bool {
|
||||
settings.preview.is_enabled()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use ruff_python_ast::name::Name;
|
||||
use ruff_python_ast::{self as ast, Expr, parenthesize::parenthesized_range};
|
||||
use ruff_python_ast::PythonVersion;
|
||||
use ruff_python_ast::{self as ast, Expr, name::Name, parenthesize::parenthesized_range};
|
||||
use ruff_python_codegen::Generator;
|
||||
use ruff_python_semantic::{BindingId, ResolvedReference, SemanticModel};
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::{Applicability, Edit, Fix};
|
||||
use ruff_python_ast::PythonVersion;
|
||||
|
||||
/// Format a code snippet to call `name.method()`.
|
||||
pub(super) fn generate_method_call(name: Name, method: &str, generator: Generator) -> String {
|
||||
|
|
@ -345,12 +344,8 @@ pub(super) fn parenthesize_loop_iter_if_necessary<'a>(
|
|||
let iter_in_source = locator.slice(iter);
|
||||
|
||||
match iter {
|
||||
ast::Expr::Tuple(tuple) if !tuple.parenthesized => {
|
||||
Cow::Owned(format!("({iter_in_source})"))
|
||||
}
|
||||
ast::Expr::Lambda(_) | ast::Expr::If(_)
|
||||
if matches!(location, IterLocation::Comprehension) =>
|
||||
{
|
||||
Expr::Tuple(tuple) if !tuple.parenthesized => Cow::Owned(format!("({iter_in_source})")),
|
||||
Expr::Lambda(_) | Expr::If(_) if matches!(location, IterLocation::Comprehension) => {
|
||||
Cow::Owned(format!("({iter_in_source})"))
|
||||
}
|
||||
_ => Cow::Borrowed(iter_in_source),
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ mod tests {
|
|||
use test_case::test_case;
|
||||
|
||||
use crate::registry::Rule;
|
||||
use crate::settings::types::PreviewMode;
|
||||
use crate::test::test_path;
|
||||
use crate::{assert_diagnostics, settings};
|
||||
|
||||
|
|
@ -62,6 +63,25 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case(Rule::ReadWholeFile, Path::new("FURB101.py"))]
|
||||
#[test_case(Rule::WriteWholeFile, Path::new("FURB103.py"))]
|
||||
fn preview_rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!(
|
||||
"preview_{}_{}",
|
||||
rule_code.noqa_code(),
|
||||
path.to_string_lossy()
|
||||
);
|
||||
let diagnostics = test_path(
|
||||
Path::new("refurb").join(path).as_path(),
|
||||
&settings::LinterSettings {
|
||||
preview: PreviewMode::Enabled,
|
||||
..settings::LinterSettings::for_rule(rule_code)
|
||||
},
|
||||
)?;
|
||||
assert_diagnostics!(snapshot, diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_whole_file_python_39() -> Result<()> {
|
||||
let diagnostics = test_path(
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
use ruff_diagnostics::{Applicability, Edit, Fix};
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::visitor::{self, Visitor};
|
||||
use ruff_python_ast::{self as ast, Expr};
|
||||
use ruff_python_ast::{
|
||||
self as ast, Expr, Stmt,
|
||||
visitor::{self, Visitor},
|
||||
};
|
||||
use ruff_python_codegen::Generator;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::Violation;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::fix::snippet::SourceCodeSnippet;
|
||||
|
||||
use crate::importer::ImportRequest;
|
||||
use crate::rules::refurb::helpers::{FileOpen, find_file_opens};
|
||||
use crate::{FixAvailability, Violation};
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for uses of `open` and `read` that can be replaced by `pathlib`
|
||||
|
|
@ -31,6 +34,8 @@ use crate::rules::refurb::helpers::{FileOpen, find_file_opens};
|
|||
///
|
||||
/// contents = Path(filename).read_text()
|
||||
/// ```
|
||||
/// ## Fix Safety
|
||||
/// This rule's fix is marked as unsafe if the replacement would remove comments attached to the original expression.
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: `Path.read_bytes`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.read_bytes)
|
||||
|
|
@ -42,12 +47,22 @@ pub(crate) struct ReadWholeFile {
|
|||
}
|
||||
|
||||
impl Violation for ReadWholeFile {
|
||||
const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes;
|
||||
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let filename = self.filename.truncated_display();
|
||||
let suggestion = self.suggestion.truncated_display();
|
||||
format!("`open` and `read` should be replaced by `Path({filename}).{suggestion}`")
|
||||
}
|
||||
|
||||
fn fix_title(&self) -> Option<String> {
|
||||
Some(format!(
|
||||
"Replace with `Path({}).{}`",
|
||||
self.filename.truncated_display(),
|
||||
self.suggestion.truncated_display(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// FURB101
|
||||
|
|
@ -64,7 +79,7 @@ pub(crate) fn read_whole_file(checker: &Checker, with: &ast::StmtWith) {
|
|||
}
|
||||
|
||||
// Then we need to match each `open` operation with exactly one `read` call.
|
||||
let mut matcher = ReadMatcher::new(checker, candidates);
|
||||
let mut matcher = ReadMatcher::new(checker, candidates, with);
|
||||
visitor::walk_body(&mut matcher, &with.body);
|
||||
}
|
||||
|
||||
|
|
@ -72,13 +87,19 @@ pub(crate) fn read_whole_file(checker: &Checker, with: &ast::StmtWith) {
|
|||
struct ReadMatcher<'a, 'b> {
|
||||
checker: &'a Checker<'b>,
|
||||
candidates: Vec<FileOpen<'a>>,
|
||||
with_stmt: &'a ast::StmtWith,
|
||||
}
|
||||
|
||||
impl<'a, 'b> ReadMatcher<'a, 'b> {
|
||||
fn new(checker: &'a Checker<'b>, candidates: Vec<FileOpen<'a>>) -> Self {
|
||||
fn new(
|
||||
checker: &'a Checker<'b>,
|
||||
candidates: Vec<FileOpen<'a>>,
|
||||
with_stmt: &'a ast::StmtWith,
|
||||
) -> Self {
|
||||
Self {
|
||||
checker,
|
||||
candidates,
|
||||
with_stmt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -92,15 +113,38 @@ impl<'a> Visitor<'a> for ReadMatcher<'a, '_> {
|
|||
.position(|open| open.is_ref(read_from))
|
||||
{
|
||||
let open = self.candidates.remove(open);
|
||||
self.checker.report_diagnostic(
|
||||
let suggestion = make_suggestion(&open, self.checker.generator());
|
||||
let mut diagnostic = self.checker.report_diagnostic(
|
||||
ReadWholeFile {
|
||||
filename: SourceCodeSnippet::from_str(
|
||||
&self.checker.generator().expr(open.filename),
|
||||
),
|
||||
suggestion: make_suggestion(&open, self.checker.generator()),
|
||||
suggestion: SourceCodeSnippet::from_str(&suggestion),
|
||||
},
|
||||
open.item.range(),
|
||||
);
|
||||
|
||||
if !crate::preview::is_fix_read_whole_file_enabled(self.checker.settings()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let target = match self.with_stmt.body.first() {
|
||||
Some(Stmt::Assign(assign))
|
||||
if assign.value.range().contains_range(expr.range()) =>
|
||||
{
|
||||
match assign.targets.first() {
|
||||
Some(Expr::Name(name)) => Some(name.id.as_str()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(fix) =
|
||||
generate_fix(self.checker, &open, target, self.with_stmt, &suggestion)
|
||||
{
|
||||
diagnostic.set_fix(fix);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -125,7 +169,7 @@ fn match_read_call(expr: &Expr) -> Option<&Expr> {
|
|||
Some(&*attr.value)
|
||||
}
|
||||
|
||||
fn make_suggestion(open: &FileOpen<'_>, generator: Generator) -> SourceCodeSnippet {
|
||||
fn make_suggestion(open: &FileOpen<'_>, generator: Generator) -> String {
|
||||
let name = ast::ExprName {
|
||||
id: open.mode.pathlib_method(),
|
||||
ctx: ast::ExprContext::Load,
|
||||
|
|
@ -143,5 +187,46 @@ fn make_suggestion(open: &FileOpen<'_>, generator: Generator) -> SourceCodeSnipp
|
|||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
};
|
||||
SourceCodeSnippet::from_str(&generator.expr(&call.into()))
|
||||
generator.expr(&call.into())
|
||||
}
|
||||
|
||||
fn generate_fix(
|
||||
checker: &Checker,
|
||||
open: &FileOpen,
|
||||
target: Option<&str>,
|
||||
with_stmt: &ast::StmtWith,
|
||||
suggestion: &str,
|
||||
) -> Option<Fix> {
|
||||
if !(with_stmt.items.len() == 1 && matches!(with_stmt.body.as_slice(), [Stmt::Assign(_)])) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let locator = checker.locator();
|
||||
let filename_code = locator.slice(open.filename.range());
|
||||
|
||||
let (import_edit, binding) = checker
|
||||
.importer()
|
||||
.get_or_import_symbol(
|
||||
&ImportRequest::import("pathlib", "Path"),
|
||||
with_stmt.start(),
|
||||
checker.semantic(),
|
||||
)
|
||||
.ok()?;
|
||||
|
||||
let replacement = match target {
|
||||
Some(var) => format!("{var} = {binding}({filename_code}).{suggestion}"),
|
||||
None => format!("{binding}({filename_code}).{suggestion}"),
|
||||
};
|
||||
|
||||
let applicability = if checker.comment_ranges().intersects(with_stmt.range()) {
|
||||
Applicability::Unsafe
|
||||
} else {
|
||||
Applicability::Safe
|
||||
};
|
||||
|
||||
Some(Fix::applicable_edits(
|
||||
Edit::range_replacement(replacement, with_stmt.range()),
|
||||
[import_edit],
|
||||
applicability,
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,19 @@
|
|||
use ruff_diagnostics::{Applicability, Edit, Fix};
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::relocate::relocate_expr;
|
||||
use ruff_python_ast::visitor::{self, Visitor};
|
||||
use ruff_python_ast::{self as ast, Expr, Stmt};
|
||||
use ruff_python_ast::{
|
||||
self as ast, Expr, Stmt,
|
||||
relocate::relocate_expr,
|
||||
visitor::{self, Visitor},
|
||||
};
|
||||
|
||||
use ruff_python_codegen::Generator;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::Violation;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::fix::snippet::SourceCodeSnippet;
|
||||
|
||||
use crate::importer::ImportRequest;
|
||||
use crate::rules::refurb::helpers::{FileOpen, find_file_opens};
|
||||
use crate::{FixAvailability, Violation};
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for uses of `open` and `write` that can be replaced by `pathlib`
|
||||
|
|
@ -33,6 +37,9 @@ use crate::rules::refurb::helpers::{FileOpen, find_file_opens};
|
|||
/// Path(filename).write_text(contents)
|
||||
/// ```
|
||||
///
|
||||
/// ## Fix Safety
|
||||
/// This rule's fix is marked as unsafe if the replacement would remove comments attached to the original expression.
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: `Path.write_bytes`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.write_bytes)
|
||||
/// - [Python documentation: `Path.write_text`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.write_text)
|
||||
|
|
@ -43,12 +50,21 @@ pub(crate) struct WriteWholeFile {
|
|||
}
|
||||
|
||||
impl Violation for WriteWholeFile {
|
||||
const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes;
|
||||
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let filename = self.filename.truncated_display();
|
||||
let suggestion = self.suggestion.truncated_display();
|
||||
format!("`open` and `write` should be replaced by `Path({filename}).{suggestion}`")
|
||||
}
|
||||
fn fix_title(&self) -> Option<String> {
|
||||
Some(format!(
|
||||
"Replace with `Path({}).{}`",
|
||||
self.filename.truncated_display(),
|
||||
self.suggestion.truncated_display(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// FURB103
|
||||
|
|
@ -65,7 +81,7 @@ pub(crate) fn write_whole_file(checker: &Checker, with: &ast::StmtWith) {
|
|||
}
|
||||
|
||||
// Then we need to match each `open` operation with exactly one `write` call.
|
||||
let mut matcher = WriteMatcher::new(checker, candidates);
|
||||
let mut matcher = WriteMatcher::new(checker, candidates, with);
|
||||
visitor::walk_body(&mut matcher, &with.body);
|
||||
}
|
||||
|
||||
|
|
@ -74,21 +90,27 @@ struct WriteMatcher<'a, 'b> {
|
|||
checker: &'a Checker<'b>,
|
||||
candidates: Vec<FileOpen<'a>>,
|
||||
loop_counter: u32,
|
||||
with_stmt: &'a ast::StmtWith,
|
||||
}
|
||||
|
||||
impl<'a, 'b> WriteMatcher<'a, 'b> {
|
||||
fn new(checker: &'a Checker<'b>, candidates: Vec<FileOpen<'a>>) -> Self {
|
||||
fn new(
|
||||
checker: &'a Checker<'b>,
|
||||
candidates: Vec<FileOpen<'a>>,
|
||||
with_stmt: &'a ast::StmtWith,
|
||||
) -> Self {
|
||||
Self {
|
||||
checker,
|
||||
candidates,
|
||||
loop_counter: 0,
|
||||
with_stmt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Visitor<'a> for WriteMatcher<'a, '_> {
|
||||
fn visit_stmt(&mut self, stmt: &'a Stmt) {
|
||||
if matches!(stmt, ast::Stmt::While(_) | ast::Stmt::For(_)) {
|
||||
if matches!(stmt, Stmt::While(_) | Stmt::For(_)) {
|
||||
self.loop_counter += 1;
|
||||
visitor::walk_stmt(self, stmt);
|
||||
self.loop_counter -= 1;
|
||||
|
|
@ -104,19 +126,30 @@ impl<'a> Visitor<'a> for WriteMatcher<'a, '_> {
|
|||
.iter()
|
||||
.position(|open| open.is_ref(write_to))
|
||||
{
|
||||
let open = self.candidates.remove(open);
|
||||
|
||||
if self.loop_counter == 0 {
|
||||
let open = self.candidates.remove(open);
|
||||
self.checker.report_diagnostic(
|
||||
let suggestion = make_suggestion(&open, content, self.checker.generator());
|
||||
|
||||
let mut diagnostic = self.checker.report_diagnostic(
|
||||
WriteWholeFile {
|
||||
filename: SourceCodeSnippet::from_str(
|
||||
&self.checker.generator().expr(open.filename),
|
||||
),
|
||||
suggestion: make_suggestion(&open, content, self.checker.generator()),
|
||||
suggestion: SourceCodeSnippet::from_str(&suggestion),
|
||||
},
|
||||
open.item.range(),
|
||||
);
|
||||
} else {
|
||||
self.candidates.remove(open);
|
||||
|
||||
if !crate::preview::is_fix_write_whole_file_enabled(self.checker.settings()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(fix) =
|
||||
generate_fix(self.checker, &open, self.with_stmt, &suggestion)
|
||||
{
|
||||
diagnostic.set_fix(fix);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
@ -143,7 +176,7 @@ fn match_write_call(expr: &Expr) -> Option<(&Expr, &Expr)> {
|
|||
Some((&*attr.value, call.arguments.args.first()?))
|
||||
}
|
||||
|
||||
fn make_suggestion(open: &FileOpen<'_>, arg: &Expr, generator: Generator) -> SourceCodeSnippet {
|
||||
fn make_suggestion(open: &FileOpen<'_>, arg: &Expr, generator: Generator) -> String {
|
||||
let name = ast::ExprName {
|
||||
id: open.mode.pathlib_method(),
|
||||
ctx: ast::ExprContext::Load,
|
||||
|
|
@ -163,5 +196,42 @@ fn make_suggestion(open: &FileOpen<'_>, arg: &Expr, generator: Generator) -> Sou
|
|||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
};
|
||||
SourceCodeSnippet::from_str(&generator.expr(&call.into()))
|
||||
generator.expr(&call.into())
|
||||
}
|
||||
|
||||
fn generate_fix(
|
||||
checker: &Checker,
|
||||
open: &FileOpen,
|
||||
with_stmt: &ast::StmtWith,
|
||||
suggestion: &str,
|
||||
) -> Option<Fix> {
|
||||
if !(with_stmt.items.len() == 1 && matches!(with_stmt.body.as_slice(), [Stmt::Expr(_)])) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let locator = checker.locator();
|
||||
let filename_code = locator.slice(open.filename.range());
|
||||
|
||||
let (import_edit, binding) = checker
|
||||
.importer()
|
||||
.get_or_import_symbol(
|
||||
&ImportRequest::import("pathlib", "Path"),
|
||||
with_stmt.start(),
|
||||
checker.semantic(),
|
||||
)
|
||||
.ok()?;
|
||||
|
||||
let replacement = format!("{binding}({filename_code}).{suggestion}");
|
||||
|
||||
let applicability = if checker.comment_ranges().intersects(with_stmt.range()) {
|
||||
Applicability::Unsafe
|
||||
} else {
|
||||
Applicability::Safe
|
||||
};
|
||||
|
||||
Some(Fix::applicable_edits(
|
||||
Edit::range_replacement(replacement, with_stmt.range()),
|
||||
[import_edit],
|
||||
applicability,
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ FURB101 `open` and `read` should be replaced by `Path("file.txt").read_text()`
|
|||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
13 | x = f.read()
|
||||
|
|
||||
help: Replace with `Path("file.txt").read_text()`
|
||||
|
||||
FURB101 `open` and `read` should be replaced by `Path("file.txt").read_bytes()`
|
||||
--> FURB101.py:16:6
|
||||
|
|
@ -18,6 +19,7 @@ FURB101 `open` and `read` should be replaced by `Path("file.txt").read_bytes()`
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
17 | x = f.read()
|
||||
|
|
||||
help: Replace with `Path("file.txt").read_bytes()`
|
||||
|
||||
FURB101 `open` and `read` should be replaced by `Path("file.txt").read_bytes()`
|
||||
--> FURB101.py:20:6
|
||||
|
|
@ -27,6 +29,7 @@ FURB101 `open` and `read` should be replaced by `Path("file.txt").read_bytes()`
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
21 | x = f.read()
|
||||
|
|
||||
help: Replace with `Path("file.txt").read_bytes()`
|
||||
|
||||
FURB101 `open` and `read` should be replaced by `Path("file.txt").read_text(encoding="utf8")`
|
||||
--> FURB101.py:24:6
|
||||
|
|
@ -36,6 +39,7 @@ FURB101 `open` and `read` should be replaced by `Path("file.txt").read_text(enco
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
25 | x = f.read()
|
||||
|
|
||||
help: Replace with `Path("file.txt").read_text(encoding="utf8")`
|
||||
|
||||
FURB101 `open` and `read` should be replaced by `Path("file.txt").read_text(errors="ignore")`
|
||||
--> FURB101.py:28:6
|
||||
|
|
@ -45,6 +49,7 @@ FURB101 `open` and `read` should be replaced by `Path("file.txt").read_text(erro
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
29 | x = f.read()
|
||||
|
|
||||
help: Replace with `Path("file.txt").read_text(errors="ignore")`
|
||||
|
||||
FURB101 `open` and `read` should be replaced by `Path("file.txt").read_text()`
|
||||
--> FURB101.py:32:6
|
||||
|
|
@ -54,6 +59,7 @@ FURB101 `open` and `read` should be replaced by `Path("file.txt").read_text()`
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
33 | x = f.read()
|
||||
|
|
||||
help: Replace with `Path("file.txt").read_text()`
|
||||
|
||||
FURB101 `open` and `read` should be replaced by `Path(foo()).read_bytes()`
|
||||
--> FURB101.py:36:6
|
||||
|
|
@ -64,6 +70,7 @@ FURB101 `open` and `read` should be replaced by `Path(foo()).read_bytes()`
|
|||
37 | # The body of `with` is non-trivial, but the recommendation holds.
|
||||
38 | bar("pre")
|
||||
|
|
||||
help: Replace with `Path(foo()).read_bytes()`
|
||||
|
||||
FURB101 `open` and `read` should be replaced by `Path("a.txt").read_text()`
|
||||
--> FURB101.py:44:6
|
||||
|
|
@ -74,6 +81,7 @@ FURB101 `open` and `read` should be replaced by `Path("a.txt").read_text()`
|
|||
45 | x = a.read()
|
||||
46 | y = b.read()
|
||||
|
|
||||
help: Replace with `Path("a.txt").read_text()`
|
||||
|
||||
FURB101 `open` and `read` should be replaced by `Path("b.txt").read_bytes()`
|
||||
--> FURB101.py:44:26
|
||||
|
|
@ -84,6 +92,7 @@ FURB101 `open` and `read` should be replaced by `Path("b.txt").read_bytes()`
|
|||
45 | x = a.read()
|
||||
46 | y = b.read()
|
||||
|
|
||||
help: Replace with `Path("b.txt").read_bytes()`
|
||||
|
||||
FURB101 `open` and `read` should be replaced by `Path("file.txt").read_text()`
|
||||
--> FURB101.py:49:18
|
||||
|
|
@ -94,3 +103,4 @@ FURB101 `open` and `read` should be replaced by `Path("file.txt").read_text()`
|
|||
50 | # We have other things in here, multiple with items, but
|
||||
51 | # the user reads the whole file and that bit they can replace.
|
||||
|
|
||||
help: Replace with `Path("file.txt").read_text()`
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text("t
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
13 | f.write("test")
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text("test")`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_bytes(foobar)`
|
||||
--> FURB103.py:16:6
|
||||
|
|
@ -18,6 +19,7 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_bytes(f
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
17 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_bytes(foobar)`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_bytes(b"abc")`
|
||||
--> FURB103.py:20:6
|
||||
|
|
@ -27,6 +29,7 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_bytes(b
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
21 | f.write(b"abc")
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_bytes(b"abc")`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(foobar, encoding="utf8")`
|
||||
--> FURB103.py:24:6
|
||||
|
|
@ -36,6 +39,7 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(fo
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
25 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(foobar, encoding="utf8")`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(foobar, errors="ignore")`
|
||||
--> FURB103.py:28:6
|
||||
|
|
@ -45,6 +49,7 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(fo
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
29 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(foobar, errors="ignore")`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(foobar)`
|
||||
--> FURB103.py:32:6
|
||||
|
|
@ -54,6 +59,7 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(fo
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
33 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(foobar)`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path(foo()).write_bytes(bar())`
|
||||
--> FURB103.py:36:6
|
||||
|
|
@ -64,6 +70,7 @@ FURB103 `open` and `write` should be replaced by `Path(foo()).write_bytes(bar())
|
|||
37 | # The body of `with` is non-trivial, but the recommendation holds.
|
||||
38 | bar("pre")
|
||||
|
|
||||
help: Replace with `Path(foo()).write_bytes(bar())`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("a.txt").write_text(x)`
|
||||
--> FURB103.py:44:6
|
||||
|
|
@ -74,6 +81,7 @@ FURB103 `open` and `write` should be replaced by `Path("a.txt").write_text(x)`
|
|||
45 | a.write(x)
|
||||
46 | b.write(y)
|
||||
|
|
||||
help: Replace with `Path("a.txt").write_text(x)`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("b.txt").write_bytes(y)`
|
||||
--> FURB103.py:44:31
|
||||
|
|
@ -84,6 +92,7 @@ FURB103 `open` and `write` should be replaced by `Path("b.txt").write_bytes(y)`
|
|||
45 | a.write(x)
|
||||
46 | b.write(y)
|
||||
|
|
||||
help: Replace with `Path("b.txt").write_bytes(y)`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(bar(bar(a + x)))`
|
||||
--> FURB103.py:49:18
|
||||
|
|
@ -94,6 +103,7 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(ba
|
|||
50 | # We have other things in here, multiple with items, but the user
|
||||
51 | # writes a single time to file and that bit they can replace.
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(bar(bar(a + x)))`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(foobar, newline="\r\n")`
|
||||
--> FURB103.py:58:6
|
||||
|
|
@ -103,6 +113,7 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(fo
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
59 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(foobar, newline="\r\n")`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(foobar, newline="\r\n")`
|
||||
--> FURB103.py:66:6
|
||||
|
|
@ -112,6 +123,7 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(fo
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
67 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(foobar, newline="\r\n")`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(foobar, newline="\r\n")`
|
||||
--> FURB103.py:74:6
|
||||
|
|
@ -121,3 +133,4 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(fo
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
75 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(foobar, newline="\r\n")`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,191 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/refurb/mod.rs
|
||||
---
|
||||
FURB101 [*] `open` and `read` should be replaced by `Path("file.txt").read_text()`
|
||||
--> FURB101.py:12:6
|
||||
|
|
||||
11 | # FURB101
|
||||
12 | with open("file.txt") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
13 | x = f.read()
|
||||
|
|
||||
help: Replace with `Path("file.txt").read_text()`
|
||||
1 + import pathlib
|
||||
2 | def foo():
|
||||
3 | ...
|
||||
4 |
|
||||
--------------------------------------------------------------------------------
|
||||
10 | # Errors.
|
||||
11 |
|
||||
12 | # FURB101
|
||||
- with open("file.txt") as f:
|
||||
- x = f.read()
|
||||
13 + x = pathlib.Path("file.txt").read_text()
|
||||
14 |
|
||||
15 | # FURB101
|
||||
16 | with open("file.txt", "rb") as f:
|
||||
|
||||
FURB101 [*] `open` and `read` should be replaced by `Path("file.txt").read_bytes()`
|
||||
--> FURB101.py:16:6
|
||||
|
|
||||
15 | # FURB101
|
||||
16 | with open("file.txt", "rb") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
17 | x = f.read()
|
||||
|
|
||||
help: Replace with `Path("file.txt").read_bytes()`
|
||||
1 + import pathlib
|
||||
2 | def foo():
|
||||
3 | ...
|
||||
4 |
|
||||
--------------------------------------------------------------------------------
|
||||
14 | x = f.read()
|
||||
15 |
|
||||
16 | # FURB101
|
||||
- with open("file.txt", "rb") as f:
|
||||
- x = f.read()
|
||||
17 + x = pathlib.Path("file.txt").read_bytes()
|
||||
18 |
|
||||
19 | # FURB101
|
||||
20 | with open("file.txt", mode="rb") as f:
|
||||
|
||||
FURB101 [*] `open` and `read` should be replaced by `Path("file.txt").read_bytes()`
|
||||
--> FURB101.py:20:6
|
||||
|
|
||||
19 | # FURB101
|
||||
20 | with open("file.txt", mode="rb") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
21 | x = f.read()
|
||||
|
|
||||
help: Replace with `Path("file.txt").read_bytes()`
|
||||
1 + import pathlib
|
||||
2 | def foo():
|
||||
3 | ...
|
||||
4 |
|
||||
--------------------------------------------------------------------------------
|
||||
18 | x = f.read()
|
||||
19 |
|
||||
20 | # FURB101
|
||||
- with open("file.txt", mode="rb") as f:
|
||||
- x = f.read()
|
||||
21 + x = pathlib.Path("file.txt").read_bytes()
|
||||
22 |
|
||||
23 | # FURB101
|
||||
24 | with open("file.txt", encoding="utf8") as f:
|
||||
|
||||
FURB101 [*] `open` and `read` should be replaced by `Path("file.txt").read_text(encoding="utf8")`
|
||||
--> FURB101.py:24:6
|
||||
|
|
||||
23 | # FURB101
|
||||
24 | with open("file.txt", encoding="utf8") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
25 | x = f.read()
|
||||
|
|
||||
help: Replace with `Path("file.txt").read_text(encoding="utf8")`
|
||||
1 + import pathlib
|
||||
2 | def foo():
|
||||
3 | ...
|
||||
4 |
|
||||
--------------------------------------------------------------------------------
|
||||
22 | x = f.read()
|
||||
23 |
|
||||
24 | # FURB101
|
||||
- with open("file.txt", encoding="utf8") as f:
|
||||
- x = f.read()
|
||||
25 + x = pathlib.Path("file.txt").read_text(encoding="utf8")
|
||||
26 |
|
||||
27 | # FURB101
|
||||
28 | with open("file.txt", errors="ignore") as f:
|
||||
|
||||
FURB101 [*] `open` and `read` should be replaced by `Path("file.txt").read_text(errors="ignore")`
|
||||
--> FURB101.py:28:6
|
||||
|
|
||||
27 | # FURB101
|
||||
28 | with open("file.txt", errors="ignore") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
29 | x = f.read()
|
||||
|
|
||||
help: Replace with `Path("file.txt").read_text(errors="ignore")`
|
||||
1 + import pathlib
|
||||
2 | def foo():
|
||||
3 | ...
|
||||
4 |
|
||||
--------------------------------------------------------------------------------
|
||||
26 | x = f.read()
|
||||
27 |
|
||||
28 | # FURB101
|
||||
- with open("file.txt", errors="ignore") as f:
|
||||
- x = f.read()
|
||||
29 + x = pathlib.Path("file.txt").read_text(errors="ignore")
|
||||
30 |
|
||||
31 | # FURB101
|
||||
32 | with open("file.txt", mode="r") as f: # noqa: FURB120
|
||||
|
||||
FURB101 [*] `open` and `read` should be replaced by `Path("file.txt").read_text()`
|
||||
--> FURB101.py:32:6
|
||||
|
|
||||
31 | # FURB101
|
||||
32 | with open("file.txt", mode="r") as f: # noqa: FURB120
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
33 | x = f.read()
|
||||
|
|
||||
help: Replace with `Path("file.txt").read_text()`
|
||||
1 + import pathlib
|
||||
2 | def foo():
|
||||
3 | ...
|
||||
4 |
|
||||
--------------------------------------------------------------------------------
|
||||
30 | x = f.read()
|
||||
31 |
|
||||
32 | # FURB101
|
||||
- with open("file.txt", mode="r") as f: # noqa: FURB120
|
||||
- x = f.read()
|
||||
33 + x = pathlib.Path("file.txt").read_text()
|
||||
34 |
|
||||
35 | # FURB101
|
||||
36 | with open(foo(), "rb") as f:
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FURB101 `open` and `read` should be replaced by `Path(foo()).read_bytes()`
|
||||
--> FURB101.py:36:6
|
||||
|
|
||||
35 | # FURB101
|
||||
36 | with open(foo(), "rb") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
37 | # The body of `with` is non-trivial, but the recommendation holds.
|
||||
38 | bar("pre")
|
||||
|
|
||||
help: Replace with `Path(foo()).read_bytes()`
|
||||
|
||||
FURB101 `open` and `read` should be replaced by `Path("a.txt").read_text()`
|
||||
--> FURB101.py:44:6
|
||||
|
|
||||
43 | # FURB101
|
||||
44 | with open("a.txt") as a, open("b.txt", "rb") as b:
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
45 | x = a.read()
|
||||
46 | y = b.read()
|
||||
|
|
||||
help: Replace with `Path("a.txt").read_text()`
|
||||
|
||||
FURB101 `open` and `read` should be replaced by `Path("b.txt").read_bytes()`
|
||||
--> FURB101.py:44:26
|
||||
|
|
||||
43 | # FURB101
|
||||
44 | with open("a.txt") as a, open("b.txt", "rb") as b:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
45 | x = a.read()
|
||||
46 | y = b.read()
|
||||
|
|
||||
help: Replace with `Path("b.txt").read_bytes()`
|
||||
|
||||
FURB101 `open` and `read` should be replaced by `Path("file.txt").read_text()`
|
||||
--> FURB101.py:49:18
|
||||
|
|
||||
48 | # FURB101
|
||||
49 | with foo() as a, open("file.txt") as b, foo() as c:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
50 | # We have other things in here, multiple with items, but
|
||||
51 | # the user reads the whole file and that bit they can replace.
|
||||
|
|
||||
help: Replace with `Path("file.txt").read_text()`
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/refurb/mod.rs
|
||||
---
|
||||
FURB103 [*] `open` and `write` should be replaced by `Path("file.txt").write_text("test")`
|
||||
--> FURB103.py:12:6
|
||||
|
|
||||
11 | # FURB103
|
||||
12 | with open("file.txt", "w") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
13 | f.write("test")
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text("test")`
|
||||
1 + import pathlib
|
||||
2 | def foo():
|
||||
3 | ...
|
||||
4 |
|
||||
--------------------------------------------------------------------------------
|
||||
10 | # Errors.
|
||||
11 |
|
||||
12 | # FURB103
|
||||
- with open("file.txt", "w") as f:
|
||||
- f.write("test")
|
||||
13 + pathlib.Path("file.txt").write_text("test")
|
||||
14 |
|
||||
15 | # FURB103
|
||||
16 | with open("file.txt", "wb") as f:
|
||||
|
||||
FURB103 [*] `open` and `write` should be replaced by `Path("file.txt").write_bytes(foobar)`
|
||||
--> FURB103.py:16:6
|
||||
|
|
||||
15 | # FURB103
|
||||
16 | with open("file.txt", "wb") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
17 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_bytes(foobar)`
|
||||
1 + import pathlib
|
||||
2 | def foo():
|
||||
3 | ...
|
||||
4 |
|
||||
--------------------------------------------------------------------------------
|
||||
14 | f.write("test")
|
||||
15 |
|
||||
16 | # FURB103
|
||||
- with open("file.txt", "wb") as f:
|
||||
- f.write(foobar)
|
||||
17 + pathlib.Path("file.txt").write_bytes(foobar)
|
||||
18 |
|
||||
19 | # FURB103
|
||||
20 | with open("file.txt", mode="wb") as f:
|
||||
|
||||
FURB103 [*] `open` and `write` should be replaced by `Path("file.txt").write_bytes(b"abc")`
|
||||
--> FURB103.py:20:6
|
||||
|
|
||||
19 | # FURB103
|
||||
20 | with open("file.txt", mode="wb") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
21 | f.write(b"abc")
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_bytes(b"abc")`
|
||||
1 + import pathlib
|
||||
2 | def foo():
|
||||
3 | ...
|
||||
4 |
|
||||
--------------------------------------------------------------------------------
|
||||
18 | f.write(foobar)
|
||||
19 |
|
||||
20 | # FURB103
|
||||
- with open("file.txt", mode="wb") as f:
|
||||
- f.write(b"abc")
|
||||
21 + pathlib.Path("file.txt").write_bytes(b"abc")
|
||||
22 |
|
||||
23 | # FURB103
|
||||
24 | with open("file.txt", "w", encoding="utf8") as f:
|
||||
|
||||
FURB103 [*] `open` and `write` should be replaced by `Path("file.txt").write_text(foobar, encoding="utf8")`
|
||||
--> FURB103.py:24:6
|
||||
|
|
||||
23 | # FURB103
|
||||
24 | with open("file.txt", "w", encoding="utf8") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
25 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(foobar, encoding="utf8")`
|
||||
1 + import pathlib
|
||||
2 | def foo():
|
||||
3 | ...
|
||||
4 |
|
||||
--------------------------------------------------------------------------------
|
||||
22 | f.write(b"abc")
|
||||
23 |
|
||||
24 | # FURB103
|
||||
- with open("file.txt", "w", encoding="utf8") as f:
|
||||
- f.write(foobar)
|
||||
25 + pathlib.Path("file.txt").write_text(foobar, encoding="utf8")
|
||||
26 |
|
||||
27 | # FURB103
|
||||
28 | with open("file.txt", "w", errors="ignore") as f:
|
||||
|
||||
FURB103 [*] `open` and `write` should be replaced by `Path("file.txt").write_text(foobar, errors="ignore")`
|
||||
--> FURB103.py:28:6
|
||||
|
|
||||
27 | # FURB103
|
||||
28 | with open("file.txt", "w", errors="ignore") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
29 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(foobar, errors="ignore")`
|
||||
1 + import pathlib
|
||||
2 | def foo():
|
||||
3 | ...
|
||||
4 |
|
||||
--------------------------------------------------------------------------------
|
||||
26 | f.write(foobar)
|
||||
27 |
|
||||
28 | # FURB103
|
||||
- with open("file.txt", "w", errors="ignore") as f:
|
||||
- f.write(foobar)
|
||||
29 + pathlib.Path("file.txt").write_text(foobar, errors="ignore")
|
||||
30 |
|
||||
31 | # FURB103
|
||||
32 | with open("file.txt", mode="w") as f:
|
||||
|
||||
FURB103 [*] `open` and `write` should be replaced by `Path("file.txt").write_text(foobar)`
|
||||
--> FURB103.py:32:6
|
||||
|
|
||||
31 | # FURB103
|
||||
32 | with open("file.txt", mode="w") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
33 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(foobar)`
|
||||
1 + import pathlib
|
||||
2 | def foo():
|
||||
3 | ...
|
||||
4 |
|
||||
--------------------------------------------------------------------------------
|
||||
30 | f.write(foobar)
|
||||
31 |
|
||||
32 | # FURB103
|
||||
- with open("file.txt", mode="w") as f:
|
||||
- f.write(foobar)
|
||||
33 + pathlib.Path("file.txt").write_text(foobar)
|
||||
34 |
|
||||
35 | # FURB103
|
||||
36 | with open(foo(), "wb") as f:
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path(foo()).write_bytes(bar())`
|
||||
--> FURB103.py:36:6
|
||||
|
|
||||
35 | # FURB103
|
||||
36 | with open(foo(), "wb") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
37 | # The body of `with` is non-trivial, but the recommendation holds.
|
||||
38 | bar("pre")
|
||||
|
|
||||
help: Replace with `Path(foo()).write_bytes(bar())`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("a.txt").write_text(x)`
|
||||
--> FURB103.py:44:6
|
||||
|
|
||||
43 | # FURB103
|
||||
44 | with open("a.txt", "w") as a, open("b.txt", "wb") as b:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
45 | a.write(x)
|
||||
46 | b.write(y)
|
||||
|
|
||||
help: Replace with `Path("a.txt").write_text(x)`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("b.txt").write_bytes(y)`
|
||||
--> FURB103.py:44:31
|
||||
|
|
||||
43 | # FURB103
|
||||
44 | with open("a.txt", "w") as a, open("b.txt", "wb") as b:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
45 | a.write(x)
|
||||
46 | b.write(y)
|
||||
|
|
||||
help: Replace with `Path("b.txt").write_bytes(y)`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(bar(bar(a + x)))`
|
||||
--> FURB103.py:49:18
|
||||
|
|
||||
48 | # FURB103
|
||||
49 | with foo() as a, open("file.txt", "w") as b, foo() as c:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
50 | # We have other things in here, multiple with items, but the user
|
||||
51 | # writes a single time to file and that bit they can replace.
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(bar(bar(a + x)))`
|
||||
|
||||
FURB103 [*] `open` and `write` should be replaced by `Path("file.txt").write_text(foobar, newline="\r\n")`
|
||||
--> FURB103.py:58:6
|
||||
|
|
||||
57 | # FURB103
|
||||
58 | with open("file.txt", "w", newline="\r\n") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
59 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(foobar, newline="\r\n")`
|
||||
1 + import pathlib
|
||||
2 | def foo():
|
||||
3 | ...
|
||||
4 |
|
||||
--------------------------------------------------------------------------------
|
||||
56 |
|
||||
57 |
|
||||
58 | # FURB103
|
||||
- with open("file.txt", "w", newline="\r\n") as f:
|
||||
- f.write(foobar)
|
||||
59 + pathlib.Path("file.txt").write_text(foobar, newline="\r\n")
|
||||
60 |
|
||||
61 |
|
||||
62 | import builtins
|
||||
|
||||
FURB103 [*] `open` and `write` should be replaced by `Path("file.txt").write_text(foobar, newline="\r\n")`
|
||||
--> FURB103.py:66:6
|
||||
|
|
||||
65 | # FURB103
|
||||
66 | with builtins.open("file.txt", "w", newline="\r\n") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
67 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(foobar, newline="\r\n")`
|
||||
60 |
|
||||
61 |
|
||||
62 | import builtins
|
||||
63 + import pathlib
|
||||
64 |
|
||||
65 |
|
||||
66 | # FURB103
|
||||
- with builtins.open("file.txt", "w", newline="\r\n") as f:
|
||||
- f.write(foobar)
|
||||
67 + pathlib.Path("file.txt").write_text(foobar, newline="\r\n")
|
||||
68 |
|
||||
69 |
|
||||
70 | from builtins import open as o
|
||||
|
||||
FURB103 [*] `open` and `write` should be replaced by `Path("file.txt").write_text(foobar, newline="\r\n")`
|
||||
--> FURB103.py:74:6
|
||||
|
|
||||
73 | # FURB103
|
||||
74 | with o("file.txt", "w", newline="\r\n") as f:
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
75 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(foobar, newline="\r\n")`
|
||||
68 |
|
||||
69 |
|
||||
70 | from builtins import open as o
|
||||
71 + import pathlib
|
||||
72 |
|
||||
73 |
|
||||
74 | # FURB103
|
||||
- with o("file.txt", "w", newline="\r\n") as f:
|
||||
- f.write(foobar)
|
||||
75 + pathlib.Path("file.txt").write_text(foobar, newline="\r\n")
|
||||
76 |
|
||||
77 | # Non-errors.
|
||||
78 |
|
||||
|
|
@ -9,6 +9,7 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text("t
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
13 | f.write("test")
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text("test")`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_bytes(foobar)`
|
||||
--> FURB103.py:16:6
|
||||
|
|
@ -18,6 +19,7 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_bytes(f
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
17 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_bytes(foobar)`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_bytes(b"abc")`
|
||||
--> FURB103.py:20:6
|
||||
|
|
@ -27,6 +29,7 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_bytes(b
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
21 | f.write(b"abc")
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_bytes(b"abc")`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(foobar, encoding="utf8")`
|
||||
--> FURB103.py:24:6
|
||||
|
|
@ -36,6 +39,7 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(fo
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
25 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(foobar, encoding="utf8")`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(foobar, errors="ignore")`
|
||||
--> FURB103.py:28:6
|
||||
|
|
@ -45,6 +49,7 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(fo
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
29 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(foobar, errors="ignore")`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(foobar)`
|
||||
--> FURB103.py:32:6
|
||||
|
|
@ -54,6 +59,7 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(fo
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
33 | f.write(foobar)
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(foobar)`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path(foo()).write_bytes(bar())`
|
||||
--> FURB103.py:36:6
|
||||
|
|
@ -64,6 +70,7 @@ FURB103 `open` and `write` should be replaced by `Path(foo()).write_bytes(bar())
|
|||
37 | # The body of `with` is non-trivial, but the recommendation holds.
|
||||
38 | bar("pre")
|
||||
|
|
||||
help: Replace with `Path(foo()).write_bytes(bar())`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("a.txt").write_text(x)`
|
||||
--> FURB103.py:44:6
|
||||
|
|
@ -74,6 +81,7 @@ FURB103 `open` and `write` should be replaced by `Path("a.txt").write_text(x)`
|
|||
45 | a.write(x)
|
||||
46 | b.write(y)
|
||||
|
|
||||
help: Replace with `Path("a.txt").write_text(x)`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("b.txt").write_bytes(y)`
|
||||
--> FURB103.py:44:31
|
||||
|
|
@ -84,6 +92,7 @@ FURB103 `open` and `write` should be replaced by `Path("b.txt").write_bytes(y)`
|
|||
45 | a.write(x)
|
||||
46 | b.write(y)
|
||||
|
|
||||
help: Replace with `Path("b.txt").write_bytes(y)`
|
||||
|
||||
FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(bar(bar(a + x)))`
|
||||
--> FURB103.py:49:18
|
||||
|
|
@ -94,3 +103,4 @@ FURB103 `open` and `write` should be replaced by `Path("file.txt").write_text(ba
|
|||
50 | # We have other things in here, multiple with items, but the user
|
||||
51 | # writes a single time to file and that bit they can replace.
|
||||
|
|
||||
help: Replace with `Path("file.txt").write_text(bar(bar(a + x)))`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue