summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2014-07-23 13:32:22 +0200
committerClaudiu Popa <pcmanticore@gmail.com>2014-07-23 13:32:22 +0200
commitc556997d7814f883a0b9571e724f33d0168b450b (patch)
treef4a261032df94e187b161fb9ed66a0cde8d4b5d8
parent228cf2146e6485e34e78b73570ea0a5a5ec05e75 (diff)
parentaad6ec6e17654b1c202d33912dfcc55fb9288441 (diff)
downloadpylint-c556997d7814f883a0b9571e724f33d0168b450b.tar.gz
Merged in PCManticore/pylint/metaclass_undefined (pull request #111)
Emit 'undefined-variable' for undefined names used as metaclasses with Python 3 `metaclass=` syntax.
-rw-r--r--ChangeLog3
-rw-r--r--checkers/__init__.py4
-rw-r--r--checkers/strings.py8
-rw-r--r--checkers/variables.py6
-rw-r--r--test/input/func_noerror_unused_variable_py30.py14
5 files changed, 28 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 35e4753..2d2006a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -46,6 +46,9 @@ ChangeLog for Pylint
* Definition order is considered for classes, function arguments
and annotations. Closes issue #257.
+ * Don't emit 'unused-variable' when assigning to a nonlocal.
+ Closes issue #275.
+
2014-04-30 -- 1.2.1
* Restore the ability to specify the init-hook option via the
configuration file, which was accidentally broken in 1.2.0.
diff --git a/checkers/__init__.py b/checkers/__init__.py
index af7965b..693a5ff 100644
--- a/checkers/__init__.py
+++ b/checkers/__init__.py
@@ -42,7 +42,6 @@ import sys
import tokenize
import warnings
-from astroid.utils import ASTWalker
from logilab.common.configuration import OptionsProviderMixIn
from pylint.reporters import diff_string
@@ -69,7 +68,7 @@ def table_lines_from_stats(stats, old_stats, columns):
return lines
-class BaseChecker(OptionsProviderMixIn, ASTWalker):
+class BaseChecker(OptionsProviderMixIn):
"""base class for checkers"""
# checker name (you may reuse an existing one)
name = None
@@ -87,7 +86,6 @@ class BaseChecker(OptionsProviderMixIn, ASTWalker):
linter is an object implementing ILinter
"""
- ASTWalker.__init__(self, self)
self.name = self.name.lower()
OptionsProviderMixIn.__init__(self)
self.linter = linter
diff --git a/checkers/strings.py b/checkers/strings.py
index 4fe16dd..ad63580 100644
--- a/checkers/strings.py
+++ b/checkers/strings.py
@@ -327,10 +327,10 @@ class StringMethodsChecker(BaseChecker):
self.add_message('bad-format-string', node=node)
return
- manual_fields = {field[0] for field in fields
- if isinstance(field[0], int)}
- named_fields = {field[0] for field in fields
- if isinstance(field[0], str)}
+ manual_fields = set(field[0] for field in fields
+ if isinstance(field[0], int))
+ named_fields = set(field[0] for field in fields
+ if isinstance(field[0], str))
if manual_fields and num_args:
self.add_message('format-combined-specification',
node=node)
diff --git a/checkers/variables.py b/checkers/variables.py
index aa63177..8f8ee87 100644
--- a/checkers/variables.py
+++ b/checkers/variables.py
@@ -422,8 +422,11 @@ builtins. Remember that you should avoid to define new builtins when possible.'
called_overridden = False
argnames = node.argnames()
global_names = set()
+ nonlocal_names = set()
for global_stmt in node.nodes_of_class(astroid.Global):
global_names.update(set(global_stmt.names))
+ for nonlocal_stmt in node.nodes_of_class(astroid.Nonlocal):
+ nonlocal_names.update(set(nonlocal_stmt.names))
for name, stmts in not_consumed.iteritems():
# ignore some special names specified by user configuration
@@ -470,6 +473,9 @@ builtins. Remember that you should avoid to define new builtins when possible.'
continue
self.add_message('unused-argument', args=name, node=stmt)
else:
+ if stmt.parent and isinstance(stmt.parent, astroid.Assign):
+ if name in nonlocal_names:
+ continue
self.add_message('unused-variable', args=name, node=stmt)
@check_messages('global-variable-undefined', 'global-variable-not-assigned', 'global-statement',
diff --git a/test/input/func_noerror_unused_variable_py30.py b/test/input/func_noerror_unused_variable_py30.py
new file mode 100644
index 0000000..ffcc978
--- /dev/null
+++ b/test/input/func_noerror_unused_variable_py30.py
@@ -0,0 +1,14 @@
+""" Test nonlocal uses and unused-variable. """
+
+__revision__ = 1
+
+def test_nonlocal():
+ """ Test that assigning to a nonlocal does not trigger
+ an 'unused-variable' warnings.
+ """
+ attr = True
+ def set_value(val):
+ """ Set the value in a nonlocal. """
+ nonlocal attr
+ attr = val
+ return set_value