From 6d2e711d9e1481b0aa247160f032d9fa34976215 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Fri, 26 Jul 2024 10:58:09 -0400 Subject: [PATCH] Use colon rather than dot formatting for integer-only types --- .../test/fixtures/pyupgrade/UP031_0.py | 10 ++ .../rules/printf_string_formatting.rs | 15 +- ...__rules__pyupgrade__tests__UP031_0.py.snap | 141 ++++++++++++++++++ 3 files changed, 164 insertions(+), 2 deletions(-) diff --git a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP031_0.py b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP031_0.py index f8b8c1fe34de0..8ce722a1f713c 100644 --- a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP031_0.py +++ b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP031_0.py @@ -129,3 +129,13 @@ # Not a valid type annotation but this test shouldn't result in a panic. # Refer: https://github.com/astral-sh/ruff/issues/11736 x: "'%s + %s' % (1, 2)" + +# See: https://github.com/astral-sh/ruff/issues/12421 +print("%.2X" % 1) +print("%.02X" % 1) +print("%02X" % 1) +print("%.00002X" % 1) +print("%.20X" % 1) + +print("%2X" % 1) +print("%02X" % 1) diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/printf_string_formatting.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/printf_string_formatting.rs index 547ae4a5b559c..6c45ac8307679 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/printf_string_formatting.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/printf_string_formatting.rs @@ -150,8 +150,19 @@ fn handle_part(part: &CFormatPart) -> Cow<'_, str> { match precision { CFormatPrecision::Quantity(quantity) => match quantity { CFormatQuantity::Amount(amount) => { - format_string.push('.'); - format_string.push_str(&amount.to_string()); + // Integer-only presentation types. + // + // See: https://docs.python.org/3/library/string.html#format-specification-mini-language + if matches!( + spec.format_char, + 'b' | 'c' | 'd' | 'o' | 'x' | 'X' | 'n' + ) { + format_string.push('0'); + format_string.push_str(&amount.to_string()); + } else { + format_string.push('.'); + format_string.push_str(&amount.to_string()); + } } CFormatQuantity::FromValuesTuple => { unreachable!("Width should be a usize") diff --git a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP031_0.py.snap b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP031_0.py.snap index e3047e0b6a4be..01a7e21e92527 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP031_0.py.snap +++ b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP031_0.py.snap @@ -1007,6 +1007,8 @@ UP031_0.py:131:5: UP031 [*] Use format specifiers instead of percent format 130 | # Refer: https://github.com/astral-sh/ruff/issues/11736 131 | x: "'%s + %s' % (1, 2)" | ^^^^^^^^^^^^^^^^^^ UP031 +132 | +133 | # See: https://github.com/astral-sh/ruff/issues/12421 | = help: Replace with format specifiers @@ -1016,3 +1018,142 @@ UP031_0.py:131:5: UP031 [*] Use format specifiers instead of percent format 130 130 | # Refer: https://github.com/astral-sh/ruff/issues/11736 131 |-x: "'%s + %s' % (1, 2)" 131 |+x: "'{} + {}'.format(1, 2)" +132 132 | +133 133 | # See: https://github.com/astral-sh/ruff/issues/12421 +134 134 | print("%.2X" % 1) + +UP031_0.py:134:7: UP031 [*] Use format specifiers instead of percent format + | +133 | # See: https://github.com/astral-sh/ruff/issues/12421 +134 | print("%.2X" % 1) + | ^^^^^^^^^^ UP031 +135 | print("%.02X" % 1) +136 | print("%02X" % 1) + | + = help: Replace with format specifiers + +ℹ Unsafe fix +131 131 | x: "'%s + %s' % (1, 2)" +132 132 | +133 133 | # See: https://github.com/astral-sh/ruff/issues/12421 +134 |-print("%.2X" % 1) + 134 |+print("{:02X}".format(1)) +135 135 | print("%.02X" % 1) +136 136 | print("%02X" % 1) +137 137 | print("%.00002X" % 1) + +UP031_0.py:135:7: UP031 [*] Use format specifiers instead of percent format + | +133 | # See: https://github.com/astral-sh/ruff/issues/12421 +134 | print("%.2X" % 1) +135 | print("%.02X" % 1) + | ^^^^^^^^^^^ UP031 +136 | print("%02X" % 1) +137 | print("%.00002X" % 1) + | + = help: Replace with format specifiers + +ℹ Unsafe fix +132 132 | +133 133 | # See: https://github.com/astral-sh/ruff/issues/12421 +134 134 | print("%.2X" % 1) +135 |-print("%.02X" % 1) + 135 |+print("{:02X}".format(1)) +136 136 | print("%02X" % 1) +137 137 | print("%.00002X" % 1) +138 138 | print("%.20X" % 1) + +UP031_0.py:136:7: UP031 [*] Use format specifiers instead of percent format + | +134 | print("%.2X" % 1) +135 | print("%.02X" % 1) +136 | print("%02X" % 1) + | ^^^^^^^^^^ UP031 +137 | print("%.00002X" % 1) +138 | print("%.20X" % 1) + | + = help: Replace with format specifiers + +ℹ Unsafe fix +133 133 | # See: https://github.com/astral-sh/ruff/issues/12421 +134 134 | print("%.2X" % 1) +135 135 | print("%.02X" % 1) +136 |-print("%02X" % 1) + 136 |+print("{:02X}".format(1)) +137 137 | print("%.00002X" % 1) +138 138 | print("%.20X" % 1) +139 139 | + +UP031_0.py:137:7: UP031 [*] Use format specifiers instead of percent format + | +135 | print("%.02X" % 1) +136 | print("%02X" % 1) +137 | print("%.00002X" % 1) + | ^^^^^^^^^^^^^^ UP031 +138 | print("%.20X" % 1) + | + = help: Replace with format specifiers + +ℹ Unsafe fix +134 134 | print("%.2X" % 1) +135 135 | print("%.02X" % 1) +136 136 | print("%02X" % 1) +137 |-print("%.00002X" % 1) + 137 |+print("{:02X}".format(1)) +138 138 | print("%.20X" % 1) +139 139 | +140 140 | print("%2X" % 1) + +UP031_0.py:138:7: UP031 [*] Use format specifiers instead of percent format + | +136 | print("%02X" % 1) +137 | print("%.00002X" % 1) +138 | print("%.20X" % 1) + | ^^^^^^^^^^^ UP031 +139 | +140 | print("%2X" % 1) + | + = help: Replace with format specifiers + +ℹ Unsafe fix +135 135 | print("%.02X" % 1) +136 136 | print("%02X" % 1) +137 137 | print("%.00002X" % 1) +138 |-print("%.20X" % 1) + 138 |+print("{:020X}".format(1)) +139 139 | +140 140 | print("%2X" % 1) +141 141 | print("%02X" % 1) + +UP031_0.py:140:7: UP031 [*] Use format specifiers instead of percent format + | +138 | print("%.20X" % 1) +139 | +140 | print("%2X" % 1) + | ^^^^^^^^^ UP031 +141 | print("%02X" % 1) + | + = help: Replace with format specifiers + +ℹ Unsafe fix +137 137 | print("%.00002X" % 1) +138 138 | print("%.20X" % 1) +139 139 | +140 |-print("%2X" % 1) + 140 |+print("{:2X}".format(1)) +141 141 | print("%02X" % 1) + +UP031_0.py:141:7: UP031 [*] Use format specifiers instead of percent format + | +140 | print("%2X" % 1) +141 | print("%02X" % 1) + | ^^^^^^^^^^ UP031 + | + = help: Replace with format specifiers + +ℹ Unsafe fix +138 138 | print("%.20X" % 1) +139 139 | +140 140 | print("%2X" % 1) +141 |-print("%02X" % 1) + 141 |+print("{:02X}".format(1))