summaryrefslogtreecommitdiff
path: root/pylint/checkers/refactoring/refactoring_checker.py
diff options
context:
space:
mode:
authorTim Martin <tim@asymptotic.co.uk>2022-06-04 07:02:51 +0100
committerGitHub <noreply@github.com>2022-06-04 08:02:51 +0200
commitbdd470d074aa6fda47298f64a487b66d9234ec0a (patch)
tree9c33769831ff36ce8862a0e73eb86aae06be82f7 /pylint/checkers/refactoring/refactoring_checker.py
parent44a3d96e1af985c6ad290a51555b9c7ced0a7079 (diff)
downloadpylint-git-bdd470d074aa6fda47298f64a487b66d9234ec0a.tar.gz
Prevent warnings on dict / list index lookup with destructuring assignment (#6808)
Co-authored-by: Jacob Walls <jacobtylerwalls@gmail.com>
Diffstat (limited to 'pylint/checkers/refactoring/refactoring_checker.py')
-rw-r--r--pylint/checkers/refactoring/refactoring_checker.py34
1 files changed, 24 insertions, 10 deletions
diff --git a/pylint/checkers/refactoring/refactoring_checker.py b/pylint/checkers/refactoring/refactoring_checker.py
index 480078df8..66773e2b3 100644
--- a/pylint/checkers/refactoring/refactoring_checker.py
+++ b/pylint/checkers/refactoring/refactoring_checker.py
@@ -160,6 +160,25 @@ def _will_be_released_automatically(node: nodes.Call) -> bool:
return func.qname() in callables_taking_care_of_exit
+def _is_part_of_assignment_target(node: nodes.NodeNG) -> bool:
+ """Check whether use of a variable is happening as part of the left-hand
+ side of an assignment.
+
+ This requires recursive checking, because destructuring assignment can have
+ arbitrarily nested tuples and lists to unpack.
+ """
+ if isinstance(node.parent, nodes.Assign):
+ return node in node.parent.targets
+
+ if isinstance(node.parent, nodes.AugAssign):
+ return node == node.parent.target
+
+ if isinstance(node.parent, (nodes.Tuple, nodes.List)):
+ return _is_part_of_assignment_target(node.parent)
+
+ return False
+
+
class ConsiderUsingWithStack(NamedTuple):
"""Stack for objects that may potentially trigger a R1732 message
if they are not used in a ``with`` block later on.
@@ -1917,15 +1936,13 @@ class RefactoringChecker(checkers.BaseTokenChecker):
value = subscript.slice
- if isinstance(node, nodes.For) and (
- isinstance(subscript.parent, nodes.Assign)
- and subscript in subscript.parent.targets
- or isinstance(subscript.parent, nodes.AugAssign)
- and subscript == subscript.parent.target
+ if isinstance(node, nodes.For) and _is_part_of_assignment_target(
+ subscript
):
# Ignore this subscript if it is the target of an assignment
# Early termination; after reassignment dict index lookup will be necessary
return
+
if isinstance(subscript.parent, nodes.Delete):
# Ignore this subscript if it's used with the delete keyword
return
@@ -2017,11 +2034,8 @@ class RefactoringChecker(checkers.BaseTokenChecker):
)
for child in children:
for subscript in child.nodes_of_class(nodes.Subscript):
- if isinstance(node, nodes.For) and (
- isinstance(subscript.parent, nodes.Assign)
- and subscript in subscript.parent.targets
- or isinstance(subscript.parent, nodes.AugAssign)
- and subscript == subscript.parent.target
+ if isinstance(node, nodes.For) and _is_part_of_assignment_target(
+ subscript
):
# Ignore this subscript if it is the target of an assignment
# Early termination; after reassignment index lookup will be necessary