Skip to content

Commit

Permalink
Remove discard, remove, and pop allowance for `loop-iterator-mu…
Browse files Browse the repository at this point in the history
…tation` (#12365)

## Summary

Pretty sure this should still be an error, but also, I think I added
this because of ecosystem CI? So want to see what pops up.

Closes #12164.
  • Loading branch information
charliermarsh committed Jul 17, 2024
1 parent e39298d commit 1435b0f
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,16 @@ def __init__(self, ls):
else:
break

# should not error
# should error
for elem in some_list:
del some_list[elem]
some_list[elem] = 1
some_list.remove(elem)
some_list.discard(elem)

# should not error
for elem in some_list:
some_list[elem] = 1

# should error
for i, elem in enumerate(some_list):
some_list.pop(0)
Expand All @@ -169,4 +172,4 @@ def __init__(self, ls):

# should not error (dict)
for i, elem in enumerate(some_list):
some_list[elem] = 1
some_list[elem] = 1
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use ruff_python_ast::comparable::ComparableExpr;
use ruff_python_ast::name::UnqualifiedName;
use ruff_python_ast::{
visitor::{self, Visitor},
Arguments, Expr, ExprAttribute, ExprCall, ExprSubscript, ExprTuple, Stmt, StmtAssign,
StmtAugAssign, StmtBreak, StmtDelete, StmtFor, StmtIf,
Expr, ExprAttribute, ExprCall, ExprSubscript, ExprTuple, Stmt, StmtAssign, StmtAugAssign,
StmtBreak, StmtDelete, StmtFor, StmtIf,
};
use ruff_text_size::TextRange;
use std::collections::HashMap;
Expand Down Expand Up @@ -175,18 +175,13 @@ impl<'a> LoopMutationsVisitor<'a> {
if let Expr::Subscript(ExprSubscript {
range: _,
value,
slice,
slice: _,
ctx: _,
}) = target
{
// Find, e.g., `del items[0]`.
if ComparableExpr::from(self.iter) == ComparableExpr::from(value) {
// But allow, e.g., `for item in items: del items[item]`.
if ComparableExpr::from(self.index) != ComparableExpr::from(slice)
&& ComparableExpr::from(self.target) != ComparableExpr::from(slice)
{
self.add_mutation(range);
}
self.add_mutation(range);
}
}
}
Expand Down Expand Up @@ -223,7 +218,7 @@ impl<'a> LoopMutationsVisitor<'a> {
}

/// Handle, e.g., `items.append(1)`.
fn handle_call(&mut self, func: &Expr, arguments: &Arguments) {
fn handle_call(&mut self, func: &Expr) {
if let Expr::Attribute(ExprAttribute {
range,
value,
Expand All @@ -234,20 +229,6 @@ impl<'a> LoopMutationsVisitor<'a> {
if is_mutating_function(attr.as_str()) {
// Find, e.g., `items.remove(1)`.
if ComparableExpr::from(self.iter) == ComparableExpr::from(value) {
// But allow, e.g., `for item in items: items.remove(item)`.
if matches!(attr.as_str(), "remove" | "discard" | "pop") {
if arguments.len() == 1 {
if let [arg] = &*arguments.args {
if ComparableExpr::from(self.index) == ComparableExpr::from(arg)
|| ComparableExpr::from(self.target)
== ComparableExpr::from(arg)
{
return;
}
}
}
}

self.add_mutation(*range);
}
}
Expand Down Expand Up @@ -323,11 +304,8 @@ impl<'a> Visitor<'a> for LoopMutationsVisitor<'a> {

fn visit_expr(&mut self, expr: &'a Expr) {
// Ex) `items.append(1)`
if let Expr::Call(ExprCall {
func, arguments, ..
}) = expr
{
self.handle_call(func, arguments);
if let Expr::Call(ExprCall { func, .. }) = expr {
self.handle_call(func);
}

visitor::walk_expr(self, expr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,12 +340,41 @@ B909.py:150:8: B909 Mutation to loop iterable `some_list` during iteration
152 | else:
|

B909.py:164:5: B909 Mutation to loop iterable `some_list` during iteration
B909.py:157:5: B909 Mutation to loop iterable `some_list` during iteration
|
162 | # should error
163 | for i, elem in enumerate(some_list):
164 | some_list.pop(0)
155 | # should error
156 | for elem in some_list:
157 | del some_list[elem]
| ^^^^^^^^^^^^^^^^^^^ B909
158 | some_list.remove(elem)
159 | some_list.discard(elem)
|

B909.py:158:5: B909 Mutation to loop iterable `some_list` during iteration
|
156 | for elem in some_list:
157 | del some_list[elem]
158 | some_list.remove(elem)
| ^^^^^^^^^^^^^^^^ B909
159 | some_list.discard(elem)
|

B909.py:159:5: B909 Mutation to loop iterable `some_list` during iteration
|
157 | del some_list[elem]
158 | some_list.remove(elem)
159 | some_list.discard(elem)
| ^^^^^^^^^^^^^^^^^ B909
160 |
161 | # should not error
|

B909.py:167:5: B909 Mutation to loop iterable `some_list` during iteration
|
165 | # should error
166 | for i, elem in enumerate(some_list):
167 | some_list.pop(0)
| ^^^^^^^^^^^^^ B909
165 |
166 | # should not error (list)
168 |
169 | # should not error (list)
|

0 comments on commit 1435b0f

Please sign in to comment.