Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(196)

Unified Diff: third_party/pylint/checkers/variables.py

Issue 719313003: Revert "pylint: upgrade to 1.3.1" (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/pylint/checkers/utils.py ('k') | third_party/pylint/config.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/pylint/checkers/variables.py
diff --git a/third_party/pylint/checkers/variables.py b/third_party/pylint/checkers/variables.py
index c75768bb66103caa6661a876d09bd22291787a1d..484a9526fede5fce652f82f186f0bb6040108225 100644
--- a/third_party/pylint/checkers/variables.py
+++ b/third_party/pylint/checkers/variables.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2003-2014 LOGILAB S.A. (Paris, FRANCE).
+# Copyright (c) 2003-2011 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This program is free software; you can redistribute it and/or modify it under
@@ -12,32 +12,27 @@
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
"""variables checkers for Python code
"""
-import os
+
import sys
from copy import copy
-import astroid
-from astroid import are_exclusive, builtin_lookup, AstroidBuildingException
-
-from logilab.common.modutils import file_from_modpath
+from logilab import astng
+from logilab.astng import are_exclusive, builtin_lookup, ASTNGBuildingException
-from pylint.interfaces import IAstroidChecker
-from pylint.utils import get_global_option
+from pylint.interfaces import IASTNGChecker
from pylint.checkers import BaseChecker
-from pylint.checkers.utils import (
- PYMETHODS, is_ancestor_name, is_builtin,
- is_defined_before, is_error, is_func_default, is_func_decorator,
- assign_parent, check_messages, is_inside_except, clobber_in_except,
- get_all_elements)
+from pylint.checkers.utils import (PYMETHODS, is_ancestor_name, is_builtin,
+ is_defined_before, is_error, is_func_default, is_func_decorator,
+ assign_parent, check_messages, is_inside_except, clobber_in_except)
def in_for_else_branch(parent, stmt):
- """Returns True if stmt in inside the else branch for a parent For stmt."""
- return (isinstance(parent, astroid.For) and
- any(else_stmt.parent_of(stmt) for else_stmt in parent.orelse))
+ """Returns True if stmt in inside the else branch for a parent For stmt."""
+ return (isinstance(parent, astng.For) and
+ any(else_stmt.parent_of(stmt) for else_stmt in parent.orelse))
def overridden_method(klass, name):
"""get overridden method if any"""
@@ -49,176 +44,58 @@ def overridden_method(klass, name):
meth_node = parent[name]
except KeyError:
# We have found an ancestor defining <name> but it's not in the local
- # dictionary. This may happen with astroid built from living objects.
+ # dictionary. This may happen with astng built from living objects.
return None
- if isinstance(meth_node, astroid.Function):
+ if isinstance(meth_node, astng.Function):
return meth_node
return None
-def _get_unpacking_extra_info(node, infered):
- """return extra information to add to the message for unpacking-non-sequence
- and unbalanced-tuple-unpacking errors
- """
- more = ''
- infered_module = infered.root().name
- if node.root().name == infered_module:
- if node.lineno == infered.lineno:
- more = ' %s' % infered.as_string()
- elif infered.lineno:
- more = ' defined at line %s' % infered.lineno
- elif infered.lineno:
- more = ' defined at line %s of %s' % (infered.lineno, infered_module)
- return more
-
-def _detect_global_scope(node, frame, defframe):
- """ Detect that the given frames shares a global
- scope.
-
- Two frames shares a global scope when neither
- of them are hidden under a function scope, as well
- as any of parent scope of them, until the root scope.
- In this case, depending from something defined later on
- will not work, because it is still undefined.
-
- Example:
- class A:
- # B has the same global scope as `C`, leading to a NameError.
- class B(C): ...
- class C: ...
-
- """
- def_scope = scope = None
- if frame and frame.parent:
- scope = frame.parent.scope()
- if defframe and defframe.parent:
- def_scope = defframe.parent.scope()
- if isinstance(frame, astroid.Function):
- # If the parent of the current node is a
- # function, then it can be under its scope
- # (defined in, which doesn't concern us) or
- # the `->` part of annotations. The same goes
- # for annotations of function arguments, they'll have
- # their parent the Arguments node.
- if not isinstance(node.parent,
- (astroid.Function, astroid.Arguments)):
- return False
- elif any(not isinstance(f, (astroid.Class, astroid.Module))
- for f in (frame, defframe)):
- # Not interested in other frames, since they are already
- # not in a global scope.
- return False
-
- break_scopes = []
- for s in (scope, def_scope):
- # Look for parent scopes. If there is anything different
- # than a module or a class scope, then they frames don't
- # share a global scope.
- parent_scope = s
- while parent_scope:
- if not isinstance(parent_scope, (astroid.Class, astroid.Module)):
- break_scopes.append(parent_scope)
- break
- if parent_scope.parent:
- parent_scope = parent_scope.parent.scope()
- else:
- break
- if break_scopes and len(set(break_scopes)) != 1:
- # Store different scopes than expected.
- # If the stored scopes are, in fact, the very same, then it means
- # that the two frames (frame and defframe) shares the same scope,
- # and we could apply our lineno analysis over them.
- # For instance, this works when they are inside a function, the node
- # that uses a definition and the definition itself.
- return False
- # At this point, we are certain that frame and defframe shares a scope
- # and the definition of the first depends on the second.
- return frame.lineno < defframe.lineno
-
MSGS = {
'E0601': ('Using variable %r before assignment',
- 'used-before-assignment',
'Used when a local variable is accessed before it\'s \
assignment.'),
'E0602': ('Undefined variable %r',
- 'undefined-variable',
'Used when an undefined variable is accessed.'),
- 'E0603': ('Undefined variable name %r in __all__',
- 'undefined-all-variable',
- 'Used when an undefined variable name is referenced in __all__.'),
- 'E0604': ('Invalid object %r in __all__, must contain only strings',
- 'invalid-all-object',
- 'Used when an invalid (non-string) object occurs in __all__.'),
'E0611': ('No name %r in module %r',
- 'no-name-in-module',
'Used when a name cannot be found in a module.'),
'W0601': ('Global variable %r undefined at the module level',
- 'global-variable-undefined',
'Used when a variable is defined through the "global" statement \
but the variable is not defined in the module scope.'),
'W0602': ('Using global for %r but no assignment is done',
- 'global-variable-not-assigned',
'Used when a variable is defined through the "global" statement \
but no assignment to this variable is done.'),
'W0603': ('Using the global statement', # W0121
- 'global-statement',
'Used when you use the "global" statement to update a global \
variable. PyLint just try to discourage this \
usage. That doesn\'t mean you can not use it !'),
'W0604': ('Using the global statement at the module level', # W0103
- 'global-at-module-level',
'Used when you use the "global" statement at the module level \
since it has no effect'),
'W0611': ('Unused import %s',
- 'unused-import',
'Used when an imported module or variable is not used.'),
'W0612': ('Unused variable %r',
- 'unused-variable',
'Used when a variable is defined but not used.'),
'W0613': ('Unused argument %r',
- 'unused-argument',
'Used when a function or method argument is not used.'),
'W0614': ('Unused import %s from wildcard import',
- 'unused-wildcard-import',
'Used when an imported module or variable is not used from a \
\'from X import *\' style import.'),
'W0621': ('Redefining name %r from outer scope (line %s)',
- 'redefined-outer-name',
'Used when a variable\'s name hide a name defined in the outer \
scope.'),
'W0622': ('Redefining built-in %r',
- 'redefined-builtin',
'Used when a variable or function override a built-in.'),
'W0623': ('Redefining name %r from %s in exception handler',
- 'redefine-in-handler',
'Used when an exception handler assigns the exception \
to an existing name'),
'W0631': ('Using possibly undefined loop variable %r',
- 'undefined-loop-variable',
'Used when an loop variable (i.e. defined by a for loop or \
a list comprehension or a generator expression) is used outside \
the loop.'),
-
- 'W0632': ('Possible unbalanced tuple unpacking with '
- 'sequence%s: '
- 'left side has %d label(s), right side has %d value(s)',
- 'unbalanced-tuple-unpacking',
- 'Used when there is an unbalanced tuple unpacking in assignment'),
-
- 'W0633': ('Attempting to unpack a non-sequence%s',
- 'unpacking-non-sequence',
- 'Used when something which is not '
- 'a sequence is used in an unpack assignment'),
-
- 'W0640': ('Cell variable %s defined in loop',
- 'cell-var-from-loop',
- 'A variable used in a closure is defined in a loop. '
- 'This will result in all closures using the same value for '
- 'the closed-over variable.'),
-
}
class VariablesChecker(BaseChecker):
@@ -227,107 +104,67 @@ class VariablesChecker(BaseChecker):
* undefined variables
* redefinition of variable from builtins or from an outer scope
* use of variable before assignment
- * __all__ consistency
"""
- __implements__ = IAstroidChecker
+ __implements__ = IASTNGChecker
name = 'variables'
msgs = MSGS
priority = -1
- options = (("init-import",
+ options = (
+ ("init-import",
{'default': 0, 'type' : 'yn', 'metavar' : '<y_or_n>',
'help' : 'Tells whether we should check for unused import in \
__init__ files.'}),
("dummy-variables-rgx",
- {'default': ('_$|dummy'),
+ {'default': ('_|dummy'),
'type' :'regexp', 'metavar' : '<regexp>',
- 'help' : 'A regular expression matching the name of dummy \
-variables (i.e. expectedly not used).'}),
+ 'help' : 'A regular expression matching the beginning of \
+ the name of dummy variables (i.e. not used).'}),
("additional-builtins",
{'default': (), 'type' : 'csv',
'metavar' : '<comma separated list>',
'help' : 'List of additional names supposed to be defined in \
builtins. Remember that you should avoid to define new builtins when possible.'
- }),
- )
+ }),
+ )
def __init__(self, linter=None):
BaseChecker.__init__(self, linter)
self._to_consume = None
self._checking_mod_attr = None
+ self._vars = None
def visit_module(self, node):
"""visit module : update consumption analysis variable
checks globals doesn't overrides builtins
"""
self._to_consume = [(copy(node.locals), {}, 'module')]
- for name, stmts in node.locals.iteritems():
+ self._vars = []
+ for name, stmts in node.locals.items():
if is_builtin(name) and not is_inside_except(stmts[0]):
# do not print Redefining builtin for additional builtins
- self.add_message('redefined-builtin', args=name, node=stmts[0])
+ self.add_message('W0622', args=name, node=stmts[0])
- @check_messages('unused-import', 'unused-wildcard-import', 'redefined-builtin', 'undefined-all-variable', 'invalid-all-object')
+ @check_messages('W0611', 'W0614')
def leave_module(self, node):
"""leave module: check globals
"""
assert len(self._to_consume) == 1
not_consumed = self._to_consume.pop()[0]
- # attempt to check for __all__ if defined
- if '__all__' in node.locals:
- assigned = node.igetattr('__all__').next()
- if assigned is not astroid.YES:
- for elt in getattr(assigned, 'elts', ()):
- try:
- elt_name = elt.infer().next()
- except astroid.InferenceError:
- continue
-
- if not isinstance(elt_name, astroid.Const) \
- or not isinstance(elt_name.value, basestring):
- self.add_message('invalid-all-object', args=elt.as_string(), node=elt)
- continue
- elt_name = elt_name.value
- # If elt is in not_consumed, remove it from not_consumed
- if elt_name in not_consumed:
- del not_consumed[elt_name]
- continue
- if elt_name not in node.locals:
- if not node.package:
- self.add_message('undefined-all-variable',
- args=elt_name,
- node=elt)
- else:
- basename = os.path.splitext(node.file)[0]
- if os.path.basename(basename) == '__init__':
- name = node.name + "." + elt_name
- try:
- file_from_modpath(name.split("."))
- except ImportError:
- self.add_message('undefined-all-variable',
- args=elt_name,
- node=elt)
- except SyntaxError:
- # don't yield an syntax-error warning,
- # because it will be later yielded
- # when the file will be checked
- pass
# don't check unused imports in __init__ files
if not self.config.init_import and node.package:
return
- for name, stmts in not_consumed.iteritems():
- if any(isinstance(stmt, astroid.AssName)
- and isinstance(stmt.ass_type(), astroid.AugAssign)
- for stmt in stmts):
- continue
+ for name, stmts in not_consumed.items():
stmt = stmts[0]
- if isinstance(stmt, astroid.Import):
- self.add_message('unused-import', args=name, node=stmt)
- elif isinstance(stmt, astroid.From) and stmt.modname != '__future__':
+ if isinstance(stmt, astng.Import):
+ self.add_message('W0611', args=name, node=stmt)
+ elif isinstance(stmt, astng.From) and stmt.modname != '__future__':
if stmt.names[0][0] == '*':
- self.add_message('unused-wildcard-import', args=name, node=stmt)
+ self.add_message('W0614', args=name, node=stmt)
else:
- self.add_message('unused-import', args=name, node=stmt)
+ self.add_message('W0611', args=name, node=stmt)
del self._to_consume
+ del self._vars
def visit_class(self, node):
"""visit class: update consumption analysis variable
@@ -388,27 +225,25 @@ builtins. Remember that you should avoid to define new builtins when possible.'
"""visit function: update consumption analysis variable and check locals
"""
self._to_consume.append((copy(node.locals), {}, 'function'))
- if not (self.linter.is_message_enabled('redefined-outer-name') or
- self.linter.is_message_enabled('redefined-builtin')):
+ self._vars.append({})
+ if not set(('W0621', 'W0622')) & self.active_msgs:
return
globs = node.root().globals
for name, stmt in node.items():
if is_inside_except(stmt):
continue
- if name in globs and not isinstance(stmt, astroid.Global):
- line = globs[name][0].fromlineno
- dummy_rgx = self.config.dummy_variables_rgx
- if not dummy_rgx.match(name):
- self.add_message('redefined-outer-name', args=(name, line), node=stmt)
+ if name in globs and not isinstance(stmt, astng.Global):
+ line = globs[name][0].lineno
+ self.add_message('W0621', args=(name, line), node=stmt)
elif is_builtin(name):
# do not print Redefining builtin for additional builtins
- self.add_message('redefined-builtin', args=name, node=stmt)
+ self.add_message('W0622', args=name, node=stmt)
def leave_function(self, node):
"""leave function: check function's locals are consumed"""
not_consumed = self._to_consume.pop()[0]
- if not (self.linter.is_message_enabled('unused-variable') or
- self.linter.is_message_enabled('unused-argument')):
+ self._vars.pop(0)
+ if not set(('W0612', 'W0613')) & self.active_msgs:
return
# don't check arguments of function which are only raising an exception
if is_error(node):
@@ -421,13 +256,6 @@ 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()
- 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
if authorized_rgx.match(name):
@@ -435,25 +263,8 @@ builtins. Remember that you should avoid to define new builtins when possible.'
# ignore names imported by the global statement
# FIXME: should only ignore them if it's assigned latter
stmt = stmts[0]
- if isinstance(stmt, astroid.Global):
+ if isinstance(stmt, astng.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:
@@ -471,27 +282,23 @@ builtins. Remember that you should avoid to define new builtins when possible.'
# don't check callback arguments XXX should be configurable
if node.name.startswith('cb_') or node.name.endswith('_cb'):
continue
- self.add_message('unused-argument', args=name, node=stmt)
+ self.add_message('W0613', 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)
+ self.add_message('W0612', args=name, node=stmt)
- @check_messages('global-variable-undefined', 'global-variable-not-assigned', 'global-statement',
- 'global-at-module-level', 'redefined-builtin')
+ @check_messages('W0601', 'W0602', 'W0603', 'W0604', 'W0622')
def visit_global(self, node):
"""check names imported exists in the global scope"""
frame = node.frame()
- if isinstance(frame, astroid.Module):
- self.add_message('global-at-module-level', node=node)
+ if isinstance(frame, astng.Module):
+ self.add_message('W0604', node=node)
return
module = frame.root()
default_message = True
for name in node.names:
try:
assign_nodes = module.getattr(name)
- except astroid.NotFoundError:
+ except astng.NotFoundError:
# unassigned global, skip
assign_nodes = []
for anode in assign_nodes:
@@ -504,69 +311,23 @@ builtins. Remember that you should avoid to define new builtins when possible.'
break
else:
# global but no assignment
- # 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)
+ self.add_message('W0602', args=name, node=node)
default_message = False
if not assign_nodes:
continue
for anode in assign_nodes:
if anode.parent is None:
- self.add_message('redefined-builtin', args=name, node=node)
+ self.add_message('W0622', args=name, node=node)
break
if anode.frame() is module:
# module level assignment
break
else:
# global undefined at the module scope
- self.add_message('global-variable-undefined', args=name, node=node)
+ self.add_message('W0601', args=name, node=node)
default_message = False
if default_message:
- self.add_message('global-statement', node=node)
-
- def _check_late_binding_closure(self, node, assignment_node, scope_type):
- def _is_direct_lambda_call():
- return (isinstance(node_scope.parent, astroid.CallFunc)
- and node_scope.parent.func is node_scope)
-
- node_scope = node.scope()
- if not isinstance(node_scope, (astroid.Lambda, astroid.Function)):
- return
- if isinstance(node.parent, astroid.Arguments):
- return
-
- if isinstance(assignment_node, astroid.Comprehension):
- if assignment_node.parent.parent_of(node.scope()):
- self.add_message('cell-var-from-loop', node=node, args=node.name)
- else:
- assign_scope = assignment_node.scope()
- maybe_for = assignment_node
- while not isinstance(maybe_for, astroid.For):
- if maybe_for is assign_scope:
- break
- maybe_for = maybe_for.parent
- else:
- if (maybe_for.parent_of(node_scope)
- and not _is_direct_lambda_call()
- and not isinstance(node_scope.statement(), astroid.Return)):
- self.add_message('cell-var-from-loop', node=node, args=node.name)
+ self.add_message('W0603', node=node)
def _loopvar_name(self, node, name):
# filter variables according to node's scope
@@ -576,7 +337,7 @@ builtins. Remember that you should avoid to define new builtins when possible.'
#astmts = [stmt for stmt in node.lookup(name)[1]
# if hasattr(stmt, 'ass_type')] and
# not stmt.statement().parent_of(node)]
- if not self.linter.is_message_enabled('undefined-loop-variable'):
+ if 'W0631' not in self.active_msgs:
return
astmts = [stmt for stmt in node.lookup(name)[1]
if hasattr(stmt, 'ass_type')]
@@ -594,38 +355,35 @@ builtins. Remember that you should avoid to define new builtins when possible.'
_astmts = astmts[:1]
for i, stmt in enumerate(astmts[1:]):
if (astmts[i].statement().parent_of(stmt)
- and not in_for_else_branch(astmts[i].statement(), stmt)):
+ and not in_for_else_branch(astmts[i].statement(), stmt)):
continue
_astmts.append(stmt)
astmts = _astmts
if len(astmts) == 1:
ass = astmts[0].ass_type()
- if isinstance(ass, (astroid.For, astroid.Comprehension, astroid.GenExpr)) \
+ if isinstance(ass, (astng.For, astng.Comprehension, astng.GenExpr)) \
and not ass.statement() is node.statement():
- self.add_message('undefined-loop-variable', args=name, node=node)
+ self.add_message('W0631', args=name, node=node)
- @check_messages('redefine-in-handler')
def visit_excepthandler(self, node):
- for name in get_all_elements(node.name):
- clobbering, args = clobber_in_except(name)
- if clobbering:
- self.add_message('redefine-in-handler', args=args, node=name)
+ clobbering, args = clobber_in_except(node.name)
+ if clobbering:
+ self.add_message('W0623', args=args, node=node)
def visit_assname(self, node):
- if isinstance(node.ass_type(), astroid.AugAssign):
+ if isinstance(node.ass_type(), astng.AugAssign):
self.visit_name(node)
def visit_delname(self, node):
self.visit_name(node)
- @check_messages(*(MSGS.keys()))
def visit_name(self, node):
"""check that a name is defined if the current scope and doesn't
redefine a built-in
"""
stmt = node.statement()
if stmt.fromlineno is None:
- # name node from a astroid built from live code, skip
+ # name node from a astng built from live code, skip
assert not stmt.root().file.endswith('.py')
return
name = node.name
@@ -634,7 +392,7 @@ builtins. Remember that you should avoid to define new builtins when possible.'
# a decorator, then start from the parent frame of the function instead
# of the function frame - and thus open an inner class scope
if (is_func_default(node) or is_func_decorator(node)
- or is_ancestor_name(frame, node)):
+ or is_ancestor_name(frame, node)):
start_index = len(self._to_consume) - 2
else:
start_index = len(self._to_consume) - 1
@@ -648,21 +406,12 @@ builtins. Remember that you should avoid to define new builtins when possible.'
# names. The only exception is when the starting scope is a
# comprehension and its direct outer scope is a class
if scope_type == 'class' and i != start_index and not (
- base_scope_type == 'comprehension' and i == start_index-1):
- # Detect if we are in a local class scope, as an assignment.
- # For example, the following is fair game.
- # class A:
- # b = 1
- # c = lambda b=b: b * b
- class_assignment = (isinstance(frame, astroid.Class) and
- name in frame.locals)
- if not class_assignment:
- continue
+ base_scope_type == 'comprehension' and i == start_index-1):
+ # XXX find a way to handle class scope in a smoother way
+ continue
# the name has already been consumed, only check it's not a loop
# variable used outside the loop
if name in consumed:
- defnode = assign_parent(consumed[name][0])
- self._check_late_binding_closure(node, defnode, scope_type)
self._loopvar_name(node, name)
break
# mark the name as consumed if it's defined in this scope
@@ -674,12 +423,11 @@ builtins. Remember that you should avoid to define new builtins when possible.'
# checks for use before assignment
defnode = assign_parent(to_consume[name][0])
if defnode is not None:
- self._check_late_binding_closure(node, defnode, scope_type)
defstmt = defnode.statement()
defframe = defstmt.frame()
maybee0601 = True
if not frame is defframe:
- maybee0601 = _detect_global_scope(node, frame, defframe)
+ maybee0601 = False
elif defframe.parent is None:
# we are at the module level, check the name is not
# defined in builtins
@@ -690,82 +438,49 @@ builtins. Remember that you should avoid to define new builtins when possible.'
# defined in global or builtin scope
if defframe.root().lookup(name)[1]:
maybee0601 = False
- else:
- # check if we have a nonlocal
- if name in defframe.locals:
- maybee0601 = not any(isinstance(child, astroid.Nonlocal)
- and name in child.names
- for child in defframe.get_children())
- if (self._to_consume[-1][-1] == 'lambda' and
- isinstance(frame, astroid.Class)
- and name in frame.locals):
- maybee0601 = True
- else:
- maybee0601 = maybee0601 and stmt.fromlineno <= defstmt.fromlineno
-
if (maybee0601
- and not is_defined_before(node)
- and not are_exclusive(stmt, defstmt, ('NameError',
- 'Exception',
- 'BaseException'))):
- if defstmt is stmt and isinstance(node, (astroid.DelName,
- astroid.AssName)):
- self.add_message('undefined-variable', args=name, node=node)
+ and stmt.fromlineno <= defstmt.fromlineno
+ and not is_defined_before(node)
+ and not are_exclusive(stmt, defstmt, ('NameError', 'Exception', 'BaseException'))):
+ if defstmt is stmt and isinstance(node, (astng.DelName,
+ astng.AssName)):
+ self.add_message('E0602', args=name, node=node)
elif self._to_consume[-1][-1] != 'lambda':
- # E0601 may *not* occurs in lambda scope.
- self.add_message('used-before-assignment', args=name, node=node)
- elif self._to_consume[-1][-1] == 'lambda':
- # E0601 can occur in class-level scope in lambdas, as in
- # the following example:
- # class A:
- # x = lambda attr: f + attr
- # f = 42
- if isinstance(frame, astroid.Class) and name in frame.locals:
- if isinstance(node.parent, astroid.Arguments):
- # Doing the following is fine:
- # class A:
- # x = 42
- # y = lambda attr=x: attr
- if stmt.fromlineno <= defstmt.fromlineno:
- self.add_message('used-before-assignment',
- args=name, node=node)
- else:
- self.add_message('undefined-variable',
- args=name, node=node)
-
- if isinstance(node, astroid.AssName): # Aug AssName
- del consumed[name]
- else:
+ # E0601 may *not* occurs in lambda scope
+ self.add_message('E0601', args=name, node=node)
+ if not isinstance(node, astng.AssName): # Aug AssName
del to_consume[name]
+ else:
+ del consumed[name]
# check it's not a loop variable used outside the loop
self._loopvar_name(node, name)
break
else:
# we have not found the name, if it isn't a builtin, that's an
# undefined name !
- if not (name in astroid.Module.scope_attrs or is_builtin(name)
+ if not (name in astng.Module.scope_attrs or is_builtin(name)
or name in self.config.additional_builtins):
- self.add_message('undefined-variable', args=name, node=node)
+ self.add_message('E0602', args=name, node=node)
- @check_messages('no-name-in-module')
+ @check_messages('E0611')
def visit_import(self, node):
"""check modules attribute accesses"""
for name, _ in node.names:
parts = name.split('.')
try:
module = node.infer_name_module(parts[0]).next()
- except astroid.ResolveError:
+ except astng.ResolveError:
continue
self._check_module_attrs(node, module, parts[1:])
- @check_messages('no-name-in-module')
+ @check_messages('E0611')
def visit_from(self, node):
"""check modules attribute accesses"""
name_parts = node.modname.split('.')
level = getattr(node, 'level', None)
try:
module = node.root().import_module(name_parts[0], level=level)
- except AstroidBuildingException:
+ except ASTNGBuildingException:
return
except Exception, exc:
print 'Unhandled exception in VariablesChecker:', exc
@@ -778,63 +493,12 @@ builtins. Remember that you should avoid to define new builtins when possible.'
continue
self._check_module_attrs(node, module, name.split('.'))
- @check_messages('unbalanced-tuple-unpacking', 'unpacking-non-sequence')
- def visit_assign(self, node):
- """Check unbalanced tuple unpacking for assignments
- and unpacking non-sequences.
- """
- if not isinstance(node.targets[0], (astroid.Tuple, astroid.List)):
- return
-
- targets = node.targets[0].itered()
- try:
- for infered in node.value.infer():
- self._check_unpacking(infered, node, targets)
- except astroid.InferenceError:
- return
-
- def _check_unpacking(self, infered, node, targets):
- """ Check for unbalanced tuple unpacking
- and unpacking non sequences.
- """
- if infered is astroid.YES:
- return
- if isinstance(infered, (astroid.Tuple, astroid.List)):
- # attempt to check unpacking is properly balanced
- values = infered.itered()
- if len(targets) != len(values):
- # Check if we have starred nodes.
- if any(isinstance(target, astroid.Starred)
- for target in targets):
- return
- self.add_message('unbalanced-tuple-unpacking', node=node,
- args=(_get_unpacking_extra_info(node, infered),
- len(targets),
- len(values)))
- # attempt to check unpacking may be possible (ie RHS is iterable)
- elif isinstance(infered, astroid.Instance):
- for meth in ('__iter__', '__getitem__'):
- try:
- infered.getattr(meth)
- break
- except astroid.NotFoundError:
- continue
- else:
- self.add_message('unpacking-non-sequence', node=node,
- args=(_get_unpacking_extra_info(node, infered),))
- else:
- self.add_message('unpacking-non-sequence', node=node,
- args=(_get_unpacking_extra_info(node, infered),))
-
-
def _check_module_attrs(self, node, module, module_names):
"""check that module_names (list of string) are accessible through the
given module
if the latest access name corresponds to a module, return it
"""
- assert isinstance(module, astroid.Module), module
- ignored_modules = get_global_option(self, 'ignored-modules',
- default=[])
+ assert isinstance(module, astng.Module), module
while module_names:
name = module_names.pop(0)
if name == '__dict__':
@@ -842,24 +506,21 @@ builtins. Remember that you should avoid to define new builtins when possible.'
break
try:
module = module.getattr(name)[0].infer().next()
- if module is astroid.YES:
- return None
- except astroid.NotFoundError:
- if module.name in ignored_modules:
+ if module is astng.YES:
return None
- self.add_message('no-name-in-module',
- args=(name, module.name), node=node)
+ except astng.NotFoundError:
+ self.add_message('E0611', args=(name, module.name), node=node)
return None
- except astroid.InferenceError:
+ except astng.InferenceError:
return None
if module_names:
# FIXME: other message if name is not the latest part of
# module_names ?
modname = module and module.name or '__dict__'
- self.add_message('no-name-in-module', node=node,
+ self.add_message('E0611', node=node,
args=('.'.join(module_names), modname))
return None
- if isinstance(module, astroid.Module):
+ if isinstance(module, astng.Module):
return module
return None
@@ -879,57 +540,6 @@ class VariablesChecker3k(VariablesChecker):
# do not check for not used locals here
self._to_consume.pop()
- def leave_module(self, node):
- """ Update consumption analysis variable
- for metaclasses.
- """
- module_locals = self._to_consume[0][0]
- module_imports = self._to_consume[0][1]
- consumed = {}
-
- for klass in node.nodes_of_class(astroid.Class):
- found = metaclass = name = None
- if not klass._metaclass:
- # Skip if this class doesn't use
- # explictly a metaclass, but inherits it from ancestors
- continue
-
- metaclass = klass.metaclass()
-
- # Look the name in the already found locals.
- # If it's not found there, look in the module locals
- # and in the imported modules.
- if isinstance(klass._metaclass, astroid.Name):
- name = klass._metaclass.name
- elif metaclass:
- # if it uses a `metaclass=module.Class`
- name = metaclass.root().name
-
- if name:
- found = consumed.setdefault(
- name, module_locals.get(name, module_imports.get(name)))
-
- if found is None and not metaclass:
- name = None
- if isinstance(klass._metaclass, astroid.Name):
- name = klass._metaclass.name
- elif isinstance(klass._metaclass, astroid.Getattr):
- name = klass._metaclass.as_string()
-
- if name is not None:
- if not (name in astroid.Module.scope_attrs or
- is_builtin(name) or
- name in self.config.additional_builtins or
- name in node.locals):
- self.add_message('undefined-variable',
- node=klass,
- args=(name, ))
- # Pop the consumed items, in order to
- # avoid having unused-import false positives
- for name in consumed:
- module_locals.pop(name, None)
- super(VariablesChecker3k, self).leave_module(node)
-
if sys.version_info >= (3, 0):
VariablesChecker = VariablesChecker3k
« no previous file with comments | « third_party/pylint/checkers/utils.py ('k') | third_party/pylint/config.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698