Skip to content

Commit 07b293d

Browse files
Add fix to automatically remove print and pprint statements (#9208)
Closes #9207.
1 parent 5ccc21a commit 07b293d

File tree

3 files changed

+98
-10
lines changed

3 files changed

+98
-10
lines changed

crates/ruff_linter/src/rules/flake8_print/rules/print_call.rs

+34-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use ruff_diagnostics::{Diagnostic, Violation};
1+
use ruff_diagnostics::{Diagnostic, Fix, FixAvailability, Violation};
22
use ruff_macros::{derive_message_formats, violation};
3-
4-
use ruff_python_ast::{self as ast};
3+
use ruff_python_ast as ast;
54
use ruff_text_size::Ranged;
65

76
use crate::checkers::ast::Checker;
7+
use crate::fix::edits::delete_stmt;
88
use crate::registry::AsRule;
99

1010
/// ## What it does
@@ -28,14 +28,24 @@ use crate::registry::AsRule;
2828
/// def add_numbers(a, b):
2929
/// return a + b
3030
/// ```
31+
///
32+
/// ## Fix safety
33+
/// This rule's fix is marked as unsafe, as it may remove `print` statements
34+
/// that are used beyond debugging purposes.
3135
#[violation]
3236
pub struct Print;
3337

3438
impl Violation for Print {
39+
const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes;
40+
3541
#[derive_message_formats]
3642
fn message(&self) -> String {
3743
format!("`print` found")
3844
}
45+
46+
fn fix_title(&self) -> Option<String> {
47+
Some("Remove `print`".to_string())
48+
}
3949
}
4050

4151
/// ## What it does
@@ -65,19 +75,29 @@ impl Violation for Print {
6575
/// dict_c = {**dict_a, **dict_b}
6676
/// return dict_c
6777
/// ```
78+
///
79+
/// ## Fix safety
80+
/// This rule's fix is marked as unsafe, as it may remove `pprint` statements
81+
/// that are used beyond debugging purposes.
6882
#[violation]
6983
pub struct PPrint;
7084

7185
impl Violation for PPrint {
86+
const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes;
87+
7288
#[derive_message_formats]
7389
fn message(&self) -> String {
7490
format!("`pprint` found")
7591
}
92+
93+
fn fix_title(&self) -> Option<String> {
94+
Some("Remove `pprint`".to_string())
95+
}
7696
}
7797

7898
/// T201, T203
7999
pub(crate) fn print_call(checker: &mut Checker, call: &ast::ExprCall) {
80-
let diagnostic = {
100+
let mut diagnostic = {
81101
let call_path = checker.semantic().resolve_call_path(&call.func);
82102
if call_path
83103
.as_ref()
@@ -113,5 +133,15 @@ pub(crate) fn print_call(checker: &mut Checker, call: &ast::ExprCall) {
113133
return;
114134
}
115135

136+
// Remove the `print`, if it's a standalone statement.
137+
if checker.semantic().current_expression_parent().is_none() {
138+
let statement = checker.semantic().current_statement();
139+
let parent = checker.semantic().current_statement_parent();
140+
let edit = delete_stmt(statement, parent, checker.locator(), checker.indexer());
141+
diagnostic.set_fix(Fix::unsafe_edit(edit).isolate(Checker::isolation(
142+
checker.semantic().current_statement_parent_id(),
143+
)));
144+
}
145+
116146
checker.diagnostics.push(diagnostic);
117147
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
source: crates/ruff_linter/src/rules/flake8_print/mod.rs
33
---
4-
T201.py:4:1: T201 `print` found
4+
T201.py:4:1: T201 [*] `print` found
55
|
66
2 | import tempfile
77
3 |
@@ -10,26 +10,56 @@ T201.py:4:1: T201 `print` found
1010
5 | print("Hello, world!", file=None) # T201
1111
6 | print("Hello, world!", file=sys.stdout) # T201
1212
|
13+
= help: Remove `print`
1314

14-
T201.py:5:1: T201 `print` found
15+
Unsafe fix
16+
1 1 | import sys
17+
2 2 | import tempfile
18+
3 3 |
19+
4 |-print("Hello, world!") # T201
20+
5 4 | print("Hello, world!", file=None) # T201
21+
6 5 | print("Hello, world!", file=sys.stdout) # T201
22+
7 6 | print("Hello, world!", file=sys.stderr) # T201
23+
24+
T201.py:5:1: T201 [*] `print` found
1525
|
1626
4 | print("Hello, world!") # T201
1727
5 | print("Hello, world!", file=None) # T201
1828
| ^^^^^ T201
1929
6 | print("Hello, world!", file=sys.stdout) # T201
2030
7 | print("Hello, world!", file=sys.stderr) # T201
2131
|
32+
= help: Remove `print`
33+
34+
Unsafe fix
35+
2 2 | import tempfile
36+
3 3 |
37+
4 4 | print("Hello, world!") # T201
38+
5 |-print("Hello, world!", file=None) # T201
39+
6 5 | print("Hello, world!", file=sys.stdout) # T201
40+
7 6 | print("Hello, world!", file=sys.stderr) # T201
41+
8 7 |
2242

23-
T201.py:6:1: T201 `print` found
43+
T201.py:6:1: T201 [*] `print` found
2444
|
2545
4 | print("Hello, world!") # T201
2646
5 | print("Hello, world!", file=None) # T201
2747
6 | print("Hello, world!", file=sys.stdout) # T201
2848
| ^^^^^ T201
2949
7 | print("Hello, world!", file=sys.stderr) # T201
3050
|
51+
= help: Remove `print`
3152

32-
T201.py:7:1: T201 `print` found
53+
Unsafe fix
54+
3 3 |
55+
4 4 | print("Hello, world!") # T201
56+
5 5 | print("Hello, world!", file=None) # T201
57+
6 |-print("Hello, world!", file=sys.stdout) # T201
58+
7 6 | print("Hello, world!", file=sys.stderr) # T201
59+
8 7 |
60+
9 8 | with tempfile.NamedTemporaryFile() as fp:
61+
62+
T201.py:7:1: T201 [*] `print` found
3363
|
3464
5 | print("Hello, world!", file=None) # T201
3565
6 | print("Hello, world!", file=sys.stdout) # T201
@@ -38,5 +68,15 @@ T201.py:7:1: T201 `print` found
3868
8 |
3969
9 | with tempfile.NamedTemporaryFile() as fp:
4070
|
71+
= help: Remove `print`
72+
73+
Unsafe fix
74+
4 4 | print("Hello, world!") # T201
75+
5 5 | print("Hello, world!", file=None) # T201
76+
6 6 | print("Hello, world!", file=sys.stdout) # T201
77+
7 |-print("Hello, world!", file=sys.stderr) # T201
78+
8 7 |
79+
9 8 | with tempfile.NamedTemporaryFile() as fp:
80+
10 9 | print("Hello, world!", file=fp) # OK
4181

4282

Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
source: crates/ruff_linter/src/rules/flake8_print/mod.rs
33
---
4-
T203.py:3:1: T203 `pprint` found
4+
T203.py:3:1: T203 [*] `pprint` found
55
|
66
1 | from pprint import pprint
77
2 |
@@ -10,8 +10,17 @@ T203.py:3:1: T203 `pprint` found
1010
4 |
1111
5 | import pprint
1212
|
13+
= help: Remove `pprint`
1314

14-
T203.py:7:1: T203 `pprint` found
15+
Unsafe fix
16+
1 1 | from pprint import pprint
17+
2 2 |
18+
3 |-pprint("Hello, world!") # T203
19+
4 3 |
20+
5 4 | import pprint
21+
6 5 |
22+
23+
T203.py:7:1: T203 [*] `pprint` found
1524
|
1625
5 | import pprint
1726
6 |
@@ -20,5 +29,14 @@ T203.py:7:1: T203 `pprint` found
2029
8 |
2130
9 | pprint.pformat("Hello, world!")
2231
|
32+
= help: Remove `pprint`
33+
34+
Unsafe fix
35+
4 4 |
36+
5 5 | import pprint
37+
6 6 |
38+
7 |-pprint.pprint("Hello, world!") # T203
39+
8 7 |
40+
9 8 | pprint.pformat("Hello, world!")
2341

2442

0 commit comments

Comments
 (0)