[`refurb`] Mark autofix as safe only for number literals in `FURB116` (#17692)

<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary
We can only guarantee the safety of the autofix for number literals, all
other cases may change the runtime behaviour of the program or introduce
a syntax error. For the cases reported in the issue that would result in
a syntax error, I disabled the autofix.

Follow-up of #17661. 

Fixes #16472.
<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan

Snapshot tests.
<!-- How was it tested? -->
This commit is contained in:
Victor Hugo Gomes 2025-05-12 17:08:12 -03:00 committed by GitHub
parent 138ab91def
commit c9031ce59f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 602 additions and 123 deletions

View File

@ -1,3 +1,6 @@
import datetime
import sys
num = 1337 num = 1337
def return_num() -> int: def return_num() -> int:
@ -10,6 +13,7 @@ print(bin(num)[2:]) # FURB116
print(oct(1337)[2:]) # FURB116 print(oct(1337)[2:]) # FURB116
print(hex(1337)[2:]) # FURB116 print(hex(1337)[2:]) # FURB116
print(bin(1337)[2:]) # FURB116 print(bin(1337)[2:]) # FURB116
print(bin(+1337)[2:]) # FURB116
print(bin(return_num())[2:]) # FURB116 (no autofix) print(bin(return_num())[2:]) # FURB116 (no autofix)
print(bin(int(f"{num}"))[2:]) # FURB116 (no autofix) print(bin(int(f"{num}"))[2:]) # FURB116 (no autofix)
@ -22,3 +26,19 @@ print(hex(0x1337)[3:])
# float and complex numbers should be ignored # float and complex numbers should be ignored
print(bin(1.0)[2:]) print(bin(1.0)[2:])
print(bin(3.14j)[2:]) print(bin(3.14j)[2:])
d = datetime.datetime.now(tz=datetime.UTC)
# autofix is display-only
print(bin(d)[2:])
# no autofix for Python 3.11 and earlier, as it introduces a syntax error
print(bin(len("xyz").numerator)[2:])
# autofix is display-only
print(bin({0: 1}[0].numerator)[2:])
# no autofix for Python 3.11 and earlier, as it introduces a syntax error
print(bin(ord("\\").numerator)[2:])
print(hex(sys
.maxunicode)[2:])
# for negatives numbers autofix is display-only
print(bin(-1)[2:])

View File

@ -89,4 +89,15 @@ mod tests {
assert_messages!(diagnostics); assert_messages!(diagnostics);
Ok(()) Ok(())
} }
#[test]
fn fstring_number_format_python_311() -> Result<()> {
let diagnostics = test_path(
Path::new("refurb/FURB116.py"),
&settings::LinterSettings::for_rule(Rule::FStringNumberFormat)
.with_target_version(PythonVersion::PY311),
)?;
assert_messages!(diagnostics);
Ok(())
}
} }

View File

@ -1,6 +1,7 @@
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_diagnostics::{Applicability, Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, ViolationMetadata}; use ruff_macros::{derive_message_formats, ViolationMetadata};
use ruff_python_ast::{self as ast, Expr, ExprCall, Number}; use ruff_python_ast::{self as ast, Expr, ExprCall, Number, PythonVersion, UnaryOp};
use ruff_source_file::find_newline;
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -24,6 +25,11 @@ use crate::fix::snippet::SourceCodeSnippet;
/// ```python /// ```python
/// print(f"{1337:b}") /// print(f"{1337:b}")
/// ``` /// ```
///
/// ## Fix safety
/// The fix is only marked as safe for integer literals, all other cases
/// are display-only, as they may change the runtime behaviour of the program
/// or introduce syntax errors.
#[derive(ViolationMetadata)] #[derive(ViolationMetadata)]
pub(crate) struct FStringNumberFormat { pub(crate) struct FStringNumberFormat {
replacement: Option<SourceCodeSnippet>, replacement: Option<SourceCodeSnippet>,
@ -121,21 +127,24 @@ pub(crate) fn fstring_number_format(checker: &Checker, subscript: &ast::ExprSubs
return; return;
} }
// Generate a replacement, if possible. let maybe_number = if let Some(maybe_number) = arg
let replacement = if matches!( .as_unary_op_expr()
arg, .filter(|unary_expr| unary_expr.op == UnaryOp::UAdd)
Expr::NumberLiteral(_) | Expr::Name(_) | Expr::Attribute(_) .map(|unary_expr| &unary_expr.operand)
) { {
let inner_source = checker.locator().slice(arg); maybe_number
let quote = checker.stylist().quote();
let shorthand = base.shorthand();
Some(format!("f{quote}{{{inner_source}:{shorthand}}}{quote}"))
} else { } else {
None arg
}; };
let applicability = if matches!(maybe_number, Expr::NumberLiteral(_)) {
Applicability::Safe
} else {
Applicability::DisplayOnly
};
let replacement = try_create_replacement(checker, arg, base);
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
FStringNumberFormat { FStringNumberFormat {
replacement: replacement.as_deref().map(SourceCodeSnippet::from_str), replacement: replacement.as_deref().map(SourceCodeSnippet::from_str),
@ -145,15 +154,54 @@ pub(crate) fn fstring_number_format(checker: &Checker, subscript: &ast::ExprSubs
); );
if let Some(replacement) = replacement { if let Some(replacement) = replacement {
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( let edit = Edit::range_replacement(replacement, subscript.range());
replacement, diagnostic.set_fix(Fix::applicable_edit(edit, applicability));
subscript.range(),
)));
} }
checker.report_diagnostic(diagnostic); checker.report_diagnostic(diagnostic);
} }
/// Generate a replacement, if possible.
fn try_create_replacement(checker: &Checker, arg: &Expr, base: Base) -> Option<String> {
if !matches!(
arg,
Expr::NumberLiteral(_) | Expr::Name(_) | Expr::Attribute(_) | Expr::UnaryOp(_)
) {
return None;
}
let inner_source = checker.locator().slice(arg);
// On Python 3.11 and earlier, trying to replace an `arg` that contains a backslash
// would create a `SyntaxError` in the f-string.
if checker.target_version() <= PythonVersion::PY311 && inner_source.contains('\\') {
return None;
}
// On Python 3.11 and earlier, trying to replace an `arg` that spans multiple lines
// would create a `SyntaxError` in the f-string.
if checker.target_version() <= PythonVersion::PY311 && find_newline(inner_source).is_some() {
return None;
}
let quote = checker.stylist().quote();
let shorthand = base.shorthand();
// If the `arg` contains double quotes we need to create the f-string with single quotes
// to avoid a `SyntaxError` in Python 3.11 and earlier.
if checker.target_version() <= PythonVersion::PY311 && inner_source.contains(quote.as_str()) {
return None;
}
// If the `arg` contains a brace add an space before it to avoid a `SyntaxError`
// in the f-string.
if inner_source.starts_with('{') {
Some(format!("f{quote}{{ {inner_source}:{shorthand}}}{quote}"))
} else {
Some(format!("f{quote}{{{inner_source}:{shorthand}}}{quote}"))
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum Base { enum Base {
Hex, Hex,

View File

@ -1,144 +1,288 @@
--- ---
source: crates/ruff_linter/src/rules/refurb/mod.rs source: crates/ruff_linter/src/rules/refurb/mod.rs
--- ---
FURB116.py:6:7: FURB116 [*] Replace `oct` call with `f"{num:o}"` FURB116.py:9:7: FURB116 Replace `oct` call with `f"{num:o}"`
|
4 | return num
5 |
6 | print(oct(num)[2:]) # FURB116
| ^^^^^^^^^^^^ FURB116
7 | print(hex(num)[2:]) # FURB116
8 | print(bin(num)[2:]) # FURB116
|
= help: Replace with `f"{num:o}"`
Safe fix
3 3 | def return_num() -> int:
4 4 | return num
5 5 |
6 |-print(oct(num)[2:]) # FURB116
6 |+print(f"{num:o}") # FURB116
7 7 | print(hex(num)[2:]) # FURB116
8 8 | print(bin(num)[2:]) # FURB116
9 9 |
FURB116.py:7:7: FURB116 [*] Replace `hex` call with `f"{num:x}"`
|
6 | print(oct(num)[2:]) # FURB116
7 | print(hex(num)[2:]) # FURB116
| ^^^^^^^^^^^^ FURB116
8 | print(bin(num)[2:]) # FURB116
|
= help: Replace with `f"{num:x}"`
Safe fix
4 4 | return num
5 5 |
6 6 | print(oct(num)[2:]) # FURB116
7 |-print(hex(num)[2:]) # FURB116
7 |+print(f"{num:x}") # FURB116
8 8 | print(bin(num)[2:]) # FURB116
9 9 |
10 10 | print(oct(1337)[2:]) # FURB116
FURB116.py:8:7: FURB116 [*] Replace `bin` call with `f"{num:b}"`
| |
6 | print(oct(num)[2:]) # FURB116 7 | return num
7 | print(hex(num)[2:]) # FURB116 8 |
8 | print(bin(num)[2:]) # FURB116 9 | print(oct(num)[2:]) # FURB116
| ^^^^^^^^^^^^ FURB116 | ^^^^^^^^^^^^ FURB116
9 | 10 | print(hex(num)[2:]) # FURB116
10 | print(oct(1337)[2:]) # FURB116 11 | print(bin(num)[2:]) # FURB116
|
= help: Replace with `f"{num:o}"`
Display-only fix
6 6 | def return_num() -> int:
7 7 | return num
8 8 |
9 |-print(oct(num)[2:]) # FURB116
9 |+print(f"{num:o}") # FURB116
10 10 | print(hex(num)[2:]) # FURB116
11 11 | print(bin(num)[2:]) # FURB116
12 12 |
FURB116.py:10:7: FURB116 Replace `hex` call with `f"{num:x}"`
|
9 | print(oct(num)[2:]) # FURB116
10 | print(hex(num)[2:]) # FURB116
| ^^^^^^^^^^^^ FURB116
11 | print(bin(num)[2:]) # FURB116
|
= help: Replace with `f"{num:x}"`
Display-only fix
7 7 | return num
8 8 |
9 9 | print(oct(num)[2:]) # FURB116
10 |-print(hex(num)[2:]) # FURB116
10 |+print(f"{num:x}") # FURB116
11 11 | print(bin(num)[2:]) # FURB116
12 12 |
13 13 | print(oct(1337)[2:]) # FURB116
FURB116.py:11:7: FURB116 Replace `bin` call with `f"{num:b}"`
|
9 | print(oct(num)[2:]) # FURB116
10 | print(hex(num)[2:]) # FURB116
11 | print(bin(num)[2:]) # FURB116
| ^^^^^^^^^^^^ FURB116
12 |
13 | print(oct(1337)[2:]) # FURB116
| |
= help: Replace with `f"{num:b}"` = help: Replace with `f"{num:b}"`
Safe fix Display-only fix
5 5 | 8 8 |
6 6 | print(oct(num)[2:]) # FURB116 9 9 | print(oct(num)[2:]) # FURB116
7 7 | print(hex(num)[2:]) # FURB116 10 10 | print(hex(num)[2:]) # FURB116
8 |-print(bin(num)[2:]) # FURB116 11 |-print(bin(num)[2:]) # FURB116
8 |+print(f"{num:b}") # FURB116 11 |+print(f"{num:b}") # FURB116
9 9 | 12 12 |
10 10 | print(oct(1337)[2:]) # FURB116 13 13 | print(oct(1337)[2:]) # FURB116
11 11 | print(hex(1337)[2:]) # FURB116 14 14 | print(hex(1337)[2:]) # FURB116
FURB116.py:10:7: FURB116 [*] Replace `oct` call with `f"{1337:o}"` FURB116.py:13:7: FURB116 [*] Replace `oct` call with `f"{1337:o}"`
| |
8 | print(bin(num)[2:]) # FURB116 11 | print(bin(num)[2:]) # FURB116
9 | 12 |
10 | print(oct(1337)[2:]) # FURB116 13 | print(oct(1337)[2:]) # FURB116
| ^^^^^^^^^^^^^ FURB116 | ^^^^^^^^^^^^^ FURB116
11 | print(hex(1337)[2:]) # FURB116 14 | print(hex(1337)[2:]) # FURB116
12 | print(bin(1337)[2:]) # FURB116 15 | print(bin(1337)[2:]) # FURB116
| |
= help: Replace with `f"{1337:o}"` = help: Replace with `f"{1337:o}"`
Safe fix Safe fix
7 7 | print(hex(num)[2:]) # FURB116 10 10 | print(hex(num)[2:]) # FURB116
8 8 | print(bin(num)[2:]) # FURB116 11 11 | print(bin(num)[2:]) # FURB116
9 9 | 12 12 |
10 |-print(oct(1337)[2:]) # FURB116 13 |-print(oct(1337)[2:]) # FURB116
10 |+print(f"{1337:o}") # FURB116 13 |+print(f"{1337:o}") # FURB116
11 11 | print(hex(1337)[2:]) # FURB116 14 14 | print(hex(1337)[2:]) # FURB116
12 12 | print(bin(1337)[2:]) # FURB116 15 15 | print(bin(1337)[2:]) # FURB116
13 13 | 16 16 | print(bin(+1337)[2:]) # FURB116
FURB116.py:11:7: FURB116 [*] Replace `hex` call with `f"{1337:x}"` FURB116.py:14:7: FURB116 [*] Replace `hex` call with `f"{1337:x}"`
| |
10 | print(oct(1337)[2:]) # FURB116 13 | print(oct(1337)[2:]) # FURB116
11 | print(hex(1337)[2:]) # FURB116 14 | print(hex(1337)[2:]) # FURB116
| ^^^^^^^^^^^^^ FURB116 | ^^^^^^^^^^^^^ FURB116
12 | print(bin(1337)[2:]) # FURB116 15 | print(bin(1337)[2:]) # FURB116
16 | print(bin(+1337)[2:]) # FURB116
| |
= help: Replace with `f"{1337:x}"` = help: Replace with `f"{1337:x}"`
Safe fix Safe fix
8 8 | print(bin(num)[2:]) # FURB116 11 11 | print(bin(num)[2:]) # FURB116
9 9 | 12 12 |
10 10 | print(oct(1337)[2:]) # FURB116 13 13 | print(oct(1337)[2:]) # FURB116
11 |-print(hex(1337)[2:]) # FURB116 14 |-print(hex(1337)[2:]) # FURB116
11 |+print(f"{1337:x}") # FURB116 14 |+print(f"{1337:x}") # FURB116
12 12 | print(bin(1337)[2:]) # FURB116 15 15 | print(bin(1337)[2:]) # FURB116
13 13 | 16 16 | print(bin(+1337)[2:]) # FURB116
14 14 | print(bin(return_num())[2:]) # FURB116 (no autofix) 17 17 |
FURB116.py:12:7: FURB116 [*] Replace `bin` call with `f"{1337:b}"` FURB116.py:15:7: FURB116 [*] Replace `bin` call with `f"{1337:b}"`
| |
10 | print(oct(1337)[2:]) # FURB116 13 | print(oct(1337)[2:]) # FURB116
11 | print(hex(1337)[2:]) # FURB116 14 | print(hex(1337)[2:]) # FURB116
12 | print(bin(1337)[2:]) # FURB116 15 | print(bin(1337)[2:]) # FURB116
| ^^^^^^^^^^^^^ FURB116 | ^^^^^^^^^^^^^ FURB116
13 | 16 | print(bin(+1337)[2:]) # FURB116
14 | print(bin(return_num())[2:]) # FURB116 (no autofix)
| |
= help: Replace with `f"{1337:b}"` = help: Replace with `f"{1337:b}"`
Safe fix Safe fix
9 9 | 12 12 |
10 10 | print(oct(1337)[2:]) # FURB116 13 13 | print(oct(1337)[2:]) # FURB116
11 11 | print(hex(1337)[2:]) # FURB116 14 14 | print(hex(1337)[2:]) # FURB116
12 |-print(bin(1337)[2:]) # FURB116 15 |-print(bin(1337)[2:]) # FURB116
12 |+print(f"{1337:b}") # FURB116 15 |+print(f"{1337:b}") # FURB116
13 13 | 16 16 | print(bin(+1337)[2:]) # FURB116
14 14 | print(bin(return_num())[2:]) # FURB116 (no autofix) 17 17 |
15 15 | print(bin(int(f"{num}"))[2:]) # FURB116 (no autofix) 18 18 | print(bin(return_num())[2:]) # FURB116 (no autofix)
FURB116.py:14:7: FURB116 Replace `bin` call with f-string FURB116.py:16:7: FURB116 [*] Replace `bin` call with `f"{+1337:b}"`
| |
12 | print(bin(1337)[2:]) # FURB116 14 | print(hex(1337)[2:]) # FURB116
13 | 15 | print(bin(1337)[2:]) # FURB116
14 | print(bin(return_num())[2:]) # FURB116 (no autofix) 16 | print(bin(+1337)[2:]) # FURB116
| ^^^^^^^^^^^^^^ FURB116
17 |
18 | print(bin(return_num())[2:]) # FURB116 (no autofix)
|
= help: Replace with `f"{+1337:b}"`
Safe fix
13 13 | print(oct(1337)[2:]) # FURB116
14 14 | print(hex(1337)[2:]) # FURB116
15 15 | print(bin(1337)[2:]) # FURB116
16 |-print(bin(+1337)[2:]) # FURB116
16 |+print(f"{+1337:b}") # FURB116
17 17 |
18 18 | print(bin(return_num())[2:]) # FURB116 (no autofix)
19 19 | print(bin(int(f"{num}"))[2:]) # FURB116 (no autofix)
FURB116.py:18:7: FURB116 Replace `bin` call with f-string
|
16 | print(bin(+1337)[2:]) # FURB116
17 |
18 | print(bin(return_num())[2:]) # FURB116 (no autofix)
| ^^^^^^^^^^^^^^^^^^^^^ FURB116 | ^^^^^^^^^^^^^^^^^^^^^ FURB116
15 | print(bin(int(f"{num}"))[2:]) # FURB116 (no autofix) 19 | print(bin(int(f"{num}"))[2:]) # FURB116 (no autofix)
| |
= help: Replace with f-string = help: Replace with f-string
FURB116.py:15:7: FURB116 Replace `bin` call with f-string FURB116.py:19:7: FURB116 Replace `bin` call with f-string
| |
14 | print(bin(return_num())[2:]) # FURB116 (no autofix) 18 | print(bin(return_num())[2:]) # FURB116 (no autofix)
15 | print(bin(int(f"{num}"))[2:]) # FURB116 (no autofix) 19 | print(bin(int(f"{num}"))[2:]) # FURB116 (no autofix)
| ^^^^^^^^^^^^^^^^^^^^^^ FURB116 | ^^^^^^^^^^^^^^^^^^^^^^ FURB116
16 | 20 |
17 | ## invalid 21 | ## invalid
| |
= help: Replace with f-string = help: Replace with f-string
FURB116.py:32:7: FURB116 Replace `bin` call with `f"{d:b}"`
|
30 | d = datetime.datetime.now(tz=datetime.UTC)
31 | # autofix is display-only
32 | print(bin(d)[2:])
| ^^^^^^^^^^ FURB116
33 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
34 | print(bin(len("xyz").numerator)[2:])
|
= help: Replace with `f"{d:b}"`
Display-only fix
29 29 |
30 30 | d = datetime.datetime.now(tz=datetime.UTC)
31 31 | # autofix is display-only
32 |-print(bin(d)[2:])
32 |+print(f"{d:b}")
33 33 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
34 34 | print(bin(len("xyz").numerator)[2:])
35 35 |
FURB116.py:34:7: FURB116 Replace `bin` call with `f"{len("xyz").numerator:b}"`
|
32 | print(bin(d)[2:])
33 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
34 | print(bin(len("xyz").numerator)[2:])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FURB116
35 |
36 | # autofix is display-only
|
= help: Replace with `f"{len("xyz").numerator:b}"`
Display-only fix
31 31 | # autofix is display-only
32 32 | print(bin(d)[2:])
33 33 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
34 |-print(bin(len("xyz").numerator)[2:])
34 |+print(f"{len("xyz").numerator:b}")
35 35 |
36 36 | # autofix is display-only
37 37 | print(bin({0: 1}[0].numerator)[2:])
FURB116.py:37:7: FURB116 Replace `bin` call with `f"{ {0: 1}[0].numerator:b}"`
|
36 | # autofix is display-only
37 | print(bin({0: 1}[0].numerator)[2:])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FURB116
38 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
39 | print(bin(ord("\\").numerator)[2:])
|
= help: Replace with `f"{ {0: 1}[0].numerator:b}"`
Display-only fix
34 34 | print(bin(len("xyz").numerator)[2:])
35 35 |
36 36 | # autofix is display-only
37 |-print(bin({0: 1}[0].numerator)[2:])
37 |+print(f"{ {0: 1}[0].numerator:b}")
38 38 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
39 39 | print(bin(ord("\\").numerator)[2:])
40 40 | print(hex(sys
FURB116.py:39:7: FURB116 Replace `bin` call with `f"{ord("\\").numerator:b}"`
|
37 | print(bin({0: 1}[0].numerator)[2:])
38 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
39 | print(bin(ord("\\").numerator)[2:])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FURB116
40 | print(hex(sys
41 | .maxunicode)[2:])
|
= help: Replace with `f"{ord("\\").numerator:b}"`
Display-only fix
36 36 | # autofix is display-only
37 37 | print(bin({0: 1}[0].numerator)[2:])
38 38 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
39 |-print(bin(ord("\\").numerator)[2:])
39 |+print(f"{ord("\\").numerator:b}")
40 40 | print(hex(sys
41 41 | .maxunicode)[2:])
42 42 |
FURB116.py:40:7: FURB116 Replace `hex` call with f-string
|
38 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
39 | print(bin(ord("\\").numerator)[2:])
40 | print(hex(sys
| _______^
41 | | .maxunicode)[2:])
| |________________^ FURB116
42 |
43 | # for negatives numbers autofix is display-only
|
= help: Replace with f-string
Display-only fix
37 37 | print(bin({0: 1}[0].numerator)[2:])
38 38 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
39 39 | print(bin(ord("\\").numerator)[2:])
40 |-print(hex(sys
41 |-.maxunicode)[2:])
40 |+print(f"{sys
41 |+.maxunicode:x}")
42 42 |
43 43 | # for negatives numbers autofix is display-only
44 44 | print(bin(-1)[2:])
FURB116.py:44:7: FURB116 Replace `bin` call with `f"{-1:b}"`
|
43 | # for negatives numbers autofix is display-only
44 | print(bin(-1)[2:])
| ^^^^^^^^^^^ FURB116
|
= help: Replace with `f"{-1:b}"`
Display-only fix
41 41 | .maxunicode)[2:])
42 42 |
43 43 | # for negatives numbers autofix is display-only
44 |-print(bin(-1)[2:])
44 |+print(f"{-1:b}")

View File

@ -0,0 +1,256 @@
---
source: crates/ruff_linter/src/rules/refurb/mod.rs
---
FURB116.py:9:7: FURB116 Replace `oct` call with `f"{num:o}"`
|
7 | return num
8 |
9 | print(oct(num)[2:]) # FURB116
| ^^^^^^^^^^^^ FURB116
10 | print(hex(num)[2:]) # FURB116
11 | print(bin(num)[2:]) # FURB116
|
= help: Replace with `f"{num:o}"`
Display-only fix
6 6 | def return_num() -> int:
7 7 | return num
8 8 |
9 |-print(oct(num)[2:]) # FURB116
9 |+print(f"{num:o}") # FURB116
10 10 | print(hex(num)[2:]) # FURB116
11 11 | print(bin(num)[2:]) # FURB116
12 12 |
FURB116.py:10:7: FURB116 Replace `hex` call with `f"{num:x}"`
|
9 | print(oct(num)[2:]) # FURB116
10 | print(hex(num)[2:]) # FURB116
| ^^^^^^^^^^^^ FURB116
11 | print(bin(num)[2:]) # FURB116
|
= help: Replace with `f"{num:x}"`
Display-only fix
7 7 | return num
8 8 |
9 9 | print(oct(num)[2:]) # FURB116
10 |-print(hex(num)[2:]) # FURB116
10 |+print(f"{num:x}") # FURB116
11 11 | print(bin(num)[2:]) # FURB116
12 12 |
13 13 | print(oct(1337)[2:]) # FURB116
FURB116.py:11:7: FURB116 Replace `bin` call with `f"{num:b}"`
|
9 | print(oct(num)[2:]) # FURB116
10 | print(hex(num)[2:]) # FURB116
11 | print(bin(num)[2:]) # FURB116
| ^^^^^^^^^^^^ FURB116
12 |
13 | print(oct(1337)[2:]) # FURB116
|
= help: Replace with `f"{num:b}"`
Display-only fix
8 8 |
9 9 | print(oct(num)[2:]) # FURB116
10 10 | print(hex(num)[2:]) # FURB116
11 |-print(bin(num)[2:]) # FURB116
11 |+print(f"{num:b}") # FURB116
12 12 |
13 13 | print(oct(1337)[2:]) # FURB116
14 14 | print(hex(1337)[2:]) # FURB116
FURB116.py:13:7: FURB116 [*] Replace `oct` call with `f"{1337:o}"`
|
11 | print(bin(num)[2:]) # FURB116
12 |
13 | print(oct(1337)[2:]) # FURB116
| ^^^^^^^^^^^^^ FURB116
14 | print(hex(1337)[2:]) # FURB116
15 | print(bin(1337)[2:]) # FURB116
|
= help: Replace with `f"{1337:o}"`
Safe fix
10 10 | print(hex(num)[2:]) # FURB116
11 11 | print(bin(num)[2:]) # FURB116
12 12 |
13 |-print(oct(1337)[2:]) # FURB116
13 |+print(f"{1337:o}") # FURB116
14 14 | print(hex(1337)[2:]) # FURB116
15 15 | print(bin(1337)[2:]) # FURB116
16 16 | print(bin(+1337)[2:]) # FURB116
FURB116.py:14:7: FURB116 [*] Replace `hex` call with `f"{1337:x}"`
|
13 | print(oct(1337)[2:]) # FURB116
14 | print(hex(1337)[2:]) # FURB116
| ^^^^^^^^^^^^^ FURB116
15 | print(bin(1337)[2:]) # FURB116
16 | print(bin(+1337)[2:]) # FURB116
|
= help: Replace with `f"{1337:x}"`
Safe fix
11 11 | print(bin(num)[2:]) # FURB116
12 12 |
13 13 | print(oct(1337)[2:]) # FURB116
14 |-print(hex(1337)[2:]) # FURB116
14 |+print(f"{1337:x}") # FURB116
15 15 | print(bin(1337)[2:]) # FURB116
16 16 | print(bin(+1337)[2:]) # FURB116
17 17 |
FURB116.py:15:7: FURB116 [*] Replace `bin` call with `f"{1337:b}"`
|
13 | print(oct(1337)[2:]) # FURB116
14 | print(hex(1337)[2:]) # FURB116
15 | print(bin(1337)[2:]) # FURB116
| ^^^^^^^^^^^^^ FURB116
16 | print(bin(+1337)[2:]) # FURB116
|
= help: Replace with `f"{1337:b}"`
Safe fix
12 12 |
13 13 | print(oct(1337)[2:]) # FURB116
14 14 | print(hex(1337)[2:]) # FURB116
15 |-print(bin(1337)[2:]) # FURB116
15 |+print(f"{1337:b}") # FURB116
16 16 | print(bin(+1337)[2:]) # FURB116
17 17 |
18 18 | print(bin(return_num())[2:]) # FURB116 (no autofix)
FURB116.py:16:7: FURB116 [*] Replace `bin` call with `f"{+1337:b}"`
|
14 | print(hex(1337)[2:]) # FURB116
15 | print(bin(1337)[2:]) # FURB116
16 | print(bin(+1337)[2:]) # FURB116
| ^^^^^^^^^^^^^^ FURB116
17 |
18 | print(bin(return_num())[2:]) # FURB116 (no autofix)
|
= help: Replace with `f"{+1337:b}"`
Safe fix
13 13 | print(oct(1337)[2:]) # FURB116
14 14 | print(hex(1337)[2:]) # FURB116
15 15 | print(bin(1337)[2:]) # FURB116
16 |-print(bin(+1337)[2:]) # FURB116
16 |+print(f"{+1337:b}") # FURB116
17 17 |
18 18 | print(bin(return_num())[2:]) # FURB116 (no autofix)
19 19 | print(bin(int(f"{num}"))[2:]) # FURB116 (no autofix)
FURB116.py:18:7: FURB116 Replace `bin` call with f-string
|
16 | print(bin(+1337)[2:]) # FURB116
17 |
18 | print(bin(return_num())[2:]) # FURB116 (no autofix)
| ^^^^^^^^^^^^^^^^^^^^^ FURB116
19 | print(bin(int(f"{num}"))[2:]) # FURB116 (no autofix)
|
= help: Replace with f-string
FURB116.py:19:7: FURB116 Replace `bin` call with f-string
|
18 | print(bin(return_num())[2:]) # FURB116 (no autofix)
19 | print(bin(int(f"{num}"))[2:]) # FURB116 (no autofix)
| ^^^^^^^^^^^^^^^^^^^^^^ FURB116
20 |
21 | ## invalid
|
= help: Replace with f-string
FURB116.py:32:7: FURB116 Replace `bin` call with `f"{d:b}"`
|
30 | d = datetime.datetime.now(tz=datetime.UTC)
31 | # autofix is display-only
32 | print(bin(d)[2:])
| ^^^^^^^^^^ FURB116
33 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
34 | print(bin(len("xyz").numerator)[2:])
|
= help: Replace with `f"{d:b}"`
Display-only fix
29 29 |
30 30 | d = datetime.datetime.now(tz=datetime.UTC)
31 31 | # autofix is display-only
32 |-print(bin(d)[2:])
32 |+print(f"{d:b}")
33 33 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
34 34 | print(bin(len("xyz").numerator)[2:])
35 35 |
FURB116.py:34:7: FURB116 Replace `bin` call with f-string
|
32 | print(bin(d)[2:])
33 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
34 | print(bin(len("xyz").numerator)[2:])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FURB116
35 |
36 | # autofix is display-only
|
= help: Replace with f-string
FURB116.py:37:7: FURB116 Replace `bin` call with `f"{ {0: 1}[0].numerator:b}"`
|
36 | # autofix is display-only
37 | print(bin({0: 1}[0].numerator)[2:])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FURB116
38 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
39 | print(bin(ord("\\").numerator)[2:])
|
= help: Replace with `f"{ {0: 1}[0].numerator:b}"`
Display-only fix
34 34 | print(bin(len("xyz").numerator)[2:])
35 35 |
36 36 | # autofix is display-only
37 |-print(bin({0: 1}[0].numerator)[2:])
37 |+print(f"{ {0: 1}[0].numerator:b}")
38 38 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
39 39 | print(bin(ord("\\").numerator)[2:])
40 40 | print(hex(sys
FURB116.py:39:7: FURB116 Replace `bin` call with f-string
|
37 | print(bin({0: 1}[0].numerator)[2:])
38 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
39 | print(bin(ord("\\").numerator)[2:])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FURB116
40 | print(hex(sys
41 | .maxunicode)[2:])
|
= help: Replace with f-string
FURB116.py:40:7: FURB116 Replace `hex` call with f-string
|
38 | # no autofix for Python 3.11 and earlier, as it introduces a syntax error
39 | print(bin(ord("\\").numerator)[2:])
40 | print(hex(sys
| _______^
41 | | .maxunicode)[2:])
| |________________^ FURB116
42 |
43 | # for negatives numbers autofix is display-only
|
= help: Replace with f-string
FURB116.py:44:7: FURB116 Replace `bin` call with `f"{-1:b}"`
|
43 | # for negatives numbers autofix is display-only
44 | print(bin(-1)[2:])
| ^^^^^^^^^^^ FURB116
|
= help: Replace with `f"{-1:b}"`
Display-only fix
41 41 | .maxunicode)[2:])
42 42 |
43 43 | # for negatives numbers autofix is display-only
44 |-print(bin(-1)[2:])
44 |+print(f"{-1:b}")