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

Side by Side Diff: third_party/pylint/checkers/utils.py

Issue 739393004: Revert "Revert "pylint: upgrade to 1.3.1"" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools/
Patch Set: Created 6 years 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 | Annotate | Revision Log
« no previous file with comments | « third_party/pylint/checkers/typecheck.py ('k') | third_party/pylint/checkers/variables.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 # pylint: disable=W0611 1 # pylint: disable=W0611
2 # 2 #
3 # Copyright (c) 2003-2010 LOGILAB S.A. (Paris, FRANCE). 3 # Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE).
4 # http://www.logilab.fr/ -- mailto:contact@logilab.fr 4 # http://www.logilab.fr/ -- mailto:contact@logilab.fr
5 # 5 #
6 # This program is free software; you can redistribute it and/or modify it under 6 # This program is free software; you can redistribute it and/or modify it under
7 # the terms of the GNU General Public License as published by the Free Software 7 # the terms of the GNU General Public License as published by the Free Software
8 # Foundation; either version 2 of the License, or (at your option) any later 8 # Foundation; either version 2 of the License, or (at your option) any later
9 # version. 9 # version.
10 # 10 #
11 # This program is distributed in the hope that it will be useful, but WITHOUT 11 # This program is distributed in the hope that it will be useful, but WITHOUT
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 # 14 #
15 # You should have received a copy of the GNU General Public License along with 15 # You should have received a copy of the GNU General Public License along with
16 # this program; if not, write to the Free Software Foundation, Inc., 16 # this program; if not, write to the Free Software Foundation, Inc.,
17 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 """some functions that may be useful for various checkers 18 """some functions that may be useful for various checkers
19 """ 19 """
20 20
21 import re
22 import sys
21 import string 23 import string
22 from logilab import astng 24
25 import astroid
26 from astroid import scoped_nodes
23 from logilab.common.compat import builtins 27 from logilab.common.compat import builtins
28
24 BUILTINS_NAME = builtins.__name__ 29 BUILTINS_NAME = builtins.__name__
30 COMP_NODE_TYPES = astroid.ListComp, astroid.SetComp, astroid.DictComp, astroid.G enExpr
31 PY3K = sys.version_info[0] == 3
25 32
26 COMP_NODE_TYPES = astng.ListComp, astng.SetComp, astng.DictComp, astng.GenExpr 33
34 class NoSuchArgumentError(Exception):
35 pass
27 36
28 def is_inside_except(node): 37 def is_inside_except(node):
29 """Returns true if node is directly inside an exception handler""" 38 """Returns true if node is inside the name of an except handler."""
30 return isinstance(node.parent, astng.ExceptHandler) 39 current = node
40 while current and not isinstance(current.parent, astroid.ExceptHandler):
41 current = current.parent
42
43 return current and current is current.parent.name
44
45
46 def get_all_elements(node):
47 """Recursively returns all atoms in nested lists and tuples."""
48 if isinstance(node, (astroid.Tuple, astroid.List)):
49 for child in node.elts:
50 for e in get_all_elements(child):
51 yield e
52 else:
53 yield node
31 54
32 55
33 def clobber_in_except(node): 56 def clobber_in_except(node):
34 """Checks if an assignment node in an except handler clobbers an existing 57 """Checks if an assignment node in an except handler clobbers an existing
35 variable. 58 variable.
36 59
37 Returns (True, args for W0623) if assignment clobbers an existing variable, 60 Returns (True, args for W0623) if assignment clobbers an existing variable,
38 (False, None) otherwise. 61 (False, None) otherwise.
39 """ 62 """
40 if isinstance(node, astng.AssAttr): 63 if isinstance(node, astroid.AssAttr):
41 return (True, (node.attrname, 'object %r' % (node.expr.name,))) 64 return (True, (node.attrname, 'object %r' % (node.expr.as_string(),)))
42 elif node is not None: 65 elif isinstance(node, astroid.AssName):
43 name = node.name 66 name = node.name
44 if is_builtin(name): 67 if is_builtin(name):
45 return (True, (name, 'builtins')) 68 return (True, (name, 'builtins'))
46 else: 69 else:
47 scope, stmts = node.lookup(name) 70 stmts = node.lookup(name)[1]
48 if (stmts and 71 if (stmts and not isinstance(stmts[0].ass_type(),
49 not isinstance(stmts[0].ass_type(), 72 (astroid.Assign, astroid.AugAssign,
50 (astng.Assign, astng.AugAssign, astng.ExceptHandl er))): 73 astroid.ExceptHandler))):
51 return (True, (name, 'outer scope (line %i)' % (stmts[0].lineno, ))) 74 return (True, (name, 'outer scope (line %s)' % stmts[0].fromline no))
52 return (False, None) 75 return (False, None)
53 76
54 77
55 def safe_infer(node): 78 def safe_infer(node):
56 """return the inferred value for the given node. 79 """return the inferred value for the given node.
57 Return None if inference failed or if there is some ambiguity (more than 80 Return None if inference failed or if there is some ambiguity (more than
58 one node has been inferred) 81 one node has been inferred)
59 """ 82 """
60 try: 83 try:
61 inferit = node.infer() 84 inferit = node.infer()
62 value = inferit.next() 85 value = inferit.next()
63 except astng.InferenceError: 86 except astroid.InferenceError:
64 return 87 return
65 try: 88 try:
66 inferit.next() 89 inferit.next()
67 return # None if there is ambiguity on the inferred node 90 return # None if there is ambiguity on the inferred node
91 except astroid.InferenceError:
92 return # there is some kind of ambiguity
68 except StopIteration: 93 except StopIteration:
69 return value 94 return value
70 95
71 def is_super(node): 96 def is_super(node):
72 """return True if the node is referencing the "super" builtin function 97 """return True if the node is referencing the "super" builtin function
73 """ 98 """
74 if getattr(node, 'name', None) == 'super' and \ 99 if getattr(node, 'name', None) == 'super' and \
75 node.root().name == BUILTINS_NAME: 100 node.root().name == BUILTINS_NAME:
76 return True 101 return True
77 return False 102 return False
78 103
79 def is_error(node): 104 def is_error(node):
80 """return true if the function does nothing but raising an exception""" 105 """return true if the function does nothing but raising an exception"""
81 for child_node in node.get_children(): 106 for child_node in node.get_children():
82 if isinstance(child_node, astng.Raise): 107 if isinstance(child_node, astroid.Raise):
83 return True 108 return True
84 return False 109 return False
85 110
86 def is_raising(body): 111 def is_raising(body):
87 """return true if the given statement node raise an exception""" 112 """return true if the given statement node raise an exception"""
88 for node in body: 113 for node in body:
89 if isinstance(node, astng.Raise): 114 if isinstance(node, astroid.Raise):
90 return True 115 return True
91 return False 116 return False
92 117
93 def is_empty(body): 118 def is_empty(body):
94 """return true if the given node does nothing but 'pass'""" 119 """return true if the given node does nothing but 'pass'"""
95 return len(body) == 1 and isinstance(body[0], astng.Pass) 120 return len(body) == 1 and isinstance(body[0], astroid.Pass)
96 121
97 builtins = __builtins__.copy() 122 builtins = builtins.__dict__.copy()
98 SPECIAL_BUILTINS = ('__builtins__',) # '__path__', '__file__') 123 SPECIAL_BUILTINS = ('__builtins__',) # '__path__', '__file__')
99 124
125 def is_builtin_object(node):
126 """Returns True if the given node is an object from the __builtin__ module." ""
127 return node and node.root().name == BUILTINS_NAME
128
100 def is_builtin(name): # was is_native_builtin 129 def is_builtin(name): # was is_native_builtin
101 """return true if <name> could be considered as a builtin defined by python 130 """return true if <name> could be considered as a builtin defined by python
102 """ 131 """
103 if name in builtins: 132 if name in builtins:
104 return True 133 return True
105 if name in SPECIAL_BUILTINS: 134 if name in SPECIAL_BUILTINS:
106 return True 135 return True
107 return False 136 return False
108 137
109 def is_defined_before(var_node): 138 def is_defined_before(var_node):
110 """return True if the variable node is defined by a parent node (list, 139 """return True if the variable node is defined by a parent node (list,
111 set, dict, or generator comprehension, lambda) or in a previous sibling 140 set, dict, or generator comprehension, lambda) or in a previous sibling
112 node on the same line (statement_defining ; statement_using) 141 node on the same line (statement_defining ; statement_using)
113 """ 142 """
114 varname = var_node.name 143 varname = var_node.name
115 _node = var_node.parent 144 _node = var_node.parent
116 while _node: 145 while _node:
117 if isinstance(_node, COMP_NODE_TYPES): 146 if isinstance(_node, COMP_NODE_TYPES):
118 for ass_node in _node.nodes_of_class(astng.AssName): 147 for ass_node in _node.nodes_of_class(astroid.AssName):
119 if ass_node.name == varname: 148 if ass_node.name == varname:
120 return True 149 return True
121 elif isinstance(_node, astng.For): 150 elif isinstance(_node, astroid.For):
122 for ass_node in _node.target.nodes_of_class(astng.AssName): 151 for ass_node in _node.target.nodes_of_class(astroid.AssName):
123 if ass_node.name == varname: 152 if ass_node.name == varname:
124 return True 153 return True
125 elif isinstance(_node, astng.With): 154 elif isinstance(_node, astroid.With):
126 if _node.vars is None: 155 for expr, vars in _node.items:
127 # quickfix : case in which 'with' is used without 'as' 156 if expr.parent_of(var_node):
128 return False 157 break
129 if _node.vars.name == varname: 158 if (vars and
130 return True 159 isinstance(vars, astroid.AssName) and
131 elif isinstance(_node, (astng.Lambda, astng.Function)): 160 vars.name == varname):
161 return True
162 elif isinstance(_node, (astroid.Lambda, astroid.Function)):
132 if _node.args.is_argument(varname): 163 if _node.args.is_argument(varname):
133 return True 164 return True
134 if getattr(_node, 'name', None) == varname: 165 if getattr(_node, 'name', None) == varname:
135 return True 166 return True
136 break 167 break
168 elif isinstance(_node, astroid.ExceptHandler):
169 if isinstance(_node.name, astroid.AssName):
170 ass_node = _node.name
171 if ass_node.name == varname:
172 return True
137 _node = _node.parent 173 _node = _node.parent
138 # possibly multiple statements on the same line using semi colon separator 174 # possibly multiple statements on the same line using semi colon separator
139 stmt = var_node.statement() 175 stmt = var_node.statement()
140 _node = stmt.previous_sibling() 176 _node = stmt.previous_sibling()
141 lineno = stmt.fromlineno 177 lineno = stmt.fromlineno
142 while _node and _node.fromlineno == lineno: 178 while _node and _node.fromlineno == lineno:
143 for ass_node in _node.nodes_of_class(astng.AssName): 179 for ass_node in _node.nodes_of_class(astroid.AssName):
144 if ass_node.name == varname: 180 if ass_node.name == varname:
145 return True 181 return True
146 for imp_node in _node.nodes_of_class( (astng.From, astng.Import)): 182 for imp_node in _node.nodes_of_class((astroid.From, astroid.Import)):
147 if varname in [name[1] or name[0] for name in imp_node.names]: 183 if varname in [name[1] or name[0] for name in imp_node.names]:
148 return True 184 return True
149 _node = _node.previous_sibling() 185 _node = _node.previous_sibling()
150 return False 186 return False
151 187
152 def is_func_default(node): 188 def is_func_default(node):
153 """return true if the given Name node is used in function default argument's 189 """return true if the given Name node is used in function default argument's
154 value 190 value
155 """ 191 """
156 parent = node.scope() 192 parent = node.scope()
157 if isinstance(parent, astng.Function): 193 if isinstance(parent, astroid.Function):
158 for default_node in parent.args.defaults: 194 for default_node in parent.args.defaults:
159 for default_name_node in default_node.nodes_of_class(astng.Name): 195 for default_name_node in default_node.nodes_of_class(astroid.Name):
160 if default_name_node is node: 196 if default_name_node is node:
161 return True 197 return True
162 return False 198 return False
163 199
164 def is_func_decorator(node): 200 def is_func_decorator(node):
165 """return true if the name is used in function decorator""" 201 """return true if the name is used in function decorator"""
166 parent = node.parent 202 parent = node.parent
167 while parent is not None: 203 while parent is not None:
168 if isinstance(parent, astng.Decorators): 204 if isinstance(parent, astroid.Decorators):
169 return True 205 return True
170 if parent.is_statement or isinstance(parent, astng.Lambda): 206 if (parent.is_statement or
207 isinstance(parent, astroid.Lambda) or
208 isinstance(parent, (scoped_nodes.ComprehensionScope,
209 scoped_nodes.ListComp))):
171 break 210 break
172 parent = parent.parent 211 parent = parent.parent
173 return False 212 return False
174 213
175 def is_ancestor_name(frame, node): 214 def is_ancestor_name(frame, node):
176 """return True if `frame` is a astng.Class node with `node` in the 215 """return True if `frame` is a astroid.Class node with `node` in the
177 subtree of its bases attribute 216 subtree of its bases attribute
178 """ 217 """
179 try: 218 try:
180 bases = frame.bases 219 bases = frame.bases
181 except AttributeError: 220 except AttributeError:
182 return False 221 return False
183 for base in bases: 222 for base in bases:
184 if node in base.nodes_of_class(astng.Name): 223 if node in base.nodes_of_class(astroid.Name):
185 return True 224 return True
186 return False 225 return False
187 226
188 def assign_parent(node): 227 def assign_parent(node):
189 """return the higher parent which is not an AssName, Tuple or List node 228 """return the higher parent which is not an AssName, Tuple or List node
190 """ 229 """
191 while node and isinstance(node, (astng.AssName, 230 while node and isinstance(node, (astroid.AssName,
192 astng.Tuple, 231 astroid.Tuple,
193 astng.List)): 232 astroid.List)):
194 node = node.parent 233 node = node.parent
195 return node 234 return node
196 235
197 def overrides_an_abstract_method(class_node, name): 236 def overrides_an_abstract_method(class_node, name):
198 """return True if pnode is a parent of node""" 237 """return True if pnode is a parent of node"""
199 for ancestor in class_node.ancestors(): 238 for ancestor in class_node.ancestors():
200 if name in ancestor and isinstance(ancestor[name], astng.Function) and \ 239 if name in ancestor and isinstance(ancestor[name], astroid.Function) and \
201 ancestor[name].is_abstract(pass_is_abstract=False): 240 ancestor[name].is_abstract(pass_is_abstract=False):
202 return True 241 return True
203 return False 242 return False
204 243
205 def overrides_a_method(class_node, name): 244 def overrides_a_method(class_node, name):
206 """return True if <name> is a method overridden from an ancestor""" 245 """return True if <name> is a method overridden from an ancestor"""
207 for ancestor in class_node.ancestors(): 246 for ancestor in class_node.ancestors():
208 if name in ancestor and isinstance(ancestor[name], astng.Function): 247 if name in ancestor and isinstance(ancestor[name], astroid.Function):
209 return True 248 return True
210 return False 249 return False
211 250
212 PYMETHODS = set(('__new__', '__init__', '__del__', '__hash__', 251 PYMETHODS = set(('__new__', '__init__', '__del__', '__hash__',
213 '__str__', '__repr__', 252 '__str__', '__repr__',
214 '__len__', '__iter__', 253 '__len__', '__iter__',
215 '__delete__', '__get__', '__set__', 254 '__delete__', '__get__', '__set__',
216 '__getitem__', '__setitem__', '__delitem__', '__contains__', 255 '__getitem__', '__setitem__', '__delitem__', '__contains__',
217 '__getattribute__', '__getattr__', '__setattr__', '__delattr__' , 256 '__getattribute__', '__getattr__', '__setattr__', '__delattr__' ,
218 '__call__', 257 '__call__',
219 '__enter__', '__exit__', 258 '__enter__', '__exit__',
220 '__cmp__', '__ge__', '__gt__', '__le__', '__lt__', '__eq__', 259 '__cmp__', '__ge__', '__gt__', '__le__', '__lt__', '__eq__',
221 '__nonzero__', '__neg__', '__invert__', 260 '__nonzero__', '__neg__', '__invert__',
222 '__mul__', '__imul__', '__rmul__', 261 '__mul__', '__imul__', '__rmul__',
223 '__div__', '__idiv__', '__rdiv__', 262 '__div__', '__idiv__', '__rdiv__',
224 '__add__', '__iadd__', '__radd__', 263 '__add__', '__iadd__', '__radd__',
225 '__sub__', '__isub__', '__rsub__', 264 '__sub__', '__isub__', '__rsub__',
226 '__pow__', '__ipow__', '__rpow__', 265 '__pow__', '__ipow__', '__rpow__',
227 '__mod__', '__imod__', '__rmod__', 266 '__mod__', '__imod__', '__rmod__',
228 '__and__', '__iand__', '__rand__', 267 '__and__', '__iand__', '__rand__',
229 '__or__', '__ior__', '__ror__', 268 '__or__', '__ior__', '__ror__',
230 '__xor__', '__ixor__', '__rxor__', 269 '__xor__', '__ixor__', '__rxor__',
231 # XXX To be continued 270 # XXX To be continued
232 )) 271 ))
233 272
234 def check_messages(*messages): 273 def check_messages(*messages):
235 """decorator to store messages that are handled by a checker method""" 274 """decorator to store messages that are handled by a checker method"""
236 275
237 def store_messages(func): 276 def store_messages(func):
238 func.checks_msgs = messages 277 func.checks_msgs = messages
239 return func 278 return func
240 return store_messages 279 return store_messages
241 280
242 class IncompleteFormatString(Exception): 281 class IncompleteFormatString(Exception):
(...skipping 15 matching lines...) Expand all
258 parse error occurs.""" 297 parse error occurs."""
259 keys = set() 298 keys = set()
260 num_args = 0 299 num_args = 0
261 def next_char(i): 300 def next_char(i):
262 i += 1 301 i += 1
263 if i == len(format_string): 302 if i == len(format_string):
264 raise IncompleteFormatString 303 raise IncompleteFormatString
265 return (i, format_string[i]) 304 return (i, format_string[i])
266 i = 0 305 i = 0
267 while i < len(format_string): 306 while i < len(format_string):
268 c = format_string[i] 307 char = format_string[i]
269 if c == '%': 308 if char == '%':
270 i, c = next_char(i) 309 i, char = next_char(i)
271 # Parse the mapping key (optional). 310 # Parse the mapping key (optional).
272 key = None 311 key = None
273 if c == '(': 312 if char == '(':
274 depth = 1 313 depth = 1
275 i, c = next_char(i) 314 i, char = next_char(i)
276 key_start = i 315 key_start = i
277 while depth != 0: 316 while depth != 0:
278 if c == '(': 317 if char == '(':
279 depth += 1 318 depth += 1
280 elif c == ')': 319 elif char == ')':
281 depth -= 1 320 depth -= 1
282 i, c = next_char(i) 321 i, char = next_char(i)
283 key_end = i - 1 322 key_end = i - 1
284 key = format_string[key_start:key_end] 323 key = format_string[key_start:key_end]
285 324
286 # Parse the conversion flags (optional). 325 # Parse the conversion flags (optional).
287 while c in '#0- +': 326 while char in '#0- +':
288 i, c = next_char(i) 327 i, char = next_char(i)
289 # Parse the minimum field width (optional). 328 # Parse the minimum field width (optional).
290 if c == '*': 329 if char == '*':
291 num_args += 1 330 num_args += 1
292 i, c = next_char(i) 331 i, char = next_char(i)
293 else: 332 else:
294 while c in string.digits: 333 while char in string.digits:
295 i, c = next_char(i) 334 i, char = next_char(i)
296 # Parse the precision (optional). 335 # Parse the precision (optional).
297 if c == '.': 336 if char == '.':
298 i, c = next_char(i) 337 i, char = next_char(i)
299 if c == '*': 338 if char == '*':
300 num_args += 1 339 num_args += 1
301 i, c = next_char(i) 340 i, char = next_char(i)
302 else: 341 else:
303 while c in string.digits: 342 while char in string.digits:
304 i, c = next_char(i) 343 i, char = next_char(i)
305 # Parse the length modifier (optional). 344 # Parse the length modifier (optional).
306 if c in 'hlL': 345 if char in 'hlL':
307 i, c = next_char(i) 346 i, char = next_char(i)
308 # Parse the conversion type (mandatory). 347 # Parse the conversion type (mandatory).
309 if c not in 'diouxXeEfFgGcrs%': 348 if PY3K:
349 flags = 'diouxXeEfFgGcrs%a'
350 else:
351 flags = 'diouxXeEfFgGcrs%'
352 if char not in flags:
310 raise UnsupportedFormatCharacter(i) 353 raise UnsupportedFormatCharacter(i)
311 if key: 354 if key:
312 keys.add(key) 355 keys.add(key)
313 elif c != '%': 356 elif char != '%':
314 num_args += 1 357 num_args += 1
315 i += 1 358 i += 1
316 return keys, num_args 359 return keys, num_args
360
361
362 def is_attr_protected(attrname):
363 """return True if attribute name is protected (start with _ and some other
364 details), False otherwise.
365 """
366 return attrname[0] == '_' and not attrname == '_' and not (
367 attrname.startswith('__') and attrname.endswith('__'))
368
369 def node_frame_class(node):
370 """return klass node for a method node (or a staticmethod or a
371 classmethod), return null otherwise
372 """
373 klass = node.frame()
374
375 while klass is not None and not isinstance(klass, astroid.Class):
376 if klass.parent is None:
377 klass = None
378 else:
379 klass = klass.parent.frame()
380
381 return klass
382
383 def is_super_call(expr):
384 """return True if expression node is a function call and if function name
385 is super. Check before that you're in a method.
386 """
387 return (isinstance(expr, astroid.CallFunc) and
388 isinstance(expr.func, astroid.Name) and
389 expr.func.name == 'super')
390
391 def is_attr_private(attrname):
392 """Check that attribute name is private (at least two leading underscores,
393 at most one trailing underscore)
394 """
395 regex = re.compile('^_{2,}.*[^_]+_?$')
396 return regex.match(attrname)
397
398 def get_argument_from_call(callfunc_node, position=None, keyword=None):
399 """Returns the specified argument from a function call.
400
401 :param callfunc_node: Node representing a function call to check.
402 :param int position: position of the argument.
403 :param str keyword: the keyword of the argument.
404
405 :returns: The node representing the argument, None if the argument is not fo und.
406 :raises ValueError: if both position and keyword are None.
407 :raises NoSuchArgumentError: if no argument at the provided position or with
408 the provided keyword.
409 """
410 if position is None and keyword is None:
411 raise ValueError('Must specify at least one of: position or keyword.')
412 try:
413 if position is not None and not isinstance(callfunc_node.args[position], astroid.Keyword):
414 return callfunc_node.args[position]
415 except IndexError, error:
416 raise NoSuchArgumentError(error)
417 if keyword:
418 for arg in callfunc_node.args:
419 if isinstance(arg, astroid.Keyword) and arg.arg == keyword:
420 return arg.value
421 raise NoSuchArgumentError
OLDNEW
« no previous file with comments | « third_party/pylint/checkers/typecheck.py ('k') | third_party/pylint/checkers/variables.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698