Skip to content

Commit

Permalink
Fix crash while iteraring over a class attribute (#7386)
Browse files Browse the repository at this point in the history
Co-authored-by: orSolocate <38433858+orSolocate@users.noreply.github.com>
  • Loading branch information
DanielNoord and orSolocate committed Aug 31, 2022
1 parent c116349 commit bcd4ca3
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 4 deletions.
3 changes: 3 additions & 0 deletions doc/whatsnew/fragments/7380.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Update ``modified_iterating`` checker to fix a crash with ``for`` loops on empty list.

Closes #7380
8 changes: 6 additions & 2 deletions pylint/checkers/modified_iterating_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def _modified_iterating_check(
msg_id = "modified-iterating-dict"
elif isinstance(inferred, nodes.Set):
msg_id = "modified-iterating-set"
elif not isinstance(iter_obj, nodes.Name):
elif not isinstance(iter_obj, (nodes.Name, nodes.Attribute)):
pass
elif self._modified_iterating_list_cond(node, iter_obj):
msg_id = "modified-iterating-list"
Expand All @@ -90,10 +90,14 @@ def _modified_iterating_check(
elif self._modified_iterating_set_cond(node, iter_obj):
msg_id = "modified-iterating-set"
if msg_id:
if isinstance(iter_obj, nodes.Attribute):
obj_name = iter_obj.attrname
else:
obj_name = iter_obj.name
self.add_message(
msg_id,
node=node,
args=(iter_obj.name,),
args=(obj_name,),
confidence=interfaces.INFERENCE,
)

Expand Down
16 changes: 14 additions & 2 deletions tests/functional/m/modified_iterating.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Tests for iterating-modified messages"""
# pylint: disable=not-callable,unnecessary-comprehension
# pylint: disable=not-callable,unnecessary-comprehension,too-few-public-methods

import copy

Expand All @@ -26,7 +26,7 @@
i = 1
for item in my_dict:
item_list[0] = i # for coverage, see reference at /pull/5628#discussion_r792181642
my_dict[i] = 1 # [modified-iterating-dict]
my_dict[i] = 1 # [modified-iterating-dict]
i += 1

i = 1
Expand Down Expand Up @@ -93,3 +93,15 @@ def update_existing_key():
for key in my_dict:
new_key = key.lower()
my_dict[new_key] = 1 # [modified-iterating-dict]


class MyClass:
"""Regression test for https://github.com/PyCQA/pylint/issues/7380"""

def __init__(self) -> None:
self.attribute = [1, 2, 3]

def my_method(self):
"""This should raise as we are deleting."""
for var in self.attribute:
del var # [modified-iterating-list]
1 change: 1 addition & 0 deletions tests/functional/m/modified_iterating.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ modified-iterating-list:64:4:64:23::Iterated list 'item_list' is being modified
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
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
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
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 comments on commit bcd4ca3

Please sign in to comment.