summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--doc/whatsnew/2.0.rst3
-rw-r--r--pylint/checkers/variables.py12
-rw-r--r--pylint/test/unittest_checker_variables.py13
4 files changed, 31 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 5c60753d9..b0f373723 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -87,6 +87,11 @@ What's New in Pylint 2.0?
Close #1120
+ * Fix false positive undefined-variable for lambda argument in
+ class definitions
+
+ Close #1824
+
What's New in Pylint 1.8.1?
=========================
diff --git a/doc/whatsnew/2.0.rst b/doc/whatsnew/2.0.rst
index 783719ab6..c9060d3b1 100644
--- a/doc/whatsnew/2.0.rst
+++ b/doc/whatsnew/2.0.rst
@@ -38,3 +38,6 @@ Other Changes
* Fix false positive ``inconsistent-return-statements`` message by
avoiding useless exception inference if the exception is not handled.
+
+* Fix false positive ``undefined-variable`` for lambda argument in
+ class definitions
diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py
index f8519507d..fd01b3072 100644
--- a/pylint/checkers/variables.py
+++ b/pylint/checkers/variables.py
@@ -956,6 +956,10 @@ class VariablesChecker(BaseChecker):
def _is_variable_violation(node, name, defnode, stmt, defstmt,
frame, defframe, base_scope_type,
recursive_klass):
+ # node: Node to check for violation
+ # name: name of node to check violation for
+ # frame: Scope of statement of node
+ # base_scope_type: local scope type
maybee0601 = True
annotation_return = False
use_outer_definition = False
@@ -969,8 +973,12 @@ class VariablesChecker(BaseChecker):
else:
# we are in a local scope, check the name is not
# defined in global or builtin scope
- # skip this lookup if name is assigned later in function scope
- forbid_lookup = isinstance(frame, astroid.FunctionDef) and _assigned_locally(node)
+ # skip this lookup if name is assigned later in function scope/lambda
+ # Note: the node.frame() is not the same as the `frame` argument which is
+ # equivalent to frame.statement().scope()
+ forbid_lookup = ((isinstance(frame, astroid.FunctionDef) or
+ isinstance(node.frame(), astroid.Lambda)) and
+ _assigned_locally(node))
if not forbid_lookup and defframe.root().lookup(name)[1]:
maybee0601 = False
use_outer_definition = (
diff --git a/pylint/test/unittest_checker_variables.py b/pylint/test/unittest_checker_variables.py
index 23142ba38..4afcd22c9 100644
--- a/pylint/test/unittest_checker_variables.py
+++ b/pylint/test/unittest_checker_variables.py
@@ -165,6 +165,19 @@ class TestVariablesCheckerWithTearDown(CheckerTestCase):
with self.assertNoMessages():
self.walk(node)
+ def test_lambda_in_classdef(self):
+ # Make sure lambda doesn't raises
+ # Undefined-method in class def
+
+ # Issue 1824
+ # https://github.com/PyCQA/pylint/issues/1824
+ node = astroid.parse('''
+ class MyObject(object):
+ method1 = lambda func: func()
+ method2 = lambda function: function()
+ ''')
+ with self.assertNoMessages():
+ self.walk(node)
class TestMissingSubmodule(CheckerTestCase):
CHECKER_CLASS = variables.VariablesChecker