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

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

Issue 10447014: Add pylint to depot_tools. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Fix unittests. Created 8 years, 6 months 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
(Empty)
1 # pylint: disable=W0611
2 #
3 # Copyright (c) 2003-2010 LOGILAB S.A. (Paris, FRANCE).
4 # http://www.logilab.fr/ -- mailto:contact@logilab.fr
5 #
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
8 # Foundation; either version 2 of the License, or (at your option) any later
9 # version.
10 #
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
13 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 #
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.,
17 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 """some functions that may be useful for various checkers
19 """
20
21 import string
22 from logilab import astng
23 from logilab.common.compat import builtins
24 BUILTINS_NAME = builtins.__name__
25
26 COMP_NODE_TYPES = astng.ListComp, astng.SetComp, astng.DictComp, astng.GenExpr
27
28 def is_inside_except(node):
29 """Returns true if node is directly inside an exception handler"""
30 return isinstance(node.parent, astng.ExceptHandler)
31
32
33 def clobber_in_except(node):
34 """Checks if an assignment node in an except handler clobbers an existing
35 variable.
36
37 Returns (True, args for W0623) if assignment clobbers an existing variable,
38 (False, None) otherwise.
39 """
40 if isinstance(node, astng.AssAttr):
41 return (True, (node.attrname, 'object %r' % (node.expr.name,)))
42 elif node is not None:
43 name = node.name
44 if is_builtin(name):
45 return (True, (name, 'builtins'))
46 else:
47 scope, stmts = node.lookup(name)
48 if (stmts and
49 not isinstance(stmts[0].ass_type(),
50 (astng.Assign, astng.AugAssign, astng.ExceptHandl er))):
51 return (True, (name, 'outer scope (line %i)' % (stmts[0].lineno, )))
52 return (False, None)
53
54
55 def safe_infer(node):
56 """return the inferred value for the given node.
57 Return None if inference failed or if there is some ambiguity (more than
58 one node has been inferred)
59 """
60 try:
61 inferit = node.infer()
62 value = inferit.next()
63 except astng.InferenceError:
64 return
65 try:
66 inferit.next()
67 return # None if there is ambiguity on the inferred node
68 except StopIteration:
69 return value
70
71 def is_super(node):
72 """return True if the node is referencing the "super" builtin function
73 """
74 if getattr(node, 'name', None) == 'super' and \
75 node.root().name == BUILTINS_NAME:
76 return True
77 return False
78
79 def is_error(node):
80 """return true if the function does nothing but raising an exception"""
81 for child_node in node.get_children():
82 if isinstance(child_node, astng.Raise):
83 return True
84 return False
85
86 def is_raising(body):
87 """return true if the given statement node raise an exception"""
88 for node in body:
89 if isinstance(node, astng.Raise):
90 return True
91 return False
92
93 def is_empty(body):
94 """return true if the given node does nothing but 'pass'"""
95 return len(body) == 1 and isinstance(body[0], astng.Pass)
96
97 builtins = __builtins__.copy()
98 SPECIAL_BUILTINS = ('__builtins__',) # '__path__', '__file__')
99
100 def is_builtin(name): # was is_native_builtin
101 """return true if <name> could be considered as a builtin defined by python
102 """
103 if name in builtins:
104 return True
105 if name in SPECIAL_BUILTINS:
106 return True
107 return False
108
109 def is_defined_before(var_node):
110 """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
112 node on the same line (statement_defining ; statement_using)
113 """
114 varname = var_node.name
115 _node = var_node.parent
116 while _node:
117 if isinstance(_node, COMP_NODE_TYPES):
118 for ass_node in _node.nodes_of_class(astng.AssName):
119 if ass_node.name == varname:
120 return True
121 elif isinstance(_node, astng.For):
122 for ass_node in _node.target.nodes_of_class(astng.AssName):
123 if ass_node.name == varname:
124 return True
125 elif isinstance(_node, astng.With):
126 if _node.vars is None:
127 # quickfix : case in which 'with' is used without 'as'
128 return False
129 if _node.vars.name == varname:
130 return True
131 elif isinstance(_node, (astng.Lambda, astng.Function)):
132 if _node.args.is_argument(varname):
133 return True
134 if getattr(_node, 'name', None) == varname:
135 return True
136 break
137 _node = _node.parent
138 # possibly multiple statements on the same line using semi colon separator
139 stmt = var_node.statement()
140 _node = stmt.previous_sibling()
141 lineno = stmt.fromlineno
142 while _node and _node.fromlineno == lineno:
143 for ass_node in _node.nodes_of_class(astng.AssName):
144 if ass_node.name == varname:
145 return True
146 for imp_node in _node.nodes_of_class( (astng.From, astng.Import)):
147 if varname in [name[1] or name[0] for name in imp_node.names]:
148 return True
149 _node = _node.previous_sibling()
150 return False
151
152 def is_func_default(node):
153 """return true if the given Name node is used in function default argument's
154 value
155 """
156 parent = node.scope()
157 if isinstance(parent, astng.Function):
158 for default_node in parent.args.defaults:
159 for default_name_node in default_node.nodes_of_class(astng.Name):
160 if default_name_node is node:
161 return True
162 return False
163
164 def is_func_decorator(node):
165 """return true if the name is used in function decorator"""
166 parent = node.parent
167 while parent is not None:
168 if isinstance(parent, astng.Decorators):
169 return True
170 if parent.is_statement or isinstance(parent, astng.Lambda):
171 break
172 parent = parent.parent
173 return False
174
175 def is_ancestor_name(frame, node):
176 """return True if `frame` is a astng.Class node with `node` in the
177 subtree of its bases attribute
178 """
179 try:
180 bases = frame.bases
181 except AttributeError:
182 return False
183 for base in bases:
184 if node in base.nodes_of_class(astng.Name):
185 return True
186 return False
187
188 def assign_parent(node):
189 """return the higher parent which is not an AssName, Tuple or List node
190 """
191 while node and isinstance(node, (astng.AssName,
192 astng.Tuple,
193 astng.List)):
194 node = node.parent
195 return node
196
197 def overrides_an_abstract_method(class_node, name):
198 """return True if pnode is a parent of node"""
199 for ancestor in class_node.ancestors():
200 if name in ancestor and isinstance(ancestor[name], astng.Function) and \
201 ancestor[name].is_abstract(pass_is_abstract=False):
202 return True
203 return False
204
205 def overrides_a_method(class_node, name):
206 """return True if <name> is a method overridden from an ancestor"""
207 for ancestor in class_node.ancestors():
208 if name in ancestor and isinstance(ancestor[name], astng.Function):
209 return True
210 return False
211
212 PYMETHODS = set(('__new__', '__init__', '__del__', '__hash__',
213 '__str__', '__repr__',
214 '__len__', '__iter__',
215 '__delete__', '__get__', '__set__',
216 '__getitem__', '__setitem__', '__delitem__', '__contains__',
217 '__getattribute__', '__getattr__', '__setattr__', '__delattr__' ,
218 '__call__',
219 '__enter__', '__exit__',
220 '__cmp__', '__ge__', '__gt__', '__le__', '__lt__', '__eq__',
221 '__nonzero__', '__neg__', '__invert__',
222 '__mul__', '__imul__', '__rmul__',
223 '__div__', '__idiv__', '__rdiv__',
224 '__add__', '__iadd__', '__radd__',
225 '__sub__', '__isub__', '__rsub__',
226 '__pow__', '__ipow__', '__rpow__',
227 '__mod__', '__imod__', '__rmod__',
228 '__and__', '__iand__', '__rand__',
229 '__or__', '__ior__', '__ror__',
230 '__xor__', '__ixor__', '__rxor__',
231 # XXX To be continued
232 ))
233
234 def check_messages(*messages):
235 """decorator to store messages that are handled by a checker method"""
236
237 def store_messages(func):
238 func.checks_msgs = messages
239 return func
240 return store_messages
241
242 class IncompleteFormatString(Exception):
243 """A format string ended in the middle of a format specifier."""
244 pass
245
246 class UnsupportedFormatCharacter(Exception):
247 """A format character in a format string is not one of the supported
248 format characters."""
249 def __init__(self, index):
250 Exception.__init__(self, index)
251 self.index = index
252
253 def parse_format_string(format_string):
254 """Parses a format string, returning a tuple of (keys, num_args), where keys
255 is the set of mapping keys in the format string, and num_args is the number
256 of arguments required by the format string. Raises
257 IncompleteFormatString or UnsupportedFormatCharacter if a
258 parse error occurs."""
259 keys = set()
260 num_args = 0
261 def next_char(i):
262 i += 1
263 if i == len(format_string):
264 raise IncompleteFormatString
265 return (i, format_string[i])
266 i = 0
267 while i < len(format_string):
268 c = format_string[i]
269 if c == '%':
270 i, c = next_char(i)
271 # Parse the mapping key (optional).
272 key = None
273 if c == '(':
274 depth = 1
275 i, c = next_char(i)
276 key_start = i
277 while depth != 0:
278 if c == '(':
279 depth += 1
280 elif c == ')':
281 depth -= 1
282 i, c = next_char(i)
283 key_end = i - 1
284 key = format_string[key_start:key_end]
285
286 # Parse the conversion flags (optional).
287 while c in '#0- +':
288 i, c = next_char(i)
289 # Parse the minimum field width (optional).
290 if c == '*':
291 num_args += 1
292 i, c = next_char(i)
293 else:
294 while c in string.digits:
295 i, c = next_char(i)
296 # Parse the precision (optional).
297 if c == '.':
298 i, c = next_char(i)
299 if c == '*':
300 num_args += 1
301 i, c = next_char(i)
302 else:
303 while c in string.digits:
304 i, c = next_char(i)
305 # Parse the length modifier (optional).
306 if c in 'hlL':
307 i, c = next_char(i)
308 # Parse the conversion type (mandatory).
309 if c not in 'diouxXeEfFgGcrs%':
310 raise UnsupportedFormatCharacter(i)
311 if key:
312 keys.add(key)
313 elif c != '%':
314 num_args += 1
315 i += 1
316 return keys, num_args
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