Skip to content

Commit

Permalink
Add a new option for finding unused global variables.
Browse files Browse the repository at this point in the history
Closes #919
  • Loading branch information
rogalski authored and PCManticore committed Dec 13, 2016
1 parent 3a94b38 commit 740d250
Show file tree
Hide file tree
Showing 12 changed files with 50 additions and 2 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ Order doesn't matter (not that much, at least ;)

* Mike Frysinger: contributor.

* Łukasz Rogalski: invalid-length-returned
* Łukasz Rogalski: contributor.

* Moisés López (Vauxoo): Support for deprecated-modules in modules not installed,
Refactory wrong-import-order to integrate it with `isort` library
Expand Down
3 changes: 3 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ Release date: tba

* Added refactoring message 'no-else-return'.

* Improve unused-variable checker to warn about unused variables in module scope.

Closes #919


What's new in Pylint 1.6.3?
Expand Down
5 changes: 5 additions & 0 deletions doc/whatsnew/2.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,11 @@ Bug fixes
def _(x):
return -x
* `unused-variable` checker has new functionality of warning about unused
variables in global module namespace. Since globals in module namespace
may be a part of exposed API, this check is disabled by default. For
enabling it, set `allow-global-unused-variables` to false.

Removed Changes
===============

Expand Down
22 changes: 21 additions & 1 deletion pylint/checkers/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,13 @@ class VariablesChecker(BaseChecker):
'help' : 'Argument names that match this expression will be '
'ignored. Default to name with leading underscore'}
),
('allow-global-unused-variables',
{'default': True,
'type': 'yn', 'metavar': '<y_or_n>',
'help': 'Tells whether unused global variables should be treated as a violation.'}
),
)

def __init__(self, linter=None):
BaseChecker.__init__(self, linter)
self._to_consume = None # list of tuples: (to_consume:dict, consumed:dict, scope_type:str)
Expand All @@ -374,6 +380,9 @@ def _analyse_fallback_blocks(self):
def _ignored_modules(self):
return get_global_option(self, 'ignored-modules', default=[])

@decorators.cachedproperty
def _allow_global_unused_variables(self):
return get_global_option(self, 'allow-global-unused-variables', default=True)

@utils.check_messages('redefined-outer-name')
def visit_for(self, node):
Expand Down Expand Up @@ -413,7 +422,7 @@ def visit_module(self, node):

@utils.check_messages('unused-import', 'unused-wildcard-import',
'redefined-builtin', 'undefined-all-variable',
'invalid-all-object')
'invalid-all-object', 'unused-variable')
def leave_module(self, node):
"""leave module: check globals
"""
Expand All @@ -422,6 +431,10 @@ def leave_module(self, node):
# attempt to check for __all__ if defined
if '__all__' in node.locals:
self._check_all(node, not_consumed)

# check for unused globals
self._check_globals(not_consumed)

# don't check unused imports in __init__ files
if not self.config.init_import and node.package:
return
Expand Down Expand Up @@ -476,6 +489,13 @@ def _check_all(self, node, not_consumed):
# when the file will be checked
pass

def _check_globals(self, not_consumed):
if self._allow_global_unused_variables:
return
for name, nodes in six.iteritems(not_consumed):
for node in nodes:
self.add_message('unused-variable', args=(name,), node=node)

def _check_imports(self, not_consumed):
local_names = _fix_dot_imports(not_consumed)
checked = set()
Expand Down
2 changes: 2 additions & 0 deletions pylint/test/functional/unused_global_variable1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# pylint: disable=missing-docstring
VAR = 'pylint'
2 changes: 2 additions & 0 deletions pylint/test/functional/unused_global_variable2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# pylint: disable=missing-docstring
VAR = 'pylint' # [unused-variable]
2 changes: 2 additions & 0 deletions pylint/test/functional/unused_global_variable2.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[variables]
allow-global-unused-variables=no
1 change: 1 addition & 0 deletions pylint/test/functional/unused_global_variable2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
unused-variable:2::Unused variable 'VAR':HIGH
6 changes: 6 additions & 0 deletions pylint/test/functional/unused_global_variable3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# pylint: disable=missing-docstring
VAR = 'pylint'


def func(argument):
return VAR + argument
3 changes: 3 additions & 0 deletions pylint/test/functional/unused_global_variable4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# pylint: disable=missing-docstring
VAR = 'pylint' # [unused-variable]
VAR = 'pylint2' # [unused-variable]
2 changes: 2 additions & 0 deletions pylint/test/functional/unused_global_variable4.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[variables]
allow-global-unused-variables=no
2 changes: 2 additions & 0 deletions pylint/test/functional/unused_global_variable4.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
unused-variable:2::Unused variable 'VAR':HIGH
unused-variable:3::Unused variable 'VAR':HIGH

0 comments on commit 740d250

Please sign in to comment.