summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcpopa <devnull@localhost>2014-07-17 23:31:24 +0300
committercpopa <devnull@localhost>2014-07-17 23:31:24 +0300
commitd61747ad0031f10f06145cc848d6d13c089f292f (patch)
treeef3f73e3034965c2a9125c3888eeb261b30dbfe5
parent235ee6dd14de0678d4f219bd57624c10af816cd0 (diff)
downloadpylint-d61747ad0031f10f06145cc848d6d13c089f292f.tar.gz
Fix an 'unused-variable' false positive, where the variable is assigned through an import. Closes issue #196.
-rw-r--r--ChangeLog3
-rw-r--r--checkers/variables.py42
-rw-r--r--test/input/func_w0612.py18
-rw-r--r--test/messages/func_w0612.txt8
4 files changed, 67 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 0e005c4..390b374 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -36,6 +36,9 @@ ChangeLog for Pylint
* Don't emit 'no-name-in-module' for ignored modules.
Closes issue #223.
+ * Fix an 'unused-variable' false positive, where the variable is
+ assigned through an import. Closes issue #196.
+
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/variables.py b/checkers/variables.py
index 6cbcdb6..94a8d6e 100644
--- a/checkers/variables.py
+++ b/checkers/variables.py
@@ -356,6 +356,10 @@ builtins. Remember that you should avoid to define new builtins when possible.'
authorized_rgx = self.config.dummy_variables_rgx
called_overridden = False
argnames = node.argnames()
+ global_names = set()
+ for global_stmt in node.nodes_of_class(astroid.Global):
+ global_names.update(set(global_stmt.names))
+
for name, stmts in not_consumed.iteritems():
# ignore some special names specified by user configuration
if authorized_rgx.match(name):
@@ -365,6 +369,23 @@ builtins. Remember that you should avoid to define new builtins when possible.'
stmt = stmts[0]
if isinstance(stmt, astroid.Global):
continue
+ if isinstance(stmt, (astroid.Import, astroid.From)):
+ # Detect imports, assigned to global statements.
+ if global_names:
+ skip = False
+ for import_name, import_alias in stmt.names:
+ # If the import uses an alias, check only that.
+ # Otherwise, check only the import name.
+ if import_alias:
+ if import_alias in global_names:
+ skip = True
+ break
+ elif import_name in global_names:
+ skip = True
+ break
+ if skip:
+ continue
+
# care about functions with unknown argument (builtins)
if name in argnames:
if is_method:
@@ -412,7 +433,26 @@ builtins. Remember that you should avoid to define new builtins when possible.'
break
else:
# global but no assignment
- self.add_message('global-variable-not-assigned', args=name, node=node)
+ # Detect imports in the current frame, with the required
+ # name. Such imports can be considered assignments.
+ imports = frame.nodes_of_class((astroid.Import, astroid.From))
+ for import_node in imports:
+ found = False
+ for import_name, import_alias in import_node.names:
+ # If the import uses an alias, check only that.
+ # Otherwise, check only the import name.
+ if import_alias:
+ if import_alias == name:
+ found = True
+ break
+ elif import_name and import_name == name:
+ found = True
+ break
+ if found:
+ break
+ else:
+ self.add_message('global-variable-not-assigned',
+ args=name, node=node)
default_message = False
if not assign_nodes:
continue
diff --git a/test/input/func_w0612.py b/test/input/func_w0612.py
index 57e139c..e871bb2 100644
--- a/test/input/func_w0612.py
+++ b/test/input/func_w0612.py
@@ -1,7 +1,8 @@
"""test unused variable
"""
-
+# pylint: disable=invalid-name, redefined-outer-name
__revision__ = 0
+PATH = OS = collections = deque = None
def function(matches):
""""yo"""
@@ -20,3 +21,18 @@ def visit_if(self, node):
self.inc_branch(branches)
self.stmts += branches
+def test_global():
+ """ Test various assignments of global
+ variables through imports.
+ """
+ global PATH, OS, collections, deque
+ from os import path as PATH
+ import os as OS
+ import collections
+ from collections import deque
+ # make sure that these triggers unused-variable
+ from sys import platform
+ from sys import version as VERSION
+ import this
+ import re as RE
+
diff --git a/test/messages/func_w0612.txt b/test/messages/func_w0612.txt
index f1647a3..c81b4f9 100644
--- a/test/messages/func_w0612.txt
+++ b/test/messages/func_w0612.txt
@@ -1,2 +1,6 @@
-W: 8:function: Unused variable 'aaaa'
-W: 9:function: Unused variable 'index'
+W: 9:function: Unused variable 'aaaa'
+W: 10:function: Unused variable 'index'
+W: 34:test_global: Unused variable 'platform'
+W: 35:test_global: Unused variable 'VERSION'
+W: 36:test_global: Unused variable 'this'
+W: 37:test_global: Unused variable 'RE'