diff options
| author | Torsten Marek <shlomme@gmail.com> | 2014-07-25 10:42:41 +0200 |
|---|---|---|
| committer | Torsten Marek <shlomme@gmail.com> | 2014-07-25 10:42:41 +0200 |
| commit | b626280fe7b2eca2359441b85535846b41bad73f (patch) | |
| tree | 5903baa59e4ba059e2770b8b23545799e4e47ac0 | |
| parent | 51c5dc1b89d899fa750440f11df6b561560826e4 (diff) | |
| download | pylint-git-b626280fe7b2eca2359441b85535846b41bad73f.tar.gz | |
Fix more edge cases in the cell-var-from-loop warning (Closes: #233).
| -rw-r--r-- | checkers/variables.py | 10 | ||||
| -rw-r--r-- | test/input/func_loopvar_in_closure.py | 18 | ||||
| -rw-r--r-- | test/messages/func_loopvar_in_closure.txt | 12 |
3 files changed, 33 insertions, 7 deletions
diff --git a/checkers/variables.py b/checkers/variables.py index 8f8ee87a0..3b9bcda2c 100644 --- a/checkers/variables.py +++ b/checkers/variables.py @@ -542,9 +542,15 @@ builtins. Remember that you should avoid to define new builtins when possible.' self.add_message('global-statement', node=node) def _check_late_binding_closure(self, node, assignment_node, scope_type): + def _is_direct_lambda_call(): + return (isinstance(node_scope.parent, astroid.CallFunc) + and node_scope.parent.func is node_scope) + node_scope = node.scope() if not isinstance(node_scope, (astroid.Lambda, astroid.Function)): return + if isinstance(node.parent, astroid.Arguments): + return if isinstance(assignment_node, astroid.Comprehension): if assignment_node.parent.parent_of(node.scope()): @@ -557,7 +563,9 @@ builtins. Remember that you should avoid to define new builtins when possible.' break maybe_for = maybe_for.parent else: - if maybe_for.parent_of(node_scope) and not isinstance(node_scope.statement(), astroid.Return): + if (maybe_for.parent_of(node_scope) + and not _is_direct_lambda_call() + and not isinstance(node_scope.statement(), astroid.Return)): self.add_message('cell-var-from-loop', node=node, args=node.name) def _loopvar_name(self, node, name): diff --git a/test/input/func_loopvar_in_closure.py b/test/input/func_loopvar_in_closure.py index 32b7a6c6e..3a791d335 100644 --- a/test/input/func_loopvar_in_closure.py +++ b/test/input/func_loopvar_in_closure.py @@ -53,6 +53,23 @@ def good_case7(): return lambda: -1 +def good_case8(): + """Lambda defined and called in loop.""" + for i in range(10): + print (lambda x: i + x)(1) + + +def good_case9(): + """Another eager binding of the cell variable.""" + funs = [] + for i in range(10): + def func(bound_i=i): + """Ignore.""" + return bound_i + funs.append(func) + return funs + + def bad_case(): """Closing over a loop variable.""" lst = [] @@ -112,3 +129,4 @@ def bad_case6(): print j lst.append(lambda: i) return lst + diff --git a/test/messages/func_loopvar_in_closure.txt b/test/messages/func_loopvar_in_closure.txt index 6ca613a59..5b068f45d 100644 --- a/test/messages/func_loopvar_in_closure.txt +++ b/test/messages/func_loopvar_in_closure.txt @@ -1,8 +1,8 @@ W: 21:good_case3: Unused variable 'i' W: 45:good_case6.<lambda>: Using possibly undefined loop variable 'i' -W: 61:bad_case.<lambda>: Cell variable i defined in loop -W: 66:bad_case2.<lambda>: Cell variable i defined in loop -W: 74:bad_case3.<lambda>: Cell variable j defined in loop -W: 84:bad_case4.nested: Cell variable i defined in loop -W:105:bad_case5.<lambda>: Cell variable i defined in loop -W:113:bad_case6.<lambda>: Cell variable i defined in loop +W: 78:bad_case.<lambda>: Cell variable i defined in loop +W: 83:bad_case2.<lambda>: Cell variable i defined in loop +W: 91:bad_case3.<lambda>: Cell variable j defined in loop +W:101:bad_case4.nested: Cell variable i defined in loop +W:122:bad_case5.<lambda>: Cell variable i defined in loop +W:130:bad_case6.<lambda>: Cell variable i defined in loop |
