[flake8-bugbear] Implement loop-iterator-mutation (B909)#9578
[flake8-bugbear] Implement loop-iterator-mutation (B909)#9578charliermarsh merged 18 commits intoastral-sh:mainfrom
flake8-bugbear] Implement loop-iterator-mutation (B909)#9578Conversation
The B038 rule checks for mutation of loop iterators in the body of a for loop and alerts when found. Editing the loop iterator can lead to undesired behavior and is probably a bug in most cases.
|
Awesome, thank you! Excited to review, I'll give it a close read per request :) |
crates/ruff_linter/src/rules/flake8_bugbear/rules/loop_iterator_mutated.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/flake8_bugbear/rules/loop_iterator_mutated.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/flake8_bugbear/rules/loop_iterator_mutated.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/flake8_bugbear/rules/loop_iterator_mutated.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/flake8_bugbear/rules/loop_iterator_mutated.rs
Outdated
Show resolved
Hide resolved
crates/ruff_linter/src/rules/flake8_bugbear/rules/loop_iterator_mutated.rs
Outdated
Show resolved
Hide resolved
| return _to_name_str(func); | ||
| } | ||
| _ => { | ||
| return "".into(); |
There was a problem hiding this comment.
This feels off to me... Can you give me some more context on what this function is intended to do?
There was a problem hiding this comment.
I think this is just the base case of the recursion.
Probably gonna remove this function anyway in favor of compose_call_path.
| } | ||
| } | ||
| Expr::Call(ExprCall { range: _, func, .. }) => { | ||
| return _to_name_str(func); |
There was a problem hiding this comment.
Does this mean that foo().bar and foo.bar would be considered identical?
There was a problem hiding this comment.
I tried out collect_call_path and compose_call_path as you've suggested below, and both of them return None for a().foo.
Not 100% sure how I should go about this - should this be the case?
Also wondering, would you say the following should be caught?:
for bar in a().foo:
del a().fooThere was a problem hiding this comment.
I would say that should not be caught, since we can't know that a() returns the same object.
There was a problem hiding this comment.
ok, then I think I can use compose_call_path - I was just worrying that it returns None whenever there is a() in the call path.
| } | ||
| } | ||
|
|
||
| fn _to_name_str(node: &Expr) -> String { |
There was a problem hiding this comment.
You may want collect_call_path for this, we have an abstraction for this exact thing, but it stores structured components (like a vector of the dot-separated pieces) rather than a String.
There was a problem hiding this comment.
Could it be that the function was removed or renamed? I can't find it anymore.
crates/ruff_linter/src/rules/flake8_bugbear/rules/loop_iterator_mutated.rs
Outdated
Show resolved
Hide resolved
|
Thank you! Left some comments -- feel free to ask questions. |
5f0800b to
d32ae77
Compare
|
Do you have any suggestion on how to set up the work environment? In general I think |
|
Awesome, I should be able to review and merge this today! |
c240966 to
fe9e35d
Compare
|
@charliermarsh please hold off from merging, I still want to remote the Also, in |
|
@mimre25 - Roger that! |
|
@mimre25 - I'm going to convert to draft for now just to help manage our review workflow. |
|
I close because it is stale. Please re-open if you plan to follow up on the remaining work. |
|
Alright, I finally got around to finish this. This is now on parity with flake8-bugbear's B909 (it was renamed). Main new features in the new commits are described in PyCQA/flake8-bugbear#454. |
|
Thanks! I'll take a look. |
crates/ruff_linter/resources/test/fixtures/flake8_bugbear/B909.py
Outdated
Show resolved
Hide resolved
flake8-bugbear] Implement B909
flake8-bugbear] Implement B909flake8-bugbear] Implement loop-iterator-mutation (B909)
| } | ||
|
|
||
| /// Handle, e.g., `items += [1]`. | ||
| fn handle_aug_assign(&mut self, range: TextRange, target: &Expr) { |
There was a problem hiding this comment.
All these &Box<Expr> were changed to &Expr.
| } | ||
|
|
||
| /// Handle, e.g., `items[0] = 1`. | ||
| fn handle_assign(&mut self, range: TextRange, targets: &[Expr]) { |
There was a problem hiding this comment.
All these &Vec<Expr> were changed to &[Expr]. You almost always want the latter -- it's a lot more flexible, because any reference to a vector can be passed in, but so can other kinds of slices.
aa8d74f to
5bdb18f
Compare
|
| code | total | + violation | - violation | + fix | - fix |
|---|---|---|---|---|---|
| B909 | 5 | 5 | 0 | 0 | 0 |
|
There are some false positives in here. For example: for auth_method in authentication_methods_dict:
authentication_methods_dict[auth_method] = TrueThat's probably the most common? |
48c23b9 to
e0a1a4f
Compare
…l-sh#9578) ## Summary This PR adds the implementation for the current [flake8-bugbear](https://github.com/PyCQA/flake8-bugbear)'s B038 rule. The B038 rule checks for mutation of loop iterators in the body of a for loop and alerts when found. Rational: Editing the loop iterator can lead to undesired behavior and is probably a bug in most cases. Closes astral-sh#9511. Note there will be a second iteration of B038 implemented in `flake8-bugbear` soon, and this PR currently only implements the weakest form of the rule. I'd be happy to also implement the further improvements to B038 here in ruff 🙂 See PyCQA/flake8-bugbear#454 for more information on the planned improvements. ## Test Plan Re-using the same test file that I've used for `flake8-bugbear`, which is included in this PR (look for the `B038.py` file). Note: this is my first time using `rust` (beside `rustlings`) - I'd be very happy about thorough feedback on what I could've done better :slightly_smiling_face: - Bring it on :grinning:
Summary
This PR adds the implementation for the current flake8-bugbear's B038 rule.
The B038 rule checks for mutation of loop iterators in the body of a for loop and alerts when found.
Rational:
Editing the loop iterator can lead to undesired behavior and is probably a bug in most cases.
Closes #9511.
Note there will be a second iteration of B038 implemented in
flake8-bugbearsoon, and this PR currently only implements the weakest form of the rule.I'd be happy to also implement the further improvements to B038 here in ruff 🙂
See PyCQA/flake8-bugbear#454 for more information on the planned improvements.
Test Plan
Re-using the same test file that I've used for
flake8-bugbear, which is included in this PR (look for theB038.pyfile).Note: this is my first time using
rust(besiderustlings) - I'd be very happy about thorough feedback on what I could've done better 🙂 - Bring it on 😀