Skip to content

Commit bcd4ca3

Browse files
Fix crash while iteraring over a class attribute (#7386)
Co-authored-by: orSolocate <[email protected]>
1 parent c116349 commit bcd4ca3

File tree

4 files changed

+24
-4
lines changed

4 files changed

+24
-4
lines changed

doc/whatsnew/fragments/7380.bugfix

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Update ``modified_iterating`` checker to fix a crash with ``for`` loops on empty list.
2+
3+
Closes #7380

pylint/checkers/modified_iterating_checker.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def _modified_iterating_check(
8181
msg_id = "modified-iterating-dict"
8282
elif isinstance(inferred, nodes.Set):
8383
msg_id = "modified-iterating-set"
84-
elif not isinstance(iter_obj, nodes.Name):
84+
elif not isinstance(iter_obj, (nodes.Name, nodes.Attribute)):
8585
pass
8686
elif self._modified_iterating_list_cond(node, iter_obj):
8787
msg_id = "modified-iterating-list"
@@ -90,10 +90,14 @@ def _modified_iterating_check(
9090
elif self._modified_iterating_set_cond(node, iter_obj):
9191
msg_id = "modified-iterating-set"
9292
if msg_id:
93+
if isinstance(iter_obj, nodes.Attribute):
94+
obj_name = iter_obj.attrname
95+
else:
96+
obj_name = iter_obj.name
9397
self.add_message(
9498
msg_id,
9599
node=node,
96-
args=(iter_obj.name,),
100+
args=(obj_name,),
97101
confidence=interfaces.INFERENCE,
98102
)
99103

tests/functional/m/modified_iterating.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""Tests for iterating-modified messages"""
2-
# pylint: disable=not-callable,unnecessary-comprehension
2+
# pylint: disable=not-callable,unnecessary-comprehension,too-few-public-methods
33

44
import copy
55

@@ -26,7 +26,7 @@
2626
i = 1
2727
for item in my_dict:
2828
item_list[0] = i # for coverage, see reference at /pull/5628#discussion_r792181642
29-
my_dict[i] = 1 # [modified-iterating-dict]
29+
my_dict[i] = 1 # [modified-iterating-dict]
3030
i += 1
3131

3232
i = 1
@@ -93,3 +93,15 @@ def update_existing_key():
9393
for key in my_dict:
9494
new_key = key.lower()
9595
my_dict[new_key] = 1 # [modified-iterating-dict]
96+
97+
98+
class MyClass:
99+
"""Regression test for https://github.com/PyCQA/pylint/issues/7380"""
100+
101+
def __init__(self) -> None:
102+
self.attribute = [1, 2, 3]
103+
104+
def my_method(self):
105+
"""This should raise as we are deleting."""
106+
for var in self.attribute:
107+
del var # [modified-iterating-list]

tests/functional/m/modified_iterating.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ modified-iterating-list:64:4:64:23::Iterated list 'item_list' is being modified
1313
modified-iterating-list:67:12:67:31::Iterated list 'item_list' is being modified inside for loop body, consider iterating through a copy of it instead.:INFERENCE
1414
modified-iterating-list:69:16:69:35::Iterated list 'item_list' is being modified inside for loop body, consider iterating through a copy of it instead.:INFERENCE
1515
modified-iterating-dict:95:8:95:28:update_existing_key:Iterated dict 'my_dict' is being modified inside for loop body, iterate through a copy of it instead.:INFERENCE
16+
modified-iterating-list:107:12:107:19:MyClass.my_method:Iterated list 'attribute' is being modified inside for loop body, consider iterating through a copy of it instead.:INFERENCE

0 commit comments

Comments
 (0)