summaryrefslogtreecommitdiff
path: root/pylint/checkers/base.py
diff options
context:
space:
mode:
Diffstat (limited to 'pylint/checkers/base.py')
-rw-r--r--pylint/checkers/base.py27
1 files changed, 27 insertions, 0 deletions
diff --git a/pylint/checkers/base.py b/pylint/checkers/base.py
index 6cff1e2..38cf0ab 100644
--- a/pylint/checkers/base.py
+++ b/pylint/checkers/base.py
@@ -328,6 +328,10 @@ class BasicErrorChecker(_BasicChecker):
'continue-in-finally',
'Emitted when the `continue` keyword is found '
'inside a finally clause, which is a SyntaxError.'),
+ 'E0117': ("nonlocal variable without binding",
+ 'nonlocal-without-binding',
+ 'Emitted when a nonlocal variable is not bound',
+ {'minversion': (3, 0)}),
}
@check_messages('function-redefined')
@@ -452,6 +456,29 @@ class BasicErrorChecker(_BasicChecker):
(node.operand.op == node.op)):
self.add_message('nonexistent-operator', node=node, args=node.op*2)
+ def _check_nonlocal_without_binding(self, node, name):
+ current_scope = node.scope()
+ while True:
+ if current_scope.parent is None:
+ break
+
+ if not isinstance(current_scope, astroid.FunctionDef):
+ self.add_message('nonlocal-without-binding', node=node)
+ break
+ else:
+ if name not in current_scope.locals:
+ current_scope = current_scope.parent.scope()
+ continue
+ else:
+ return
+
+ self.add_message('nonlocal-without-binding', node=node)
+
+ @check_messages('nonlocal-without-binding')
+ def visit_nonlocal(self, node):
+ for name in node.names:
+ self._check_nonlocal_without_binding(node, name)
+
@check_messages('abstract-class-instantiated')
def visit_call(self, node):
""" Check instantiating abstract class with