Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ def bar(x):
with open("file.txt", buffering=1) as f:
x = f.read()

# force CRLF, not supported in read_text()
# FURB101 (newline is supported in read_text on Python 3.13+)
with open("file.txt", newline="\r\n") as f:
x = f.read()

# dont mistake "newline" for "mode"
# FURB101 (dont mistake "newline" for "mode")
with open("file.txt", newline="b") as f:
x = f.read()

Expand Down
13 changes: 13 additions & 0 deletions crates/ruff_linter/resources/test/fixtures/refurb/FURB101_3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Tests for Python 3.13+ where `pathlib.Path.read_text` supports `newline`.

# FURB101 (newline is supported in read_text on Python 3.13+)
with open("file.txt", newline="\r\n") as f:
x = f.read()

# FURB101 (newline with encoding)
with open("file.txt", encoding="utf-8", newline="") as f:
x = f.read()

# FURB101 (newline=None is also valid)
with open("file.txt", newline=None) as f:
x = f.read()
8 changes: 5 additions & 3 deletions crates/ruff_linter/src/rules/refurb/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,10 +366,12 @@ fn match_open_keywords(
"encoding" | "errors" => result.push(keyword),
"newline" => {
if read_mode {
// newline is only valid for write_text
return None;
if target_version < PythonVersion::PY313 {
// `pathlib.Path.read_text` doesn't support `newline` until Python 3.13.
return None;
}
} else if target_version < PythonVersion::PY310 {
// `pathlib` doesn't support `newline` until Python 3.10.
// `pathlib.Path.write_text` doesn't support `newline` until Python 3.10.
return None;
}

Expand Down
14 changes: 13 additions & 1 deletion crates/ruff_linter/src/rules/refurb/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ mod tests {

use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_diagnostics, settings};
use crate::{assert_diagnostics, assert_diagnostics_diff, settings};

#[test_case(Rule::ReadWholeFile, Path::new("FURB101_0.py"))]
#[test_case(Rule::ReadWholeFile, Path::new("FURB101_1.py"))]
Expand Down Expand Up @@ -66,6 +66,18 @@ mod tests {
Ok(())
}

#[test]
fn read_whole_file_newline_python_version_diff() -> Result<()> {
assert_diagnostics_diff!(
Path::new("refurb/FURB101_3.py"),
&settings::LinterSettings::for_rule(Rule::ReadWholeFile)
.with_target_version(PythonVersion::PY313),
&settings::LinterSettings::for_rule(Rule::ReadWholeFile)
.with_target_version(PythonVersion::PY312),
);
Ok(())
}

#[test]
fn write_whole_file_python_39() -> Result<()> {
let diagnostics = test_path(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,54 @@ FURB101 `open` and `read` should be replaced by `Path("file.txt").read_text()`
|
help: Replace with `Path("file.txt").read_text()`

FURB101 [*] `open` and `read` should be replaced by `Path("file.txt").read_text(newline="\r\n")`
--> FURB101_0.py:85:6
|
84 | # FURB101 (newline is supported in read_text on Python 3.13+)
85 | with open("file.txt", newline="\r\n") as f:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
86 | x = f.read()
|
help: Replace with `Path("file.txt").read_text(newline="\r\n")`
1 + import pathlib
2 | def foo():
3 | ...
4 |
--------------------------------------------------------------------------------
83 | x = f.read()
84 |
85 | # FURB101 (newline is supported in read_text on Python 3.13+)
- with open("file.txt", newline="\r\n") as f:
- x = f.read()
86 + x = pathlib.Path("file.txt").read_text(newline="\r\n")
87 |
88 | # FURB101 (dont mistake "newline" for "mode")
89 | with open("file.txt", newline="b") as f:

FURB101 [*] `open` and `read` should be replaced by `Path("file.txt").read_text(newline="b")`
--> FURB101_0.py:89:6
|
88 | # FURB101 (dont mistake "newline" for "mode")
89 | with open("file.txt", newline="b") as f:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
90 | x = f.read()
|
help: Replace with `Path("file.txt").read_text(newline="b")`
1 + import pathlib
2 | def foo():
3 | ...
4 |
--------------------------------------------------------------------------------
87 | x = f.read()
88 |
89 | # FURB101 (dont mistake "newline" for "mode")
- with open("file.txt", newline="b") as f:
- x = f.read()
90 + x = pathlib.Path("file.txt").read_text(newline="b")
91 |
92 | # I guess we can possibly also report this case, but the question
93 | # is why the user would put "r+" here in the first place.

FURB101 [*] `open` and `read` should be replaced by `Path("file.txt").read_text(encoding="utf-8")`
--> FURB101_0.py:130:6
|
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---
source: crates/ruff_linter/src/rules/refurb/mod.rs
---
--- Linter settings ---
-linter.unresolved_target_version = 3.13
+linter.unresolved_target_version = 3.12

--- Summary ---
Removed: 3
Added: 0

--- Removed ---
FURB101 [*] `open` and `read` should be replaced by `Path("file.txt").read_text(newline="\r\n")`
--> FURB101_3.py:4:6
|
3 | # FURB101 (newline is supported in read_text on Python 3.13+)
4 | with open("file.txt", newline="\r\n") as f:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 | x = f.read()
|
help: Replace with `Path("file.txt").read_text(newline="\r\n")`
1 | # Tests for Python 3.13+ where `pathlib.Path.read_text` supports `newline`.
2 |
3 | # FURB101 (newline is supported in read_text on Python 3.13+)
- with open("file.txt", newline="\r\n") as f:
- x = f.read()
4 + import pathlib
5 + x = pathlib.Path("file.txt").read_text(newline="\r\n")
6 |
7 | # FURB101 (newline with encoding)
8 | with open("file.txt", encoding="utf-8", newline="") as f:


FURB101 [*] `open` and `read` should be replaced by `Path("file.txt").read_text(encoding="utf-8", newline="")`
--> FURB101_3.py:8:6
|
7 | # FURB101 (newline with encoding)
8 | with open("file.txt", encoding="utf-8", newline="") as f:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9 | x = f.read()
|
help: Replace with `Path("file.txt").read_text(encoding="utf-8", newline="")`
1 | # Tests for Python 3.13+ where `pathlib.Path.read_text` supports `newline`.
2 |
3 | # FURB101 (newline is supported in read_text on Python 3.13+)
4 + import pathlib
5 | with open("file.txt", newline="\r\n") as f:
6 | x = f.read()
7 |
8 | # FURB101 (newline with encoding)
- with open("file.txt", encoding="utf-8", newline="") as f:
- x = f.read()
9 + x = pathlib.Path("file.txt").read_text(encoding="utf-8", newline="")
10 |
11 | # FURB101 (newline=None is also valid)
12 | with open("file.txt", newline=None) as f:


FURB101 [*] `open` and `read` should be replaced by `Path("file.txt").read_text(newline=None)`
--> FURB101_3.py:12:6
|
11 | # FURB101 (newline=None is also valid)
12 | with open("file.txt", newline=None) as f:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13 | x = f.read()
|
help: Replace with `Path("file.txt").read_text(newline=None)`
1 | # Tests for Python 3.13+ where `pathlib.Path.read_text` supports `newline`.
2 |
3 | # FURB101 (newline is supported in read_text on Python 3.13+)
4 + import pathlib
5 | with open("file.txt", newline="\r\n") as f:
6 | x = f.read()
7 |
--------------------------------------------------------------------------------
10 | x = f.read()
11 |
12 | # FURB101 (newline=None is also valid)
- with open("file.txt", newline=None) as f:
- x = f.read()
13 + x = pathlib.Path("file.txt").read_text(newline=None)