-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[flake8-bugbear
] Implement loop-iterator-mutation
(B909
)
#9578
[flake8-bugbear
] Implement loop-iterator-mutation
(B909
)
#9578
Conversation
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean that foo().bar
and foo.bar
would be considered identical?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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().foo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 B909
flake8-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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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] = True That'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-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 theB038.py
file).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 😀