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

Side by Side Diff: third_party/logilab/logilab/astroid/inference.py

Issue 1920403002: [content/test/gpu] Run pylint check of gpu tests in unittest instead of PRESUBMIT (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update path to LICENSE.txt of logilab/README.chromium Created 4 years, 7 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
OLDNEW
(Empty)
1 # copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
3 #
4 # This file is part of astroid.
5 #
6 # astroid is free software: you can redistribute it and/or modify it
7 # under the terms of the GNU Lesser General Public License as published by the
8 # Free Software Foundation, either version 2.1 of the License, or (at your
9 # option) any later version.
10 #
11 # astroid is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
14 # for more details.
15 #
16 # You should have received a copy of the GNU Lesser General Public License along
17 # with astroid. If not, see <http://www.gnu.org/licenses/>.
18 """this module contains a set of functions to handle inference on astroid trees
19 """
20
21 __doctype__ = "restructuredtext en"
22
23 from itertools import chain
24
25 from astroid import nodes
26
27 from astroid.manager import AstroidManager
28 from astroid.exceptions import (AstroidError, InferenceError, NoDefault,
29 NotFoundError, UnresolvableName)
30 from astroid.bases import (YES, Instance, InferenceContext,
31 _infer_stmts, path_wrapper,
32 raise_if_nothing_infered)
33 from astroid.protocols import (
34 _arguments_infer_argname,
35 BIN_OP_METHOD, UNARY_OP_METHOD)
36
37 MANAGER = AstroidManager()
38
39
40 class CallContext(object):
41 """when inferring a function call, this class is used to remember values
42 given as argument
43 """
44 def __init__(self, args, starargs, dstarargs):
45 self.args = []
46 self.nargs = {}
47 for arg in args:
48 if isinstance(arg, nodes.Keyword):
49 self.nargs[arg.arg] = arg.value
50 else:
51 self.args.append(arg)
52 self.starargs = starargs
53 self.dstarargs = dstarargs
54
55 def infer_argument(self, funcnode, name, context):
56 """infer a function argument value according to the call context"""
57 # 1. search in named keywords
58 try:
59 return self.nargs[name].infer(context)
60 except KeyError:
61 # Function.args.args can be None in astroid (means that we don't hav e
62 # information on argnames)
63 argindex = funcnode.args.find_argname(name)[0]
64 if argindex is not None:
65 # 2. first argument of instance/class method
66 if argindex == 0 and funcnode.type in ('method', 'classmethod'):
67 if context.boundnode is not None:
68 boundnode = context.boundnode
69 else:
70 # XXX can do better ?
71 boundnode = funcnode.parent.frame()
72 if funcnode.type == 'method':
73 if not isinstance(boundnode, Instance):
74 boundnode = Instance(boundnode)
75 return iter((boundnode,))
76 if funcnode.type == 'classmethod':
77 return iter((boundnode,))
78 # if we have a method, extract one position
79 # from the index, so we'll take in account
80 # the extra parameter represented by `self` or `cls`
81 if funcnode.type in ('method', 'classmethod'):
82 argindex -= 1
83 # 2. search arg index
84 try:
85 return self.args[argindex].infer(context)
86 except IndexError:
87 pass
88 # 3. search in *args (.starargs)
89 if self.starargs is not None:
90 its = []
91 for infered in self.starargs.infer(context):
92 if infered is YES:
93 its.append((YES,))
94 continue
95 try:
96 its.append(infered.getitem(argindex, context).infer( context))
97 except (InferenceError, AttributeError):
98 its.append((YES,))
99 except (IndexError, TypeError):
100 continue
101 if its:
102 return chain(*its)
103 # 4. XXX search in **kwargs (.dstarargs)
104 if self.dstarargs is not None:
105 its = []
106 for infered in self.dstarargs.infer(context):
107 if infered is YES:
108 its.append((YES,))
109 continue
110 try:
111 its.append(infered.getitem(name, context).infer(context))
112 except (InferenceError, AttributeError):
113 its.append((YES,))
114 except (IndexError, TypeError):
115 continue
116 if its:
117 return chain(*its)
118 # 5. */** argument, (Tuple or Dict)
119 if name == funcnode.args.vararg:
120 return iter((nodes.const_factory(())))
121 if name == funcnode.args.kwarg:
122 return iter((nodes.const_factory({})))
123 # 6. return default value if any
124 try:
125 return funcnode.args.default_value(name).infer(context)
126 except NoDefault:
127 raise InferenceError(name)
128
129
130 # .infer method ###############################################################
131
132
133 def infer_end(self, context=None):
134 """inference's end for node such as Module, Class, Function, Const...
135 """
136 yield self
137 nodes.Module._infer = infer_end
138 nodes.Class._infer = infer_end
139 nodes.Function._infer = infer_end
140 nodes.Lambda._infer = infer_end
141 nodes.Const._infer = infer_end
142 nodes.List._infer = infer_end
143 nodes.Tuple._infer = infer_end
144 nodes.Dict._infer = infer_end
145 nodes.Set._infer = infer_end
146
147 def _higher_function_scope(node):
148 """ Search for the first function which encloses the given
149 scope. This can be used for looking up in that function's
150 scope, in case looking up in a lower scope for a particular
151 name fails.
152
153 :param node: A scope node.
154 :returns:
155 ``None``, if no parent function scope was found,
156 otherwise an instance of :class:`astroid.scoped_nodes.Function`,
157 which encloses the given node.
158 """
159 current = node
160 while current.parent and not isinstance(current.parent, nodes.Function):
161 current = current.parent
162 if current and current.parent:
163 return current.parent
164
165 def infer_name(self, context=None):
166 """infer a Name: use name lookup rules"""
167 frame, stmts = self.lookup(self.name)
168 if not stmts:
169 # Try to see if the name is enclosed in a nested function
170 # and use the higher (first function) scope for searching.
171 # TODO: should this be promoted to other nodes as well?
172 parent_function = _higher_function_scope(self.scope())
173 if parent_function:
174 _, stmts = parent_function.lookup(self.name)
175
176 if not stmts:
177 raise UnresolvableName(self.name)
178 return _infer_stmts(stmts, context, frame, self.name)
179 nodes.Name._infer = path_wrapper(infer_name)
180 nodes.AssName.infer_lhs = infer_name # won't work with a path wrapper
181
182
183 def infer_callfunc(self, context=None):
184 """infer a CallFunc node by trying to guess what the function returns"""
185 if context is None:
186 context = InferenceContext()
187 for callee in self.func.infer(context):
188 with context.scope(
189 callcontext=CallContext(self.args, self.starargs, self.kwargs),
190 boundnode=None,
191 ):
192 if callee is YES:
193 yield callee
194 continue
195 try:
196 if hasattr(callee, 'infer_call_result'):
197 for infered in callee.infer_call_result(self, context):
198 yield infered
199 except InferenceError:
200 ## XXX log error ?
201 continue
202 nodes.CallFunc._infer = path_wrapper(raise_if_nothing_infered(infer_callfunc))
203
204
205 def infer_import(self, context=None, asname=True, lookupname=None):
206 """infer an Import node: return the imported module/object"""
207 if lookupname is None:
208 raise InferenceError()
209 if asname:
210 yield self.do_import_module(self.real_name(lookupname))
211 else:
212 yield self.do_import_module(lookupname)
213 nodes.Import._infer = path_wrapper(infer_import)
214
215 def infer_name_module(self, name):
216 context = InferenceContext()
217 return self.infer(context, asname=False, lookupname=name)
218 nodes.Import.infer_name_module = infer_name_module
219
220
221 def infer_from(self, context=None, asname=True, lookupname=None):
222 """infer a From nodes: return the imported module/object"""
223 if lookupname is None:
224 raise InferenceError()
225 if asname:
226 lookupname = self.real_name(lookupname)
227 module = self.do_import_module()
228 try:
229 return _infer_stmts(module.getattr(lookupname, ignore_locals=module is s elf.root()), context, lookupname=lookupname)
230 except NotFoundError:
231 raise InferenceError(lookupname)
232 nodes.From._infer = path_wrapper(infer_from)
233
234
235 def infer_getattr(self, context=None):
236 """infer a Getattr node by using getattr on the associated object"""
237 if not context:
238 context = InferenceContext()
239 for owner in self.expr.infer(context):
240 if owner is YES:
241 yield owner
242 continue
243 try:
244 with context.scope(boundnode=owner):
245 for obj in owner.igetattr(self.attrname, context):
246 yield obj
247 except (NotFoundError, InferenceError):
248 pass
249 except AttributeError:
250 # XXX method / function
251 pass
252 nodes.Getattr._infer = path_wrapper(raise_if_nothing_infered(infer_getattr))
253 nodes.AssAttr.infer_lhs = raise_if_nothing_infered(infer_getattr) # # won't work with a path wrapper
254
255
256 def infer_global(self, context=None, lookupname=None):
257 if lookupname is None:
258 raise InferenceError()
259 try:
260 return _infer_stmts(self.root().getattr(lookupname), context)
261 except NotFoundError:
262 raise InferenceError()
263 nodes.Global._infer = path_wrapper(infer_global)
264
265
266 def infer_subscript(self, context=None):
267 """infer simple subscription such as [1,2,3][0] or (1,2,3)[-1]"""
268 value = next(self.value.infer(context))
269 if value is YES:
270 yield YES
271 return
272
273 index = next(self.slice.infer(context))
274 if index is YES:
275 yield YES
276 return
277
278 if isinstance(index, nodes.Const):
279 try:
280 assigned = value.getitem(index.value, context)
281 except AttributeError:
282 raise InferenceError()
283 except (IndexError, TypeError):
284 yield YES
285 return
286
287 # Prevent inferring if the infered subscript
288 # is the same as the original subscripted object.
289 if self is assigned:
290 yield YES
291 return
292 for infered in assigned.infer(context):
293 yield infered
294 else:
295 raise InferenceError()
296 nodes.Subscript._infer = path_wrapper(infer_subscript)
297 nodes.Subscript.infer_lhs = raise_if_nothing_infered(infer_subscript)
298
299 def infer_unaryop(self, context=None):
300 for operand in self.operand.infer(context):
301 try:
302 yield operand.infer_unary_op(self.op)
303 except TypeError:
304 continue
305 except AttributeError:
306 meth = UNARY_OP_METHOD[self.op]
307 if meth is None:
308 yield YES
309 else:
310 try:
311 # XXX just suppose if the type implement meth, returned type
312 # will be the same
313 operand.getattr(meth)
314 yield operand
315 except GeneratorExit:
316 raise
317 except:
318 yield YES
319 nodes.UnaryOp._infer = path_wrapper(infer_unaryop)
320
321 def _infer_binop(operator, operand1, operand2, context, failures=None):
322 if operand1 is YES:
323 yield operand1
324 return
325 try:
326 for valnode in operand1.infer_binary_op(operator, operand2, context):
327 yield valnode
328 except AttributeError:
329 try:
330 # XXX just suppose if the type implement meth, returned type
331 # will be the same
332 operand1.getattr(BIN_OP_METHOD[operator])
333 yield operand1
334 except:
335 if failures is None:
336 yield YES
337 else:
338 failures.append(operand1)
339
340 def infer_binop(self, context=None):
341 failures = []
342 for lhs in self.left.infer(context):
343 for val in _infer_binop(self.op, lhs, self.right, context, failures):
344 yield val
345 for lhs in failures:
346 for rhs in self.right.infer(context):
347 for val in _infer_binop(self.op, rhs, lhs, context):
348 yield val
349 nodes.BinOp._infer = path_wrapper(infer_binop)
350
351
352 def infer_arguments(self, context=None, lookupname=None):
353 if lookupname is None:
354 raise InferenceError()
355 return _arguments_infer_argname(self, lookupname, context)
356 nodes.Arguments._infer = infer_arguments
357
358
359 def infer_ass(self, context=None):
360 """infer a AssName/AssAttr: need to inspect the RHS part of the
361 assign node
362 """
363 stmt = self.statement()
364 if isinstance(stmt, nodes.AugAssign):
365 return stmt.infer(context)
366 stmts = list(self.assigned_stmts(context=context))
367 return _infer_stmts(stmts, context)
368 nodes.AssName._infer = path_wrapper(infer_ass)
369 nodes.AssAttr._infer = path_wrapper(infer_ass)
370
371 def infer_augassign(self, context=None):
372 failures = []
373 for lhs in self.target.infer_lhs(context):
374 for val in _infer_binop(self.op, lhs, self.value, context, failures):
375 yield val
376 for lhs in failures:
377 for rhs in self.value.infer(context):
378 for val in _infer_binop(self.op, rhs, lhs, context):
379 yield val
380 nodes.AugAssign._infer = path_wrapper(infer_augassign)
381
382
383 # no infer method on DelName and DelAttr (expected InferenceError)
384
385
386 def infer_empty_node(self, context=None):
387 if not self.has_underlying_object():
388 yield YES
389 else:
390 try:
391 for infered in MANAGER.infer_ast_from_something(self.object,
392 context=context):
393 yield infered
394 except AstroidError:
395 yield YES
396 nodes.EmptyNode._infer = path_wrapper(infer_empty_node)
397
398
399 def infer_index(self, context=None):
400 return self.value.infer(context)
401 nodes.Index._infer = infer_index
OLDNEW
« no previous file with comments | « third_party/logilab/logilab/astroid/exceptions.py ('k') | third_party/logilab/logilab/astroid/inspector.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698