[pylint] Implement rule to prefer augmented assignment (PLR6104)#9932
Conversation
|
| code | total | + violation | - violation | + fix | - fix |
|---|---|---|---|---|---|
| PLR6104 | 506 | 506 | 0 | 0 | 0 |
| PLR0914 | 2 | 1 | 1 | 0 | 0 |
c3255c5 to
2241be2
Compare
CodSpeed Performance ReportMerging #9932 will not alter performanceComparing Summary
|
0bc73ac to
6fbedf6
Compare
|
Not a rust dev, so I won't comment on your implementation, but I think the tests should also check for proper handling of order of operation: >>> test = 2
>>> test = test * test + 10 # OK
>>> test
14
>>> test = 2
>>> test *= test + 10
>>> test
24
>>> test = 2
>>> test = test * (test + 10) # RUF028
>>> test
24 |
|
Thanks for the quick reply. I added the suggested test cases. I had these two test cases in my earlier draft, but wasn’t sure and removed them. It is nice that you brought them up and have them back. |
|
Related pylint rule: Related issue: #970 @lshi18 instead of assigning it to RUF028, this rule should be placed under PyLint R6104. |
8bd617a to
6e57b2c
Compare
|
The new rule has been moved under PLR6104 instead of RUF028. |
|
The |
| checker: &mut Checker, | ||
| assign @ ast::StmtAssign { value, targets, .. }: &ast::StmtAssign, | ||
| ) { | ||
| if targets.len() != 1 { |
There was a problem hiding this comment.
Using let-else here to make this check a bit nicer:
let target = Some(targets.first()) else {
return;
}There was a problem hiding this comment.
Please correct me if I am wrong, but do you mean
let Some(target) = target.first() else {
return;
}I agree that this looks nicer if it could be changed to it.
I don't think, in this case, that they are semantically equal. In particular, the following test case which is marked as OK fails after the suggested change.
a_number = index = a_number + 1 # OKI think a further question would be whether we should detect the above case and, in the same gist, the one below.
index = a_number = a_number + 1 # OKThere was a problem hiding this comment.
My bad, I hadn't tested. Since targets is a vector, this should work:
let targets = vec![1];
// let targets = vec![1, 2];
// let targets: Vec<i32> = vec![];
let &[target] = targets.as_slice() else{
return;
};There was a problem hiding this comment.
I had a quick test with pylint 3.0.3, whose R6104 rule detects this
a_number = index = a_number + 1 # OKbut not this,
index = a_number = a_number + 1 # OKDo you think we should implement to reproduce this effect?
BTW, the test cases for this rule in the pylint project include neither of the above cases, so I think the current behaviour is a side-effect of implementation.
Meanwhile, my current implementation is incorrect regarding handling more complex subsript / attribute expressions. I'll reimplement it while also taking into consideration of your other suggestions .
| } | ||
| let target = targets.first().unwrap(); | ||
|
|
||
| let rhs_expr = value |
There was a problem hiding this comment.
let (left_operand, operator, right_operand) = Some(
value
.as_bin_op_expr()
.map(|e| (e.left.as_ref(), e.op, e.right.as_ref()))
) else {
return;
}See let
| } | ||
| let (left_operand, operator, right_operand) = rhs_expr.unwrap(); | ||
|
|
||
| if name_expr(target, left_operand) |
There was a problem hiding this comment.
Instead of testing these conditions, you could match the target/left_operand type with match.
There may be some other rules to serve as inspiration e.g.
pylint] Implement rule to prefer augmented assignment (PLR6104)
840ef33 to
5afd7de
Compare
…stral-sh#9932) ## Summary Implement new rule: Prefer augmented assignment (astral-sh#8877). It checks for the assignment statement with the form of `<expr> = <expr> <binary-operator> …` with a unsafe fix to use augmented assignment instead. ## Test Plan 1. Snapshot test is included in the PR. 2. Manually test with playground.
Summary
Implement new rule: Prefer augmented assignment (#8877). It checks for the assignment statement with the form of
<expr> = <expr> <binary-operator> …with a unsafe fix to use augmented assignment instead.Test Plan