Skip to content

Commit

Permalink
Check if global is set for import (pylint-dev#2090)
Browse files Browse the repository at this point in the history
The following code should trigger a global-variable-unassigned, as it is assigned
by the import statement:

def func():
    global sys
    import sys


Closes pylint-dev#1453
  • Loading branch information
mar-chi-pan authored and PCManticore committed May 15, 2018
1 parent 656c17b commit c011c53
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 4 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ Pylint's ChangeLog
What's New in Pylint 2.0?
=========================

* Don't warn that a global variable is unused if it is defined by an import

Close #1453

* Skip wildcard import check for `__init__.py`.

Close #2026
Expand Down
8 changes: 8 additions & 0 deletions doc/whatsnew/2.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,11 @@ Other Changes
They also no longer need to document raising a NotImplementedError.

* Skip wildcard import check for `__init__.py`.

* Don't warn that a global variable is unused if it is defined by an import

.. code-block:: python
def func():
global sys
import sys
13 changes: 9 additions & 4 deletions pylint/checkers/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -844,14 +844,18 @@ def visit_global(self, node):

module = frame.root()
default_message = True
locals_ = node.scope().locals
for name in node.names:
try:
assign_nodes = module.getattr(name)
except astroid.NotFoundError:
# unassigned global, skip
assign_nodes = []

if not assign_nodes:
not_defined_locally_by_import = not any(
isinstance(local, astroid.node_classes.Import)
for local in locals_.get(name, ()))
if not assign_nodes and not_defined_locally_by_import:
self.add_message('global-variable-not-assigned',
args=name, node=node)
default_message = False
Expand All @@ -866,9 +870,10 @@ def visit_global(self, node):
# module level assignment
break
else:
# global undefined at the module scope
self.add_message('global-variable-undefined', args=name, node=node)
default_message = False
if not_defined_locally_by_import:
# global undefined at the module scope
self.add_message('global-variable-undefined', args=name, node=node)
default_message = False

if default_message:
self.add_message('global-statement', node=node)
Expand Down
7 changes: 7 additions & 0 deletions pylint/test/functional/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,10 @@ def define_constant():
"""ok but somevar is not defined at the module scope"""
global SOMEVAR # [global-variable-undefined]
SOMEVAR = 2


# pylint: disable=invalid-name
def global_with_import():
"""should only warn for global-statement"""
global sys # [global-statement]
import sys
1 change: 1 addition & 0 deletions pylint/test/functional/globals.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ global-statement:11:fix_contant:Using the global statement
global-variable-not-assigned:18:other:Using global for 'HOP' but no assignment is done
undefined-variable:19:other:Undefined variable 'HOP'
global-variable-undefined:24:define_constant:Global variable 'SOMEVAR' undefined at the module level
global-statement:31:global_with_import:Using the global statement
11 changes: 11 additions & 0 deletions pylint/test/unittest_checker_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from pylint.checkers import variables
from pylint.testutils import CheckerTestCase, linter, set_config, Message
from pylint.interfaces import UNDEFINED

class TestVariablesChecker(CheckerTestCase):

Expand Down Expand Up @@ -89,6 +90,16 @@ def test():
self.checker.visit_module(node.root())
self.checker.visit_functiondef(node)

def test_unassigned_global(self):
node = astroid.extract_node('''
def func():
global sys #@
import sys, lala
''')
msg = Message('global-statement', node=node, confidence=UNDEFINED)
with self.assertAddsMessages(msg):
self.checker.visit_global(node)


class TestVariablesCheckerWithTearDown(CheckerTestCase):

Expand Down

0 comments on commit c011c53

Please sign in to comment.