Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,20 @@ def t(self):
a_number = index = a_number + 1
index = index * index + 10
some_string = "a very long start to the string" + some_string

# Regression tests for https://github.com/astral-sh/ruff/issues/11672
test = 0x5
test = test + 0xBA

test2 = b""
test2 = test2 + b"\000"

test3 = ""
test3 = test3 + ( a := R""
f"oo" )

test4 = []
test4 = test4 + ( e
for e in
range(10)
)
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use ast::{Expr, StmtAugAssign};
use ast::Expr;
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, ViolationMetadata};
use ruff_python_ast as ast;
use ruff_python_ast::comparable::ComparableExpr;
use ruff_python_ast::Operator;
use ruff_python_codegen::Generator;
use ruff_text_size::{Ranged, TextRange};

use crate::checkers::ast::Checker;
use crate::Locator;

/// ## What it does
/// Checks for assignments that can be replaced with augmented assignment
Expand Down Expand Up @@ -103,9 +103,9 @@ pub(crate) fn non_augmented_assignment(checker: &mut Checker, assign: &ast::Stmt
if ComparableExpr::from(target) == ComparableExpr::from(&value.left) {
let mut diagnostic = Diagnostic::new(NonAugmentedAssignment { operator }, assign.range());
diagnostic.set_fix(Fix::unsafe_edit(augmented_assignment(
checker.generator(),
checker.locator(),
target,
value.op,
operator,
&value.right,
assign.range(),
)));
Expand All @@ -121,9 +121,9 @@ pub(crate) fn non_augmented_assignment(checker: &mut Checker, assign: &ast::Stmt
{
let mut diagnostic = Diagnostic::new(NonAugmentedAssignment { operator }, assign.range());
diagnostic.set_fix(Fix::unsafe_edit(augmented_assignment(
checker.generator(),
checker.locator(),
target,
value.op,
operator,
&value.left,
assign.range(),
)));
Expand All @@ -135,21 +135,25 @@ pub(crate) fn non_augmented_assignment(checker: &mut Checker, assign: &ast::Stmt
///
/// For example, given `x = x + 1`, the fix would be `x += 1`.
fn augmented_assignment(
generator: Generator,
locator: &Locator,
target: &Expr,
operator: Operator,
operator: AugmentedOperator,
right_operand: &Expr,
range: TextRange,
) -> Edit {
Edit::range_replacement(
generator.stmt(&ast::Stmt::AugAssign(StmtAugAssign {
range: TextRange::default(),
target: Box::new(target.clone()),
op: operator,
value: Box::new(right_operand.clone()),
})),
range,
)
let target_expr = locator.slice(target);
let right_operand_expr = locator.slice(right_operand);

// expressions using the walrus operator (`:=`) must be parenthesized
// when they're used as standalone expressions:
let new_value_expr = if right_operand.is_named_expr() {
format!("({right_operand_expr})")
} else {
right_operand_expr.to_string()
};
let new_content = format!("{target_expr} {operator} {new_value_expr}");

Edit::range_replacement(new_content, range)
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ non_augmented_assignment.py:29:1: PLR6104 [*] Use `&=` to perform an augmented a
27 27 | to_cube = to_cube**to_cube
28 28 | timeDiffSeconds = timeDiffSeconds % 60
29 |-flags = flags & 0x1
29 |+flags &= 1
29 |+flags &= 0x1
30 30 | flags = flags | 0x1
31 31 | flags = flags ^ 0x1
32 32 | flags = flags << 1
Expand All @@ -290,7 +290,7 @@ non_augmented_assignment.py:30:1: PLR6104 [*] Use `|=` to perform an augmented a
28 28 | timeDiffSeconds = timeDiffSeconds % 60
29 29 | flags = flags & 0x1
30 |-flags = flags | 0x1
30 |+flags |= 1
30 |+flags |= 0x1
31 31 | flags = flags ^ 0x1
32 32 | flags = flags << 1
33 33 | flags = flags >> 1
Expand All @@ -311,7 +311,7 @@ non_augmented_assignment.py:31:1: PLR6104 [*] Use `^=` to perform an augmented a
29 29 | flags = flags & 0x1
30 30 | flags = flags | 0x1
31 |-flags = flags ^ 0x1
31 |+flags ^= 1
31 |+flags ^= 0x1
32 32 | flags = flags << 1
33 33 | flags = flags >> 1
34 34 | mat1 = mat1 @ mat2
Expand Down Expand Up @@ -538,3 +538,88 @@ non_augmented_assignment.py:51:1: PLR6104 [*] Use `+=` to perform an augmented a
52 52 |
53 53 | # OK
54 54 | a_list[0] = a_list[:] * 3

non_augmented_assignment.py:62:1: PLR6104 [*] Use `+=` to perform an augmented assignment directly
|
60 | # Regression tests for https://github.com/astral-sh/ruff/issues/11672
61 | test = 0x5
62 | test = test + 0xBA
| ^^^^^^^^^^^^^^^^^^ PLR6104
63 |
64 | test2 = b""
|
= help: Replace with augmented assignment

ℹ Unsafe fix
59 59 |
60 60 | # Regression tests for https://github.com/astral-sh/ruff/issues/11672
61 61 | test = 0x5
62 |-test = test + 0xBA
62 |+test += 0xBA
63 63 |
64 64 | test2 = b""
65 65 | test2 = test2 + b"\000"

non_augmented_assignment.py:65:1: PLR6104 [*] Use `+=` to perform an augmented assignment directly
|
64 | test2 = b""
65 | test2 = test2 + b"\000"
| ^^^^^^^^^^^^^^^^^^^^^^^ PLR6104
66 |
67 | test3 = ""
|
= help: Replace with augmented assignment

ℹ Unsafe fix
62 62 | test = test + 0xBA
63 63 |
64 64 | test2 = b""
65 |-test2 = test2 + b"\000"
65 |+test2 += b"\000"
66 66 |
67 67 | test3 = ""
68 68 | test3 = test3 + ( a := R""

non_augmented_assignment.py:68:1: PLR6104 [*] Use `+=` to perform an augmented assignment directly
|
67 | test3 = ""
68 | / test3 = test3 + ( a := R""
69 | | f"oo" )
| |_______________________________^ PLR6104
70 |
71 | test4 = []
|
= help: Replace with augmented assignment

ℹ Unsafe fix
65 65 | test2 = test2 + b"\000"
66 66 |
67 67 | test3 = ""
68 |-test3 = test3 + ( a := R""
69 |- f"oo" )
68 |+test3 += (a := R""
69 |+ f"oo")
70 70 |
71 71 | test4 = []
72 72 | test4 = test4 + ( e

non_augmented_assignment.py:72:1: PLR6104 [*] Use `+=` to perform an augmented assignment directly
|
71 | test4 = []
72 | / test4 = test4 + ( e
73 | | for e in
74 | | range(10)
75 | | )
| |___________________^ PLR6104
|
= help: Replace with augmented assignment

ℹ Unsafe fix
69 69 | f"oo" )
70 70 |
71 71 | test4 = []
72 |-test4 = test4 + ( e
72 |+test4 += ( e
73 73 | for e in
74 74 | range(10)
75 75 | )
Loading