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
14 changes: 14 additions & 0 deletions crates/ruff_linter/resources/test/fixtures/flake8_print/T203.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import sys
import tempfile
from pprint import pprint

pprint("Hello, world!") # T203
pprint("Hello, world!", stream=None) # T203
pprint("Hello, world!", stream=sys.stdout) # T203
pprint("Hello, world!", stream=sys.stderr) # T203

with tempfile.NamedTemporaryFile() as fp:
pprint("Hello, world!", stream=fp) # OK

import pprint

pprint.pprint("Hello, world!") # T203
pprint.pprint("Hello, world!", stream=None) # T203
pprint.pprint("Hello, world!", stream=sys.stdout) # T203
pprint.pprint("Hello, world!", stream=sys.stderr) # T203

with tempfile.NamedTemporaryFile() as fp:
pprint.pprint("Hello, world!", stream=fp) # OK

pprint.pformat("Hello, world!")
37 changes: 26 additions & 11 deletions crates/ruff_linter/src/rules/flake8_print/rules/print_call.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast;
use ruff_python_semantic::SemanticModel;
use ruff_text_size::Ranged;

use crate::checkers::ast::Checker;
Expand Down Expand Up @@ -130,20 +131,19 @@ pub(crate) fn print_call(checker: &Checker, call: &ast::ExprCall) {
["" | "builtins", "print"] => {
// If the print call has a `file=` argument (that isn't `None`, `"sys.stdout"`,
// or `"sys.stderr"`), don't trigger T201.
if let Some(keyword) = call.arguments.find_keyword("file") {
if !keyword.value.is_none_literal_expr() {
if semantic.resolve_qualified_name(&keyword.value).is_none_or(
|qualified_name| {
!matches!(qualified_name.segments(), ["sys", "stdout" | "stderr"])
},
) {
return;
}
}
if has_non_default_output_target(semantic, call, "file") {
return;
}
checker.report_diagnostic_if_enabled(Print, call.func.range())
}
["pprint", "pprint"] => checker.report_diagnostic_if_enabled(PPrint, call.func.range()),
["pprint", "pprint"] => {
// If the pprint call has a `stream=` argument (that isn't `None`,
// `"sys.stdout"`, or `"sys.stderr"`), don't trigger T203.
if has_non_default_output_target(semantic, call, "stream") {
return;
}
checker.report_diagnostic_if_enabled(PPrint, call.func.range())
}
_ => return,
};

Expand All @@ -162,3 +162,18 @@ pub(crate) fn print_call(checker: &Checker, call: &ast::ExprCall) {
);
}
}

fn has_non_default_output_target(
semantic: &SemanticModel,
call: &ast::ExprCall,
keyword: &str,
) -> bool {
call.arguments.find_keyword(keyword).is_some_and(|keyword| {
!keyword.value.is_none_literal_expr()
&& semantic
.resolve_qualified_name(&keyword.value)
.is_none_or(|qualified_name| {
!matches!(qualified_name.segments(), ["sys", "stdout" | "stderr"])
})
})
}
Original file line number Diff line number Diff line change
@@ -1,40 +1,159 @@
---
source: crates/ruff_linter/src/rules/flake8_print/mod.rs
assertion_line: 23
---
T203 [*] `pprint` found
--> T203.py:3:1
--> T203.py:5:1
|
1 | from pprint import pprint
2 |
3 | pprint("Hello, world!") # T203
| ^^^^^^
3 | from pprint import pprint
4 |
5 | import pprint
5 | pprint("Hello, world!") # T203
| ^^^^^^
6 | pprint("Hello, world!", stream=None) # T203
7 | pprint("Hello, world!", stream=sys.stdout) # T203
|
help: Remove `pprint`
1 | from pprint import pprint
2 |
2 | import tempfile
3 | from pprint import pprint
4 |
- pprint("Hello, world!") # T203
3 |
4 | import pprint
5 |
5 | pprint("Hello, world!", stream=None) # T203
6 | pprint("Hello, world!", stream=sys.stdout) # T203
7 | pprint("Hello, world!", stream=sys.stderr) # T203
note: This is an unsafe fix and may change runtime behavior

T203 [*] `pprint` found
--> T203.py:6:1
|
5 | pprint("Hello, world!") # T203
6 | pprint("Hello, world!", stream=None) # T203
| ^^^^^^
7 | pprint("Hello, world!", stream=sys.stdout) # T203
8 | pprint("Hello, world!", stream=sys.stderr) # T203
|
help: Remove `pprint`
3 | from pprint import pprint
4 |
5 | pprint("Hello, world!") # T203
- pprint("Hello, world!", stream=None) # T203
6 | pprint("Hello, world!", stream=sys.stdout) # T203
7 | pprint("Hello, world!", stream=sys.stderr) # T203
8 |
note: This is an unsafe fix and may change runtime behavior

T203 [*] `pprint` found
--> T203.py:7:1
|
5 | import pprint
6 |
7 | pprint.pprint("Hello, world!") # T203
| ^^^^^^^^^^^^^
8 |
9 | pprint.pformat("Hello, world!")
5 | pprint("Hello, world!") # T203
6 | pprint("Hello, world!", stream=None) # T203
7 | pprint("Hello, world!", stream=sys.stdout) # T203
| ^^^^^^
8 | pprint("Hello, world!", stream=sys.stderr) # T203
|
help: Remove `pprint`
4 |
5 | import pprint
6 |
- pprint.pprint("Hello, world!") # T203
7 |
8 | pprint.pformat("Hello, world!")
5 | pprint("Hello, world!") # T203
6 | pprint("Hello, world!", stream=None) # T203
- pprint("Hello, world!", stream=sys.stdout) # T203
7 | pprint("Hello, world!", stream=sys.stderr) # T203
8 |
9 | with tempfile.NamedTemporaryFile() as fp:
note: This is an unsafe fix and may change runtime behavior

T203 [*] `pprint` found
--> T203.py:8:1
|
6 | pprint("Hello, world!", stream=None) # T203
7 | pprint("Hello, world!", stream=sys.stdout) # T203
8 | pprint("Hello, world!", stream=sys.stderr) # T203
| ^^^^^^
9 |
10 | with tempfile.NamedTemporaryFile() as fp:
|
help: Remove `pprint`
5 | pprint("Hello, world!") # T203
6 | pprint("Hello, world!", stream=None) # T203
7 | pprint("Hello, world!", stream=sys.stdout) # T203
- pprint("Hello, world!", stream=sys.stderr) # T203
8 |
9 | with tempfile.NamedTemporaryFile() as fp:
10 | pprint("Hello, world!", stream=fp) # OK
note: This is an unsafe fix and may change runtime behavior

T203 [*] `pprint` found
--> T203.py:15:1
|
13 | import pprint
14 |
15 | pprint.pprint("Hello, world!") # T203
| ^^^^^^^^^^^^^
16 | pprint.pprint("Hello, world!", stream=None) # T203
17 | pprint.pprint("Hello, world!", stream=sys.stdout) # T203
|
help: Remove `pprint`
12 |
13 | import pprint
14 |
- pprint.pprint("Hello, world!") # T203
15 | pprint.pprint("Hello, world!", stream=None) # T203
16 | pprint.pprint("Hello, world!", stream=sys.stdout) # T203
17 | pprint.pprint("Hello, world!", stream=sys.stderr) # T203
note: This is an unsafe fix and may change runtime behavior

T203 [*] `pprint` found
--> T203.py:16:1
|
15 | pprint.pprint("Hello, world!") # T203
16 | pprint.pprint("Hello, world!", stream=None) # T203
| ^^^^^^^^^^^^^
17 | pprint.pprint("Hello, world!", stream=sys.stdout) # T203
18 | pprint.pprint("Hello, world!", stream=sys.stderr) # T203
|
help: Remove `pprint`
13 | import pprint
14 |
15 | pprint.pprint("Hello, world!") # T203
- pprint.pprint("Hello, world!", stream=None) # T203
16 | pprint.pprint("Hello, world!", stream=sys.stdout) # T203
17 | pprint.pprint("Hello, world!", stream=sys.stderr) # T203
18 |
note: This is an unsafe fix and may change runtime behavior

T203 [*] `pprint` found
--> T203.py:17:1
|
15 | pprint.pprint("Hello, world!") # T203
16 | pprint.pprint("Hello, world!", stream=None) # T203
17 | pprint.pprint("Hello, world!", stream=sys.stdout) # T203
| ^^^^^^^^^^^^^
18 | pprint.pprint("Hello, world!", stream=sys.stderr) # T203
|
help: Remove `pprint`
14 |
15 | pprint.pprint("Hello, world!") # T203
16 | pprint.pprint("Hello, world!", stream=None) # T203
- pprint.pprint("Hello, world!", stream=sys.stdout) # T203
17 | pprint.pprint("Hello, world!", stream=sys.stderr) # T203
18 |
19 | with tempfile.NamedTemporaryFile() as fp:
note: This is an unsafe fix and may change runtime behavior

T203 [*] `pprint` found
--> T203.py:18:1
|
16 | pprint.pprint("Hello, world!", stream=None) # T203
17 | pprint.pprint("Hello, world!", stream=sys.stdout) # T203
18 | pprint.pprint("Hello, world!", stream=sys.stderr) # T203
| ^^^^^^^^^^^^^
19 |
20 | with tempfile.NamedTemporaryFile() as fp:
|
help: Remove `pprint`
15 | pprint.pprint("Hello, world!") # T203
16 | pprint.pprint("Hello, world!", stream=None) # T203
17 | pprint.pprint("Hello, world!", stream=sys.stdout) # T203
- pprint.pprint("Hello, world!", stream=sys.stderr) # T203
18 |
19 | with tempfile.NamedTemporaryFile() as fp:
20 | pprint.pprint("Hello, world!", stream=fp) # OK
note: This is an unsafe fix and may change runtime behavior