summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Walls <jacobtylerwalls@gmail.com>2022-05-01 09:56:08 -0400
committerPierre Sassoulas <pierre.sassoulas@gmail.com>2022-05-02 16:38:19 +0200
commit135477af5331f11981d1ffeb3b4adc3a6878669a (patch)
tree8f10f70e1f8c4646c9cf13a20c46f688e05bee01
parent33a9aba4321f4b3fef8e9aefcfc9aa10abed1836 (diff)
downloadpylint-git-135477af5331f11981d1ffeb3b4adc3a6878669a.tar.gz
Fix a false positive for `undefined-loop-variable` when a loop else raises or returns (#6480)
Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com>
-rw-r--r--ChangeLog5
-rw-r--r--doc/whatsnew/2.13.rst5
-rw-r--r--pylint/checkers/variables.py8
-rw-r--r--tests/functional/u/undefined/undefined_loop_variable.py16
4 files changed, 33 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index c52bf9033..7c630d631 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -34,6 +34,11 @@ Release date: TBA
Closes #5930
+* Fix a false positive for ``undefined-loop-variable`` when the ``else`` of a ``for``
+ loop raises or returns.
+
+ Closes #5971
+
* Fix false positive for ``unused-variable`` for classes inside functions
and where a metaclass is provided via a call.
diff --git a/doc/whatsnew/2.13.rst b/doc/whatsnew/2.13.rst
index 1d86a6fd9..5f3c86673 100644
--- a/doc/whatsnew/2.13.rst
+++ b/doc/whatsnew/2.13.rst
@@ -607,6 +607,11 @@ Other Changes
Closes #5769
+* Fix a false positive for ``undefined-loop-variable`` when the ``else`` of a ``for``
+ loop raises or returns.
+
+ Closes #5971
+
* Fix false positive for ``unused-variable`` for classes inside functions
and where a metaclass is provided via a call.
diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py
index 2e4f4d70f..807e031e6 100644
--- a/pylint/checkers/variables.py
+++ b/pylint/checkers/variables.py
@@ -2207,6 +2207,7 @@ class VariablesChecker(BaseChecker):
scope = node.scope()
# FunctionDef subclasses Lambda due to a curious ontology. Check both.
# See https://github.com/PyCQA/astroid/issues/291
+ # pylint: disable-next=fixme
# TODO: Revisit when astroid 3.0 includes the change
if isinstance(scope, nodes.Lambda) and any(
asmt.scope().parent_of(scope) for asmt in astmts
@@ -2252,11 +2253,16 @@ class VariablesChecker(BaseChecker):
):
return
- # For functions we can do more by inferring the length of the itered object
if not isinstance(assign, nodes.For):
self.add_message("undefined-loop-variable", args=node.name, node=node)
return
+ if any(
+ isinstance(else_stmt, (nodes.Return, nodes.Raise))
+ for else_stmt in assign.orelse
+ ):
+ return
+ # For functions we can do more by inferring the length of the itered object
try:
inferred = next(assign.iter.infer())
except astroid.InferenceError:
diff --git a/tests/functional/u/undefined/undefined_loop_variable.py b/tests/functional/u/undefined/undefined_loop_variable.py
index 0270c6b53..6bcf6103d 100644
--- a/tests/functional/u/undefined/undefined_loop_variable.py
+++ b/tests/functional/u/undefined/undefined_loop_variable.py
@@ -91,6 +91,22 @@ def test(content):
handle_line(layne)
+def for_else_returns(iterable):
+ for thing in iterable:
+ break
+ else:
+ return
+ print(thing)
+
+
+def for_else_raises(iterable):
+ for thing in iterable:
+ break
+ else:
+ raise Exception
+ print(thing)
+
+
lst = []
lst2 = [1, 2, 3]