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

Side by Side 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2003-2014 LOGILAB S.A. (Paris, FRANCE). 1 # Copyright (c) 2003-2011 LOGILAB S.A. (Paris, FRANCE).
2 # http://www.logilab.fr/ -- mailto:contact@logilab.fr 2 # http://www.logilab.fr/ -- mailto:contact@logilab.fr
3 # 3 #
4 # This program is free software; you can redistribute it and/or modify it under 4 # This program is free software; you can redistribute it and/or modify it under
5 # the terms of the GNU General Public License as published by the Free Software 5 # the terms of the GNU General Public License as published by the Free Software
6 # Foundation; either version 2 of the License, or (at your option) any later 6 # Foundation; either version 2 of the License, or (at your option) any later
7 # version. 7 # version.
8 # 8 #
9 # This program is distributed in the hope that it will be useful, but WITHOUT 9 # This program is distributed in the hope that it will be useful, but WITHOUT
10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 # 12 #
13 # You should have received a copy of the GNU General Public License along with 13 # You should have received a copy of the GNU General Public License along with
14 # this program; if not, write to the Free Software Foundation, Inc., 14 # this program; if not, write to the Free Software Foundation, Inc.,
15 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 15 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 """variables checkers for Python code 16 """variables checkers for Python code
17 """ 17 """
18 import os 18
19 import sys 19 import sys
20 from copy import copy 20 from copy import copy
21 21
22 import astroid 22 from logilab import astng
23 from astroid import are_exclusive, builtin_lookup, AstroidBuildingException 23 from logilab.astng import are_exclusive, builtin_lookup, ASTNGBuildingException
24 24
25 from logilab.common.modutils import file_from_modpath 25 from pylint.interfaces import IASTNGChecker
26
27 from pylint.interfaces import IAstroidChecker
28 from pylint.utils import get_global_option
29 from pylint.checkers import BaseChecker 26 from pylint.checkers import BaseChecker
30 from pylint.checkers.utils import ( 27 from pylint.checkers.utils import (PYMETHODS, is_ancestor_name, is_builtin,
31 PYMETHODS, is_ancestor_name, is_builtin, 28 is_defined_before, is_error, is_func_default, is_func_decorator,
32 is_defined_before, is_error, is_func_default, is_func_decorator, 29 assign_parent, check_messages, is_inside_except, clobber_in_except)
33 assign_parent, check_messages, is_inside_except, clobber_in_except,
34 get_all_elements)
35 30
36 31
37 def in_for_else_branch(parent, stmt): 32 def in_for_else_branch(parent, stmt):
38 """Returns True if stmt in inside the else branch for a parent For stmt.""" 33 """Returns True if stmt in inside the else branch for a parent For stmt."""
39 return (isinstance(parent, astroid.For) and 34 return (isinstance(parent, astng.For) and
40 any(else_stmt.parent_of(stmt) for else_stmt in parent.orelse)) 35 any(else_stmt.parent_of(stmt) for else_stmt in parent.orelse))
41 36
42 def overridden_method(klass, name): 37 def overridden_method(klass, name):
43 """get overridden method if any""" 38 """get overridden method if any"""
44 try: 39 try:
45 parent = klass.local_attr_ancestors(name).next() 40 parent = klass.local_attr_ancestors(name).next()
46 except (StopIteration, KeyError): 41 except (StopIteration, KeyError):
47 return None 42 return None
48 try: 43 try:
49 meth_node = parent[name] 44 meth_node = parent[name]
50 except KeyError: 45 except KeyError:
51 # We have found an ancestor defining <name> but it's not in the local 46 # We have found an ancestor defining <name> but it's not in the local
52 # dictionary. This may happen with astroid built from living objects. 47 # dictionary. This may happen with astng built from living objects.
53 return None 48 return None
54 if isinstance(meth_node, astroid.Function): 49 if isinstance(meth_node, astng.Function):
55 return meth_node 50 return meth_node
56 return None 51 return None
57 52
58 def _get_unpacking_extra_info(node, infered):
59 """return extra information to add to the message for unpacking-non-sequence
60 and unbalanced-tuple-unpacking errors
61 """
62 more = ''
63 infered_module = infered.root().name
64 if node.root().name == infered_module:
65 if node.lineno == infered.lineno:
66 more = ' %s' % infered.as_string()
67 elif infered.lineno:
68 more = ' defined at line %s' % infered.lineno
69 elif infered.lineno:
70 more = ' defined at line %s of %s' % (infered.lineno, infered_module)
71 return more
72
73 def _detect_global_scope(node, frame, defframe):
74 """ Detect that the given frames shares a global
75 scope.
76
77 Two frames shares a global scope when neither
78 of them are hidden under a function scope, as well
79 as any of parent scope of them, until the root scope.
80 In this case, depending from something defined later on
81 will not work, because it is still undefined.
82
83 Example:
84 class A:
85 # B has the same global scope as `C`, leading to a NameError.
86 class B(C): ...
87 class C: ...
88
89 """
90 def_scope = scope = None
91 if frame and frame.parent:
92 scope = frame.parent.scope()
93 if defframe and defframe.parent:
94 def_scope = defframe.parent.scope()
95 if isinstance(frame, astroid.Function):
96 # If the parent of the current node is a
97 # function, then it can be under its scope
98 # (defined in, which doesn't concern us) or
99 # the `->` part of annotations. The same goes
100 # for annotations of function arguments, they'll have
101 # their parent the Arguments node.
102 if not isinstance(node.parent,
103 (astroid.Function, astroid.Arguments)):
104 return False
105 elif any(not isinstance(f, (astroid.Class, astroid.Module))
106 for f in (frame, defframe)):
107 # Not interested in other frames, since they are already
108 # not in a global scope.
109 return False
110
111 break_scopes = []
112 for s in (scope, def_scope):
113 # Look for parent scopes. If there is anything different
114 # than a module or a class scope, then they frames don't
115 # share a global scope.
116 parent_scope = s
117 while parent_scope:
118 if not isinstance(parent_scope, (astroid.Class, astroid.Module)):
119 break_scopes.append(parent_scope)
120 break
121 if parent_scope.parent:
122 parent_scope = parent_scope.parent.scope()
123 else:
124 break
125 if break_scopes and len(set(break_scopes)) != 1:
126 # Store different scopes than expected.
127 # If the stored scopes are, in fact, the very same, then it means
128 # that the two frames (frame and defframe) shares the same scope,
129 # and we could apply our lineno analysis over them.
130 # For instance, this works when they are inside a function, the node
131 # that uses a definition and the definition itself.
132 return False
133 # At this point, we are certain that frame and defframe shares a scope
134 # and the definition of the first depends on the second.
135 return frame.lineno < defframe.lineno
136
137 53
138 MSGS = { 54 MSGS = {
139 'E0601': ('Using variable %r before assignment', 55 'E0601': ('Using variable %r before assignment',
140 'used-before-assignment',
141 'Used when a local variable is accessed before it\'s \ 56 'Used when a local variable is accessed before it\'s \
142 assignment.'), 57 assignment.'),
143 'E0602': ('Undefined variable %r', 58 'E0602': ('Undefined variable %r',
144 'undefined-variable',
145 'Used when an undefined variable is accessed.'), 59 'Used when an undefined variable is accessed.'),
146 'E0603': ('Undefined variable name %r in __all__',
147 'undefined-all-variable',
148 'Used when an undefined variable name is referenced in __all__.'),
149 'E0604': ('Invalid object %r in __all__, must contain only strings',
150 'invalid-all-object',
151 'Used when an invalid (non-string) object occurs in __all__.'),
152 'E0611': ('No name %r in module %r', 60 'E0611': ('No name %r in module %r',
153 'no-name-in-module',
154 'Used when a name cannot be found in a module.'), 61 'Used when a name cannot be found in a module.'),
155 62
156 'W0601': ('Global variable %r undefined at the module level', 63 'W0601': ('Global variable %r undefined at the module level',
157 'global-variable-undefined',
158 'Used when a variable is defined through the "global" statement \ 64 'Used when a variable is defined through the "global" statement \
159 but the variable is not defined in the module scope.'), 65 but the variable is not defined in the module scope.'),
160 'W0602': ('Using global for %r but no assignment is done', 66 'W0602': ('Using global for %r but no assignment is done',
161 'global-variable-not-assigned',
162 'Used when a variable is defined through the "global" statement \ 67 'Used when a variable is defined through the "global" statement \
163 but no assignment to this variable is done.'), 68 but no assignment to this variable is done.'),
164 'W0603': ('Using the global statement', # W0121 69 'W0603': ('Using the global statement', # W0121
165 'global-statement',
166 'Used when you use the "global" statement to update a global \ 70 'Used when you use the "global" statement to update a global \
167 variable. PyLint just try to discourage this \ 71 variable. PyLint just try to discourage this \
168 usage. That doesn\'t mean you can not use it !'), 72 usage. That doesn\'t mean you can not use it !'),
169 'W0604': ('Using the global statement at the module level', # W0103 73 'W0604': ('Using the global statement at the module level', # W0103
170 'global-at-module-level',
171 'Used when you use the "global" statement at the module level \ 74 'Used when you use the "global" statement at the module level \
172 since it has no effect'), 75 since it has no effect'),
173 'W0611': ('Unused import %s', 76 'W0611': ('Unused import %s',
174 'unused-import',
175 'Used when an imported module or variable is not used.'), 77 'Used when an imported module or variable is not used.'),
176 'W0612': ('Unused variable %r', 78 'W0612': ('Unused variable %r',
177 'unused-variable',
178 'Used when a variable is defined but not used.'), 79 'Used when a variable is defined but not used.'),
179 'W0613': ('Unused argument %r', 80 'W0613': ('Unused argument %r',
180 'unused-argument',
181 'Used when a function or method argument is not used.'), 81 'Used when a function or method argument is not used.'),
182 'W0614': ('Unused import %s from wildcard import', 82 'W0614': ('Unused import %s from wildcard import',
183 'unused-wildcard-import',
184 'Used when an imported module or variable is not used from a \ 83 'Used when an imported module or variable is not used from a \
185 \'from X import *\' style import.'), 84 \'from X import *\' style import.'),
186 85
187 'W0621': ('Redefining name %r from outer scope (line %s)', 86 'W0621': ('Redefining name %r from outer scope (line %s)',
188 'redefined-outer-name',
189 'Used when a variable\'s name hide a name defined in the outer \ 87 'Used when a variable\'s name hide a name defined in the outer \
190 scope.'), 88 scope.'),
191 'W0622': ('Redefining built-in %r', 89 'W0622': ('Redefining built-in %r',
192 'redefined-builtin',
193 'Used when a variable or function override a built-in.'), 90 'Used when a variable or function override a built-in.'),
194 'W0623': ('Redefining name %r from %s in exception handler', 91 'W0623': ('Redefining name %r from %s in exception handler',
195 'redefine-in-handler',
196 'Used when an exception handler assigns the exception \ 92 'Used when an exception handler assigns the exception \
197 to an existing name'), 93 to an existing name'),
198 94
199 'W0631': ('Using possibly undefined loop variable %r', 95 'W0631': ('Using possibly undefined loop variable %r',
200 'undefined-loop-variable',
201 'Used when an loop variable (i.e. defined by a for loop or \ 96 'Used when an loop variable (i.e. defined by a for loop or \
202 a list comprehension or a generator expression) is used outside \ 97 a list comprehension or a generator expression) is used outside \
203 the loop.'), 98 the loop.'),
204
205 'W0632': ('Possible unbalanced tuple unpacking with '
206 'sequence%s: '
207 'left side has %d label(s), right side has %d value(s)',
208 'unbalanced-tuple-unpacking',
209 'Used when there is an unbalanced tuple unpacking in assignment'),
210
211 'W0633': ('Attempting to unpack a non-sequence%s',
212 'unpacking-non-sequence',
213 'Used when something which is not '
214 'a sequence is used in an unpack assignment'),
215
216 'W0640': ('Cell variable %s defined in loop',
217 'cell-var-from-loop',
218 'A variable used in a closure is defined in a loop. '
219 'This will result in all closures using the same value for '
220 'the closed-over variable.'),
221
222 } 99 }
223 100
224 class VariablesChecker(BaseChecker): 101 class VariablesChecker(BaseChecker):
225 """checks for 102 """checks for
226 * unused variables / imports 103 * unused variables / imports
227 * undefined variables 104 * undefined variables
228 * redefinition of variable from builtins or from an outer scope 105 * redefinition of variable from builtins or from an outer scope
229 * use of variable before assignment 106 * use of variable before assignment
230 * __all__ consistency
231 """ 107 """
232 108
233 __implements__ = IAstroidChecker 109 __implements__ = IASTNGChecker
234 110
235 name = 'variables' 111 name = 'variables'
236 msgs = MSGS 112 msgs = MSGS
237 priority = -1 113 priority = -1
238 options = (("init-import", 114 options = (
115 ("init-import",
239 {'default': 0, 'type' : 'yn', 'metavar' : '<y_or_n>', 116 {'default': 0, 'type' : 'yn', 'metavar' : '<y_or_n>',
240 'help' : 'Tells whether we should check for unused import in \ 117 'help' : 'Tells whether we should check for unused import in \
241 __init__ files.'}), 118 __init__ files.'}),
242 ("dummy-variables-rgx", 119 ("dummy-variables-rgx",
243 {'default': ('_$|dummy'), 120 {'default': ('_|dummy'),
244 'type' :'regexp', 'metavar' : '<regexp>', 121 'type' :'regexp', 'metavar' : '<regexp>',
245 'help' : 'A regular expression matching the name of dummy \ 122 'help' : 'A regular expression matching the beginning of \
246 variables (i.e. expectedly not used).'}), 123 the name of dummy variables (i.e. not used).'}),
247 ("additional-builtins", 124 ("additional-builtins",
248 {'default': (), 'type' : 'csv', 125 {'default': (), 'type' : 'csv',
249 'metavar' : '<comma separated list>', 126 'metavar' : '<comma separated list>',
250 'help' : 'List of additional names supposed to be defined in \ 127 'help' : 'List of additional names supposed to be defined in \
251 builtins. Remember that you should avoid to define new builtins when possible.' 128 builtins. Remember that you should avoid to define new builtins when possible.'
252 }), 129 }),
253 ) 130 )
254 def __init__(self, linter=None): 131 def __init__(self, linter=None):
255 BaseChecker.__init__(self, linter) 132 BaseChecker.__init__(self, linter)
256 self._to_consume = None 133 self._to_consume = None
257 self._checking_mod_attr = None 134 self._checking_mod_attr = None
135 self._vars = None
258 136
259 def visit_module(self, node): 137 def visit_module(self, node):
260 """visit module : update consumption analysis variable 138 """visit module : update consumption analysis variable
261 checks globals doesn't overrides builtins 139 checks globals doesn't overrides builtins
262 """ 140 """
263 self._to_consume = [(copy(node.locals), {}, 'module')] 141 self._to_consume = [(copy(node.locals), {}, 'module')]
264 for name, stmts in node.locals.iteritems(): 142 self._vars = []
143 for name, stmts in node.locals.items():
265 if is_builtin(name) and not is_inside_except(stmts[0]): 144 if is_builtin(name) and not is_inside_except(stmts[0]):
266 # do not print Redefining builtin for additional builtins 145 # do not print Redefining builtin for additional builtins
267 self.add_message('redefined-builtin', args=name, node=stmts[0]) 146 self.add_message('W0622', args=name, node=stmts[0])
268 147
269 @check_messages('unused-import', 'unused-wildcard-import', 'redefined-builti n', 'undefined-all-variable', 'invalid-all-object') 148 @check_messages('W0611', 'W0614')
270 def leave_module(self, node): 149 def leave_module(self, node):
271 """leave module: check globals 150 """leave module: check globals
272 """ 151 """
273 assert len(self._to_consume) == 1 152 assert len(self._to_consume) == 1
274 not_consumed = self._to_consume.pop()[0] 153 not_consumed = self._to_consume.pop()[0]
275 # attempt to check for __all__ if defined
276 if '__all__' in node.locals:
277 assigned = node.igetattr('__all__').next()
278 if assigned is not astroid.YES:
279 for elt in getattr(assigned, 'elts', ()):
280 try:
281 elt_name = elt.infer().next()
282 except astroid.InferenceError:
283 continue
284
285 if not isinstance(elt_name, astroid.Const) \
286 or not isinstance(elt_name.value, basestring):
287 self.add_message('invalid-all-object', args=elt.as_strin g(), node=elt)
288 continue
289 elt_name = elt_name.value
290 # If elt is in not_consumed, remove it from not_consumed
291 if elt_name in not_consumed:
292 del not_consumed[elt_name]
293 continue
294 if elt_name not in node.locals:
295 if not node.package:
296 self.add_message('undefined-all-variable',
297 args=elt_name,
298 node=elt)
299 else:
300 basename = os.path.splitext(node.file)[0]
301 if os.path.basename(basename) == '__init__':
302 name = node.name + "." + elt_name
303 try:
304 file_from_modpath(name.split("."))
305 except ImportError:
306 self.add_message('undefined-all-variable',
307 args=elt_name,
308 node=elt)
309 except SyntaxError:
310 # don't yield an syntax-error warning,
311 # because it will be later yielded
312 # when the file will be checked
313 pass
314 # don't check unused imports in __init__ files 154 # don't check unused imports in __init__ files
315 if not self.config.init_import and node.package: 155 if not self.config.init_import and node.package:
316 return 156 return
317 for name, stmts in not_consumed.iteritems(): 157 for name, stmts in not_consumed.items():
318 if any(isinstance(stmt, astroid.AssName)
319 and isinstance(stmt.ass_type(), astroid.AugAssign)
320 for stmt in stmts):
321 continue
322 stmt = stmts[0] 158 stmt = stmts[0]
323 if isinstance(stmt, astroid.Import): 159 if isinstance(stmt, astng.Import):
324 self.add_message('unused-import', args=name, node=stmt) 160 self.add_message('W0611', args=name, node=stmt)
325 elif isinstance(stmt, astroid.From) and stmt.modname != '__future__' : 161 elif isinstance(stmt, astng.From) and stmt.modname != '__future__':
326 if stmt.names[0][0] == '*': 162 if stmt.names[0][0] == '*':
327 self.add_message('unused-wildcard-import', args=name, node=s tmt) 163 self.add_message('W0614', args=name, node=stmt)
328 else: 164 else:
329 self.add_message('unused-import', args=name, node=stmt) 165 self.add_message('W0611', args=name, node=stmt)
330 del self._to_consume 166 del self._to_consume
167 del self._vars
331 168
332 def visit_class(self, node): 169 def visit_class(self, node):
333 """visit class: update consumption analysis variable 170 """visit class: update consumption analysis variable
334 """ 171 """
335 self._to_consume.append((copy(node.locals), {}, 'class')) 172 self._to_consume.append((copy(node.locals), {}, 'class'))
336 173
337 def leave_class(self, _): 174 def leave_class(self, _):
338 """leave class: update consumption analysis variable 175 """leave class: update consumption analysis variable
339 """ 176 """
340 # do not check for not used locals here (no sense) 177 # do not check for not used locals here (no sense)
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 def leave_setcomp(self, _): 218 def leave_setcomp(self, _):
382 """leave setcomp: update consumption analysis variable 219 """leave setcomp: update consumption analysis variable
383 """ 220 """
384 # do not check for not used locals here 221 # do not check for not used locals here
385 self._to_consume.pop() 222 self._to_consume.pop()
386 223
387 def visit_function(self, node): 224 def visit_function(self, node):
388 """visit function: update consumption analysis variable and check locals 225 """visit function: update consumption analysis variable and check locals
389 """ 226 """
390 self._to_consume.append((copy(node.locals), {}, 'function')) 227 self._to_consume.append((copy(node.locals), {}, 'function'))
391 if not (self.linter.is_message_enabled('redefined-outer-name') or 228 self._vars.append({})
392 self.linter.is_message_enabled('redefined-builtin')): 229 if not set(('W0621', 'W0622')) & self.active_msgs:
393 return 230 return
394 globs = node.root().globals 231 globs = node.root().globals
395 for name, stmt in node.items(): 232 for name, stmt in node.items():
396 if is_inside_except(stmt): 233 if is_inside_except(stmt):
397 continue 234 continue
398 if name in globs and not isinstance(stmt, astroid.Global): 235 if name in globs and not isinstance(stmt, astng.Global):
399 line = globs[name][0].fromlineno 236 line = globs[name][0].lineno
400 dummy_rgx = self.config.dummy_variables_rgx 237 self.add_message('W0621', args=(name, line), node=stmt)
401 if not dummy_rgx.match(name):
402 self.add_message('redefined-outer-name', args=(name, line), node=stmt)
403 elif is_builtin(name): 238 elif is_builtin(name):
404 # do not print Redefining builtin for additional builtins 239 # do not print Redefining builtin for additional builtins
405 self.add_message('redefined-builtin', args=name, node=stmt) 240 self.add_message('W0622', args=name, node=stmt)
406 241
407 def leave_function(self, node): 242 def leave_function(self, node):
408 """leave function: check function's locals are consumed""" 243 """leave function: check function's locals are consumed"""
409 not_consumed = self._to_consume.pop()[0] 244 not_consumed = self._to_consume.pop()[0]
410 if not (self.linter.is_message_enabled('unused-variable') or 245 self._vars.pop(0)
411 self.linter.is_message_enabled('unused-argument')): 246 if not set(('W0612', 'W0613')) & self.active_msgs:
412 return 247 return
413 # don't check arguments of function which are only raising an exception 248 # don't check arguments of function which are only raising an exception
414 if is_error(node): 249 if is_error(node):
415 return 250 return
416 # don't check arguments of abstract methods or within an interface 251 # don't check arguments of abstract methods or within an interface
417 is_method = node.is_method() 252 is_method = node.is_method()
418 klass = node.parent.frame() 253 klass = node.parent.frame()
419 if is_method and (klass.type == 'interface' or node.is_abstract()): 254 if is_method and (klass.type == 'interface' or node.is_abstract()):
420 return 255 return
421 authorized_rgx = self.config.dummy_variables_rgx 256 authorized_rgx = self.config.dummy_variables_rgx
422 called_overridden = False 257 called_overridden = False
423 argnames = node.argnames() 258 argnames = node.argnames()
424 global_names = set()
425 nonlocal_names = set()
426 for global_stmt in node.nodes_of_class(astroid.Global):
427 global_names.update(set(global_stmt.names))
428 for nonlocal_stmt in node.nodes_of_class(astroid.Nonlocal):
429 nonlocal_names.update(set(nonlocal_stmt.names))
430
431 for name, stmts in not_consumed.iteritems(): 259 for name, stmts in not_consumed.iteritems():
432 # ignore some special names specified by user configuration 260 # ignore some special names specified by user configuration
433 if authorized_rgx.match(name): 261 if authorized_rgx.match(name):
434 continue 262 continue
435 # ignore names imported by the global statement 263 # ignore names imported by the global statement
436 # FIXME: should only ignore them if it's assigned latter 264 # FIXME: should only ignore them if it's assigned latter
437 stmt = stmts[0] 265 stmt = stmts[0]
438 if isinstance(stmt, astroid.Global): 266 if isinstance(stmt, astng.Global):
439 continue 267 continue
440 if isinstance(stmt, (astroid.Import, astroid.From)):
441 # Detect imports, assigned to global statements.
442 if global_names:
443 skip = False
444 for import_name, import_alias in stmt.names:
445 # If the import uses an alias, check only that.
446 # Otherwise, check only the import name.
447 if import_alias:
448 if import_alias in global_names:
449 skip = True
450 break
451 elif import_name in global_names:
452 skip = True
453 break
454 if skip:
455 continue
456
457 # care about functions with unknown argument (builtins) 268 # care about functions with unknown argument (builtins)
458 if name in argnames: 269 if name in argnames:
459 if is_method: 270 if is_method:
460 # don't warn for the first argument of a (non static) method 271 # don't warn for the first argument of a (non static) method
461 if node.type != 'staticmethod' and name == argnames[0]: 272 if node.type != 'staticmethod' and name == argnames[0]:
462 continue 273 continue
463 # don't warn for argument of an overridden method 274 # don't warn for argument of an overridden method
464 if not called_overridden: 275 if not called_overridden:
465 overridden = overridden_method(klass, node.name) 276 overridden = overridden_method(klass, node.name)
466 called_overridden = True 277 called_overridden = True
467 if overridden is not None and name in overridden.argnames(): 278 if overridden is not None and name in overridden.argnames():
468 continue 279 continue
469 if node.name in PYMETHODS and node.name not in ('__init__', '__new__'): 280 if node.name in PYMETHODS and node.name not in ('__init__', '__new__'):
470 continue 281 continue
471 # don't check callback arguments XXX should be configurable 282 # don't check callback arguments XXX should be configurable
472 if node.name.startswith('cb_') or node.name.endswith('_cb'): 283 if node.name.startswith('cb_') or node.name.endswith('_cb'):
473 continue 284 continue
474 self.add_message('unused-argument', args=name, node=stmt) 285 self.add_message('W0613', args=name, node=stmt)
475 else: 286 else:
476 if stmt.parent and isinstance(stmt.parent, astroid.Assign): 287 self.add_message('W0612', args=name, node=stmt)
477 if name in nonlocal_names:
478 continue
479 self.add_message('unused-variable', args=name, node=stmt)
480 288
481 @check_messages('global-variable-undefined', 'global-variable-not-assigned', 'global-statement', 289 @check_messages('W0601', 'W0602', 'W0603', 'W0604', 'W0622')
482 'global-at-module-level', 'redefined-builtin')
483 def visit_global(self, node): 290 def visit_global(self, node):
484 """check names imported exists in the global scope""" 291 """check names imported exists in the global scope"""
485 frame = node.frame() 292 frame = node.frame()
486 if isinstance(frame, astroid.Module): 293 if isinstance(frame, astng.Module):
487 self.add_message('global-at-module-level', node=node) 294 self.add_message('W0604', node=node)
488 return 295 return
489 module = frame.root() 296 module = frame.root()
490 default_message = True 297 default_message = True
491 for name in node.names: 298 for name in node.names:
492 try: 299 try:
493 assign_nodes = module.getattr(name) 300 assign_nodes = module.getattr(name)
494 except astroid.NotFoundError: 301 except astng.NotFoundError:
495 # unassigned global, skip 302 # unassigned global, skip
496 assign_nodes = [] 303 assign_nodes = []
497 for anode in assign_nodes: 304 for anode in assign_nodes:
498 if anode.parent is None: 305 if anode.parent is None:
499 # node returned for builtin attribute such as __file__, 306 # node returned for builtin attribute such as __file__,
500 # __doc__, etc... 307 # __doc__, etc...
501 continue 308 continue
502 if anode.frame() is frame: 309 if anode.frame() is frame:
503 # same scope level assignment 310 # same scope level assignment
504 break 311 break
505 else: 312 else:
506 # global but no assignment 313 # global but no assignment
507 # Detect imports in the current frame, with the required 314 self.add_message('W0602', args=name, node=node)
508 # name. Such imports can be considered assignments.
509 imports = frame.nodes_of_class((astroid.Import, astroid.From))
510 for import_node in imports:
511 found = False
512 for import_name, import_alias in import_node.names:
513 # If the import uses an alias, check only that.
514 # Otherwise, check only the import name.
515 if import_alias:
516 if import_alias == name:
517 found = True
518 break
519 elif import_name and import_name == name:
520 found = True
521 break
522 if found:
523 break
524 else:
525 self.add_message('global-variable-not-assigned',
526 args=name, node=node)
527 default_message = False 315 default_message = False
528 if not assign_nodes: 316 if not assign_nodes:
529 continue 317 continue
530 for anode in assign_nodes: 318 for anode in assign_nodes:
531 if anode.parent is None: 319 if anode.parent is None:
532 self.add_message('redefined-builtin', args=name, node=node) 320 self.add_message('W0622', args=name, node=node)
533 break 321 break
534 if anode.frame() is module: 322 if anode.frame() is module:
535 # module level assignment 323 # module level assignment
536 break 324 break
537 else: 325 else:
538 # global undefined at the module scope 326 # global undefined at the module scope
539 self.add_message('global-variable-undefined', args=name, node=no de) 327 self.add_message('W0601', args=name, node=node)
540 default_message = False 328 default_message = False
541 if default_message: 329 if default_message:
542 self.add_message('global-statement', node=node) 330 self.add_message('W0603', node=node)
543
544 def _check_late_binding_closure(self, node, assignment_node, scope_type):
545 def _is_direct_lambda_call():
546 return (isinstance(node_scope.parent, astroid.CallFunc)
547 and node_scope.parent.func is node_scope)
548
549 node_scope = node.scope()
550 if not isinstance(node_scope, (astroid.Lambda, astroid.Function)):
551 return
552 if isinstance(node.parent, astroid.Arguments):
553 return
554
555 if isinstance(assignment_node, astroid.Comprehension):
556 if assignment_node.parent.parent_of(node.scope()):
557 self.add_message('cell-var-from-loop', node=node, args=node.name )
558 else:
559 assign_scope = assignment_node.scope()
560 maybe_for = assignment_node
561 while not isinstance(maybe_for, astroid.For):
562 if maybe_for is assign_scope:
563 break
564 maybe_for = maybe_for.parent
565 else:
566 if (maybe_for.parent_of(node_scope)
567 and not _is_direct_lambda_call()
568 and not isinstance(node_scope.statement(), astroid.Retur n)):
569 self.add_message('cell-var-from-loop', node=node, args=node. name)
570 331
571 def _loopvar_name(self, node, name): 332 def _loopvar_name(self, node, name):
572 # filter variables according to node's scope 333 # filter variables according to node's scope
573 # XXX used to filter parents but don't remember why, and removing this 334 # XXX used to filter parents but don't remember why, and removing this
574 # fixes a W0631 false positive reported by Paul Hachmann on 2008/12 on 335 # fixes a W0631 false positive reported by Paul Hachmann on 2008/12 on
575 # python-projects (added to func_use_for_or_listcomp_var test) 336 # python-projects (added to func_use_for_or_listcomp_var test)
576 #astmts = [stmt for stmt in node.lookup(name)[1] 337 #astmts = [stmt for stmt in node.lookup(name)[1]
577 # if hasattr(stmt, 'ass_type')] and 338 # if hasattr(stmt, 'ass_type')] and
578 # not stmt.statement().parent_of(node)] 339 # not stmt.statement().parent_of(node)]
579 if not self.linter.is_message_enabled('undefined-loop-variable'): 340 if 'W0631' not in self.active_msgs:
580 return 341 return
581 astmts = [stmt for stmt in node.lookup(name)[1] 342 astmts = [stmt for stmt in node.lookup(name)[1]
582 if hasattr(stmt, 'ass_type')] 343 if hasattr(stmt, 'ass_type')]
583 # filter variables according their respective scope test is_statement 344 # filter variables according their respective scope test is_statement
584 # and parent to avoid #74747. This is not a total fix, which would 345 # and parent to avoid #74747. This is not a total fix, which would
585 # introduce a mechanism similar to special attribute lookup in 346 # introduce a mechanism similar to special attribute lookup in
586 # modules. Also, in order to get correct inference in this case, the 347 # modules. Also, in order to get correct inference in this case, the
587 # scope lookup rules would need to be changed to return the initial 348 # scope lookup rules would need to be changed to return the initial
588 # assignment (which does not exist in code per se) as well as any later 349 # assignment (which does not exist in code per se) as well as any later
589 # modifications. 350 # modifications.
590 if not astmts or (astmts[0].is_statement or astmts[0].parent) \ 351 if not astmts or (astmts[0].is_statement or astmts[0].parent) \
591 and astmts[0].statement().parent_of(node): 352 and astmts[0].statement().parent_of(node):
592 _astmts = [] 353 _astmts = []
593 else: 354 else:
594 _astmts = astmts[:1] 355 _astmts = astmts[:1]
595 for i, stmt in enumerate(astmts[1:]): 356 for i, stmt in enumerate(astmts[1:]):
596 if (astmts[i].statement().parent_of(stmt) 357 if (astmts[i].statement().parent_of(stmt)
597 and not in_for_else_branch(astmts[i].statement(), stmt)): 358 and not in_for_else_branch(astmts[i].statement(), stmt)):
598 continue 359 continue
599 _astmts.append(stmt) 360 _astmts.append(stmt)
600 astmts = _astmts 361 astmts = _astmts
601 if len(astmts) == 1: 362 if len(astmts) == 1:
602 ass = astmts[0].ass_type() 363 ass = astmts[0].ass_type()
603 if isinstance(ass, (astroid.For, astroid.Comprehension, astroid.GenE xpr)) \ 364 if isinstance(ass, (astng.For, astng.Comprehension, astng.GenExpr)) \
604 and not ass.statement() is node.statement(): 365 and not ass.statement() is node.statement():
605 self.add_message('undefined-loop-variable', args=name, node=node ) 366 self.add_message('W0631', args=name, node=node)
606 367
607 @check_messages('redefine-in-handler')
608 def visit_excepthandler(self, node): 368 def visit_excepthandler(self, node):
609 for name in get_all_elements(node.name): 369 clobbering, args = clobber_in_except(node.name)
610 clobbering, args = clobber_in_except(name) 370 if clobbering:
611 if clobbering: 371 self.add_message('W0623', args=args, node=node)
612 self.add_message('redefine-in-handler', args=args, node=name)
613 372
614 def visit_assname(self, node): 373 def visit_assname(self, node):
615 if isinstance(node.ass_type(), astroid.AugAssign): 374 if isinstance(node.ass_type(), astng.AugAssign):
616 self.visit_name(node) 375 self.visit_name(node)
617 376
618 def visit_delname(self, node): 377 def visit_delname(self, node):
619 self.visit_name(node) 378 self.visit_name(node)
620 379
621 @check_messages(*(MSGS.keys()))
622 def visit_name(self, node): 380 def visit_name(self, node):
623 """check that a name is defined if the current scope and doesn't 381 """check that a name is defined if the current scope and doesn't
624 redefine a built-in 382 redefine a built-in
625 """ 383 """
626 stmt = node.statement() 384 stmt = node.statement()
627 if stmt.fromlineno is None: 385 if stmt.fromlineno is None:
628 # name node from a astroid built from live code, skip 386 # name node from a astng built from live code, skip
629 assert not stmt.root().file.endswith('.py') 387 assert not stmt.root().file.endswith('.py')
630 return 388 return
631 name = node.name 389 name = node.name
632 frame = stmt.scope() 390 frame = stmt.scope()
633 # if the name node is used as a function default argument's value or as 391 # if the name node is used as a function default argument's value or as
634 # a decorator, then start from the parent frame of the function instead 392 # a decorator, then start from the parent frame of the function instead
635 # of the function frame - and thus open an inner class scope 393 # of the function frame - and thus open an inner class scope
636 if (is_func_default(node) or is_func_decorator(node) 394 if (is_func_default(node) or is_func_decorator(node)
637 or is_ancestor_name(frame, node)): 395 or is_ancestor_name(frame, node)):
638 start_index = len(self._to_consume) - 2 396 start_index = len(self._to_consume) - 2
639 else: 397 else:
640 start_index = len(self._to_consume) - 1 398 start_index = len(self._to_consume) - 1
641 # iterates through parent scopes, from the inner to the outer 399 # iterates through parent scopes, from the inner to the outer
642 base_scope_type = self._to_consume[start_index][-1] 400 base_scope_type = self._to_consume[start_index][-1]
643 for i in range(start_index, -1, -1): 401 for i in range(start_index, -1, -1):
644 to_consume, consumed, scope_type = self._to_consume[i] 402 to_consume, consumed, scope_type = self._to_consume[i]
645 # if the current scope is a class scope but it's not the inner 403 # if the current scope is a class scope but it's not the inner
646 # scope, ignore it. This prevents to access this scope instead of 404 # scope, ignore it. This prevents to access this scope instead of
647 # the globals one in function members when there are some common 405 # the globals one in function members when there are some common
648 # names. The only exception is when the starting scope is a 406 # names. The only exception is when the starting scope is a
649 # comprehension and its direct outer scope is a class 407 # comprehension and its direct outer scope is a class
650 if scope_type == 'class' and i != start_index and not ( 408 if scope_type == 'class' and i != start_index and not (
651 base_scope_type == 'comprehension' and i == start_index-1): 409 base_scope_type == 'comprehension' and i == start_index-1):
652 # Detect if we are in a local class scope, as an assignment. 410 # XXX find a way to handle class scope in a smoother way
653 # For example, the following is fair game. 411 continue
654 # class A:
655 # b = 1
656 # c = lambda b=b: b * b
657 class_assignment = (isinstance(frame, astroid.Class) and
658 name in frame.locals)
659 if not class_assignment:
660 continue
661 # the name has already been consumed, only check it's not a loop 412 # the name has already been consumed, only check it's not a loop
662 # variable used outside the loop 413 # variable used outside the loop
663 if name in consumed: 414 if name in consumed:
664 defnode = assign_parent(consumed[name][0])
665 self._check_late_binding_closure(node, defnode, scope_type)
666 self._loopvar_name(node, name) 415 self._loopvar_name(node, name)
667 break 416 break
668 # mark the name as consumed if it's defined in this scope 417 # mark the name as consumed if it's defined in this scope
669 # (i.e. no KeyError is raised by "to_consume[name]") 418 # (i.e. no KeyError is raised by "to_consume[name]")
670 try: 419 try:
671 consumed[name] = to_consume[name] 420 consumed[name] = to_consume[name]
672 except KeyError: 421 except KeyError:
673 continue 422 continue
674 # checks for use before assignment 423 # checks for use before assignment
675 defnode = assign_parent(to_consume[name][0]) 424 defnode = assign_parent(to_consume[name][0])
676 if defnode is not None: 425 if defnode is not None:
677 self._check_late_binding_closure(node, defnode, scope_type)
678 defstmt = defnode.statement() 426 defstmt = defnode.statement()
679 defframe = defstmt.frame() 427 defframe = defstmt.frame()
680 maybee0601 = True 428 maybee0601 = True
681 if not frame is defframe: 429 if not frame is defframe:
682 maybee0601 = _detect_global_scope(node, frame, defframe) 430 maybee0601 = False
683 elif defframe.parent is None: 431 elif defframe.parent is None:
684 # we are at the module level, check the name is not 432 # we are at the module level, check the name is not
685 # defined in builtins 433 # defined in builtins
686 if name in defframe.scope_attrs or builtin_lookup(name)[1]: 434 if name in defframe.scope_attrs or builtin_lookup(name)[1]:
687 maybee0601 = False 435 maybee0601 = False
688 else: 436 else:
689 # we are in a local scope, check the name is not 437 # we are in a local scope, check the name is not
690 # defined in global or builtin scope 438 # defined in global or builtin scope
691 if defframe.root().lookup(name)[1]: 439 if defframe.root().lookup(name)[1]:
692 maybee0601 = False 440 maybee0601 = False
693 else:
694 # check if we have a nonlocal
695 if name in defframe.locals:
696 maybee0601 = not any(isinstance(child, astroid.Nonlo cal)
697 and name in child.names
698 for child in defframe.get_child ren())
699 if (self._to_consume[-1][-1] == 'lambda' and
700 isinstance(frame, astroid.Class)
701 and name in frame.locals):
702 maybee0601 = True
703 else:
704 maybee0601 = maybee0601 and stmt.fromlineno <= defstmt.froml ineno
705
706 if (maybee0601 441 if (maybee0601
707 and not is_defined_before(node) 442 and stmt.fromlineno <= defstmt.fromlineno
708 and not are_exclusive(stmt, defstmt, ('NameError', 443 and not is_defined_before(node)
709 'Exception', 444 and not are_exclusive(stmt, defstmt, ('NameError', 'Exceptio n', 'BaseException'))):
710 'BaseException'))) : 445 if defstmt is stmt and isinstance(node, (astng.DelName,
711 if defstmt is stmt and isinstance(node, (astroid.DelName, 446 astng.AssName)):
712 astroid.AssName)): 447 self.add_message('E0602', args=name, node=node)
713 self.add_message('undefined-variable', args=name, node=n ode)
714 elif self._to_consume[-1][-1] != 'lambda': 448 elif self._to_consume[-1][-1] != 'lambda':
715 # E0601 may *not* occurs in lambda scope. 449 # E0601 may *not* occurs in lambda scope
716 self.add_message('used-before-assignment', args=name, no de=node) 450 self.add_message('E0601', args=name, node=node)
717 elif self._to_consume[-1][-1] == 'lambda': 451 if not isinstance(node, astng.AssName): # Aug AssName
718 # E0601 can occur in class-level scope in lambdas, as in 452 del to_consume[name]
719 # the following example: 453 else:
720 # class A:
721 # x = lambda attr: f + attr
722 # f = 42
723 if isinstance(frame, astroid.Class) and name in frame.lo cals:
724 if isinstance(node.parent, astroid.Arguments):
725 # Doing the following is fine:
726 # class A:
727 # x = 42
728 # y = lambda attr=x: attr
729 if stmt.fromlineno <= defstmt.fromlineno:
730 self.add_message('used-before-assignment',
731 args=name, node=node)
732 else:
733 self.add_message('undefined-variable',
734 args=name, node=node)
735
736 if isinstance(node, astroid.AssName): # Aug AssName
737 del consumed[name] 454 del consumed[name]
738 else:
739 del to_consume[name]
740 # check it's not a loop variable used outside the loop 455 # check it's not a loop variable used outside the loop
741 self._loopvar_name(node, name) 456 self._loopvar_name(node, name)
742 break 457 break
743 else: 458 else:
744 # we have not found the name, if it isn't a builtin, that's an 459 # we have not found the name, if it isn't a builtin, that's an
745 # undefined name ! 460 # undefined name !
746 if not (name in astroid.Module.scope_attrs or is_builtin(name) 461 if not (name in astng.Module.scope_attrs or is_builtin(name)
747 or name in self.config.additional_builtins): 462 or name in self.config.additional_builtins):
748 self.add_message('undefined-variable', args=name, node=node) 463 self.add_message('E0602', args=name, node=node)
749 464
750 @check_messages('no-name-in-module') 465 @check_messages('E0611')
751 def visit_import(self, node): 466 def visit_import(self, node):
752 """check modules attribute accesses""" 467 """check modules attribute accesses"""
753 for name, _ in node.names: 468 for name, _ in node.names:
754 parts = name.split('.') 469 parts = name.split('.')
755 try: 470 try:
756 module = node.infer_name_module(parts[0]).next() 471 module = node.infer_name_module(parts[0]).next()
757 except astroid.ResolveError: 472 except astng.ResolveError:
758 continue 473 continue
759 self._check_module_attrs(node, module, parts[1:]) 474 self._check_module_attrs(node, module, parts[1:])
760 475
761 @check_messages('no-name-in-module') 476 @check_messages('E0611')
762 def visit_from(self, node): 477 def visit_from(self, node):
763 """check modules attribute accesses""" 478 """check modules attribute accesses"""
764 name_parts = node.modname.split('.') 479 name_parts = node.modname.split('.')
765 level = getattr(node, 'level', None) 480 level = getattr(node, 'level', None)
766 try: 481 try:
767 module = node.root().import_module(name_parts[0], level=level) 482 module = node.root().import_module(name_parts[0], level=level)
768 except AstroidBuildingException: 483 except ASTNGBuildingException:
769 return 484 return
770 except Exception, exc: 485 except Exception, exc:
771 print 'Unhandled exception in VariablesChecker:', exc 486 print 'Unhandled exception in VariablesChecker:', exc
772 return 487 return
773 module = self._check_module_attrs(node, module, name_parts[1:]) 488 module = self._check_module_attrs(node, module, name_parts[1:])
774 if not module: 489 if not module:
775 return 490 return
776 for name, _ in node.names: 491 for name, _ in node.names:
777 if name == '*': 492 if name == '*':
778 continue 493 continue
779 self._check_module_attrs(node, module, name.split('.')) 494 self._check_module_attrs(node, module, name.split('.'))
780 495
781 @check_messages('unbalanced-tuple-unpacking', 'unpacking-non-sequence')
782 def visit_assign(self, node):
783 """Check unbalanced tuple unpacking for assignments
784 and unpacking non-sequences.
785 """
786 if not isinstance(node.targets[0], (astroid.Tuple, astroid.List)):
787 return
788
789 targets = node.targets[0].itered()
790 try:
791 for infered in node.value.infer():
792 self._check_unpacking(infered, node, targets)
793 except astroid.InferenceError:
794 return
795
796 def _check_unpacking(self, infered, node, targets):
797 """ Check for unbalanced tuple unpacking
798 and unpacking non sequences.
799 """
800 if infered is astroid.YES:
801 return
802 if isinstance(infered, (astroid.Tuple, astroid.List)):
803 # attempt to check unpacking is properly balanced
804 values = infered.itered()
805 if len(targets) != len(values):
806 # Check if we have starred nodes.
807 if any(isinstance(target, astroid.Starred)
808 for target in targets):
809 return
810 self.add_message('unbalanced-tuple-unpacking', node=node,
811 args=(_get_unpacking_extra_info(node, infered),
812 len(targets),
813 len(values)))
814 # attempt to check unpacking may be possible (ie RHS is iterable)
815 elif isinstance(infered, astroid.Instance):
816 for meth in ('__iter__', '__getitem__'):
817 try:
818 infered.getattr(meth)
819 break
820 except astroid.NotFoundError:
821 continue
822 else:
823 self.add_message('unpacking-non-sequence', node=node,
824 args=(_get_unpacking_extra_info(node, infered), ))
825 else:
826 self.add_message('unpacking-non-sequence', node=node,
827 args=(_get_unpacking_extra_info(node, infered),))
828
829
830 def _check_module_attrs(self, node, module, module_names): 496 def _check_module_attrs(self, node, module, module_names):
831 """check that module_names (list of string) are accessible through the 497 """check that module_names (list of string) are accessible through the
832 given module 498 given module
833 if the latest access name corresponds to a module, return it 499 if the latest access name corresponds to a module, return it
834 """ 500 """
835 assert isinstance(module, astroid.Module), module 501 assert isinstance(module, astng.Module), module
836 ignored_modules = get_global_option(self, 'ignored-modules',
837 default=[])
838 while module_names: 502 while module_names:
839 name = module_names.pop(0) 503 name = module_names.pop(0)
840 if name == '__dict__': 504 if name == '__dict__':
841 module = None 505 module = None
842 break 506 break
843 try: 507 try:
844 module = module.getattr(name)[0].infer().next() 508 module = module.getattr(name)[0].infer().next()
845 if module is astroid.YES: 509 if module is astng.YES:
846 return None 510 return None
847 except astroid.NotFoundError: 511 except astng.NotFoundError:
848 if module.name in ignored_modules: 512 self.add_message('E0611', args=(name, module.name), node=node)
849 return None
850 self.add_message('no-name-in-module',
851 args=(name, module.name), node=node)
852 return None 513 return None
853 except astroid.InferenceError: 514 except astng.InferenceError:
854 return None 515 return None
855 if module_names: 516 if module_names:
856 # FIXME: other message if name is not the latest part of 517 # FIXME: other message if name is not the latest part of
857 # module_names ? 518 # module_names ?
858 modname = module and module.name or '__dict__' 519 modname = module and module.name or '__dict__'
859 self.add_message('no-name-in-module', node=node, 520 self.add_message('E0611', node=node,
860 args=('.'.join(module_names), modname)) 521 args=('.'.join(module_names), modname))
861 return None 522 return None
862 if isinstance(module, astroid.Module): 523 if isinstance(module, astng.Module):
863 return module 524 return module
864 return None 525 return None
865 526
866 527
867 class VariablesChecker3k(VariablesChecker): 528 class VariablesChecker3k(VariablesChecker):
868 '''Modified variables checker for 3k''' 529 '''Modified variables checker for 3k'''
869 # listcomp have now also their scope 530 # listcomp have now also their scope
870 531
871 def visit_listcomp(self, node): 532 def visit_listcomp(self, node):
872 """visit dictcomp: update consumption analysis variable 533 """visit dictcomp: update consumption analysis variable
873 """ 534 """
874 self._to_consume.append((copy(node.locals), {}, 'comprehension')) 535 self._to_consume.append((copy(node.locals), {}, 'comprehension'))
875 536
876 def leave_listcomp(self, _): 537 def leave_listcomp(self, _):
877 """leave dictcomp: update consumption analysis variable 538 """leave dictcomp: update consumption analysis variable
878 """ 539 """
879 # do not check for not used locals here 540 # do not check for not used locals here
880 self._to_consume.pop() 541 self._to_consume.pop()
881 542
882 def leave_module(self, node):
883 """ Update consumption analysis variable
884 for metaclasses.
885 """
886 module_locals = self._to_consume[0][0]
887 module_imports = self._to_consume[0][1]
888 consumed = {}
889
890 for klass in node.nodes_of_class(astroid.Class):
891 found = metaclass = name = None
892 if not klass._metaclass:
893 # Skip if this class doesn't use
894 # explictly a metaclass, but inherits it from ancestors
895 continue
896
897 metaclass = klass.metaclass()
898
899 # Look the name in the already found locals.
900 # If it's not found there, look in the module locals
901 # and in the imported modules.
902 if isinstance(klass._metaclass, astroid.Name):
903 name = klass._metaclass.name
904 elif metaclass:
905 # if it uses a `metaclass=module.Class`
906 name = metaclass.root().name
907
908 if name:
909 found = consumed.setdefault(
910 name, module_locals.get(name, module_imports.get(name)))
911
912 if found is None and not metaclass:
913 name = None
914 if isinstance(klass._metaclass, astroid.Name):
915 name = klass._metaclass.name
916 elif isinstance(klass._metaclass, astroid.Getattr):
917 name = klass._metaclass.as_string()
918
919 if name is not None:
920 if not (name in astroid.Module.scope_attrs or
921 is_builtin(name) or
922 name in self.config.additional_builtins or
923 name in node.locals):
924 self.add_message('undefined-variable',
925 node=klass,
926 args=(name, ))
927 # Pop the consumed items, in order to
928 # avoid having unused-import false positives
929 for name in consumed:
930 module_locals.pop(name, None)
931 super(VariablesChecker3k, self).leave_module(node)
932
933 if sys.version_info >= (3, 0): 543 if sys.version_info >= (3, 0):
934 VariablesChecker = VariablesChecker3k 544 VariablesChecker = VariablesChecker3k
935 545
936 546
937 def register(linter): 547 def register(linter):
938 """required method to auto register this checker""" 548 """required method to auto register this checker"""
939 linter.register_checker(VariablesChecker(linter)) 549 linter.register_checker(VariablesChecker(linter))
OLDNEW
« 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