OLD | NEW |
1 # copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. | 1 # copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr | 2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
3 # | 3 # |
4 # This file is part of astroid. | 4 # This file is part of astroid. |
5 # | 5 # |
6 # astroid is free software: you can redistribute it and/or modify it | 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 | 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 | 8 # Free Software Foundation, either version 2.1 of the License, or (at your |
9 # option) any later version. | 9 # option) any later version. |
10 # | 10 # |
(...skipping 10 matching lines...) Expand all Loading... |
21 __doctype__ = "restructuredtext en" | 21 __doctype__ = "restructuredtext en" |
22 | 22 |
23 from itertools import chain | 23 from itertools import chain |
24 | 24 |
25 from astroid import nodes | 25 from astroid import nodes |
26 | 26 |
27 from astroid.manager import AstroidManager | 27 from astroid.manager import AstroidManager |
28 from astroid.exceptions import (AstroidError, InferenceError, NoDefault, | 28 from astroid.exceptions import (AstroidError, InferenceError, NoDefault, |
29 NotFoundError, UnresolvableName) | 29 NotFoundError, UnresolvableName) |
30 from astroid.bases import (YES, Instance, InferenceContext, | 30 from astroid.bases import (YES, Instance, InferenceContext, |
31 _infer_stmts, copy_context, path_wrapper, | 31 _infer_stmts, path_wrapper, |
32 raise_if_nothing_infered) | 32 raise_if_nothing_infered) |
33 from astroid.protocols import ( | 33 from astroid.protocols import ( |
34 _arguments_infer_argname, | 34 _arguments_infer_argname, |
35 BIN_OP_METHOD, UNARY_OP_METHOD) | 35 BIN_OP_METHOD, UNARY_OP_METHOD) |
36 | 36 |
37 MANAGER = AstroidManager() | 37 MANAGER = AstroidManager() |
38 | 38 |
39 | 39 |
40 class CallContext(object): | 40 class CallContext(object): |
41 """when inferring a function call, this class is used to remember values | 41 """when inferring a function call, this class is used to remember values |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 if not stmts: | 168 if not stmts: |
169 # Try to see if the name is enclosed in a nested function | 169 # Try to see if the name is enclosed in a nested function |
170 # and use the higher (first function) scope for searching. | 170 # and use the higher (first function) scope for searching. |
171 # TODO: should this be promoted to other nodes as well? | 171 # TODO: should this be promoted to other nodes as well? |
172 parent_function = _higher_function_scope(self.scope()) | 172 parent_function = _higher_function_scope(self.scope()) |
173 if parent_function: | 173 if parent_function: |
174 _, stmts = parent_function.lookup(self.name) | 174 _, stmts = parent_function.lookup(self.name) |
175 | 175 |
176 if not stmts: | 176 if not stmts: |
177 raise UnresolvableName(self.name) | 177 raise UnresolvableName(self.name) |
178 context = context.clone() | 178 return _infer_stmts(stmts, context, frame, self.name) |
179 context.lookupname = self.name | |
180 return _infer_stmts(stmts, context, frame) | |
181 nodes.Name._infer = path_wrapper(infer_name) | 179 nodes.Name._infer = path_wrapper(infer_name) |
182 nodes.AssName.infer_lhs = infer_name # won't work with a path wrapper | 180 nodes.AssName.infer_lhs = infer_name # won't work with a path wrapper |
183 | 181 |
184 | 182 |
185 def infer_callfunc(self, context=None): | 183 def infer_callfunc(self, context=None): |
186 """infer a CallFunc node by trying to guess what the function returns""" | 184 """infer a CallFunc node by trying to guess what the function returns""" |
187 callcontext = context.clone() | 185 if context is None: |
188 callcontext.callcontext = CallContext(self.args, self.starargs, self.kwargs) | 186 context = InferenceContext() |
189 callcontext.boundnode = None | |
190 for callee in self.func.infer(context): | 187 for callee in self.func.infer(context): |
191 if callee is YES: | 188 with context.scope( |
192 yield callee | 189 callcontext=CallContext(self.args, self.starargs, self.kwargs), |
193 continue | 190 boundnode=None, |
194 try: | 191 ): |
195 if hasattr(callee, 'infer_call_result'): | 192 if callee is YES: |
196 for infered in callee.infer_call_result(self, callcontext): | 193 yield callee |
197 yield infered | 194 continue |
198 except InferenceError: | 195 try: |
199 ## XXX log error ? | 196 if hasattr(callee, 'infer_call_result'): |
200 continue | 197 for infered in callee.infer_call_result(self, context): |
| 198 yield infered |
| 199 except InferenceError: |
| 200 ## XXX log error ? |
| 201 continue |
201 nodes.CallFunc._infer = path_wrapper(raise_if_nothing_infered(infer_callfunc)) | 202 nodes.CallFunc._infer = path_wrapper(raise_if_nothing_infered(infer_callfunc)) |
202 | 203 |
203 | 204 |
204 def infer_import(self, context=None, asname=True): | 205 def infer_import(self, context=None, asname=True, lookupname=None): |
205 """infer an Import node: return the imported module/object""" | 206 """infer an Import node: return the imported module/object""" |
206 name = context.lookupname | 207 if lookupname is None: |
207 if name is None: | |
208 raise InferenceError() | 208 raise InferenceError() |
209 if asname: | 209 if asname: |
210 yield self.do_import_module(self.real_name(name)) | 210 yield self.do_import_module(self.real_name(lookupname)) |
211 else: | 211 else: |
212 yield self.do_import_module(name) | 212 yield self.do_import_module(lookupname) |
213 nodes.Import._infer = path_wrapper(infer_import) | 213 nodes.Import._infer = path_wrapper(infer_import) |
214 | 214 |
215 def infer_name_module(self, name): | 215 def infer_name_module(self, name): |
216 context = InferenceContext() | 216 context = InferenceContext() |
217 context.lookupname = name | 217 return self.infer(context, asname=False, lookupname=name) |
218 return self.infer(context, asname=False) | |
219 nodes.Import.infer_name_module = infer_name_module | 218 nodes.Import.infer_name_module = infer_name_module |
220 | 219 |
221 | 220 |
222 def infer_from(self, context=None, asname=True): | 221 def infer_from(self, context=None, asname=True, lookupname=None): |
223 """infer a From nodes: return the imported module/object""" | 222 """infer a From nodes: return the imported module/object""" |
224 name = context.lookupname | 223 if lookupname is None: |
225 if name is None: | |
226 raise InferenceError() | 224 raise InferenceError() |
227 if asname: | 225 if asname: |
228 name = self.real_name(name) | 226 lookupname = self.real_name(lookupname) |
229 module = self.do_import_module() | 227 module = self.do_import_module() |
230 try: | 228 try: |
231 context = copy_context(context) | 229 return _infer_stmts(module.getattr(lookupname, ignore_locals=module is s
elf.root()), context, lookupname=lookupname) |
232 context.lookupname = name | |
233 return _infer_stmts(module.getattr(name, ignore_locals=module is self.ro
ot()), context) | |
234 except NotFoundError: | 230 except NotFoundError: |
235 raise InferenceError(name) | 231 raise InferenceError(lookupname) |
236 nodes.From._infer = path_wrapper(infer_from) | 232 nodes.From._infer = path_wrapper(infer_from) |
237 | 233 |
238 | 234 |
239 def infer_getattr(self, context=None): | 235 def infer_getattr(self, context=None): |
240 """infer a Getattr node by using getattr on the associated object""" | 236 """infer a Getattr node by using getattr on the associated object""" |
241 #context = context.clone() | 237 if not context: |
| 238 context = InferenceContext() |
242 for owner in self.expr.infer(context): | 239 for owner in self.expr.infer(context): |
243 if owner is YES: | 240 if owner is YES: |
244 yield owner | 241 yield owner |
245 continue | 242 continue |
246 try: | 243 try: |
247 context.boundnode = owner | 244 with context.scope(boundnode=owner): |
248 for obj in owner.igetattr(self.attrname, context): | 245 for obj in owner.igetattr(self.attrname, context): |
249 yield obj | 246 yield obj |
250 context.boundnode = None | |
251 except (NotFoundError, InferenceError): | 247 except (NotFoundError, InferenceError): |
252 context.boundnode = None | 248 pass |
253 except AttributeError: | 249 except AttributeError: |
254 # XXX method / function | 250 # XXX method / function |
255 context.boundnode = None | 251 pass |
256 nodes.Getattr._infer = path_wrapper(raise_if_nothing_infered(infer_getattr)) | 252 nodes.Getattr._infer = path_wrapper(raise_if_nothing_infered(infer_getattr)) |
257 nodes.AssAttr.infer_lhs = raise_if_nothing_infered(infer_getattr) # # won't work
with a path wrapper | 253 nodes.AssAttr.infer_lhs = raise_if_nothing_infered(infer_getattr) # # won't work
with a path wrapper |
258 | 254 |
259 | 255 |
260 def infer_global(self, context=None): | 256 def infer_global(self, context=None, lookupname=None): |
261 if context.lookupname is None: | 257 if lookupname is None: |
262 raise InferenceError() | 258 raise InferenceError() |
263 try: | 259 try: |
264 return _infer_stmts(self.root().getattr(context.lookupname), context) | 260 return _infer_stmts(self.root().getattr(lookupname), context) |
265 except NotFoundError: | 261 except NotFoundError: |
266 raise InferenceError() | 262 raise InferenceError() |
267 nodes.Global._infer = path_wrapper(infer_global) | 263 nodes.Global._infer = path_wrapper(infer_global) |
268 | 264 |
269 | 265 |
270 def infer_subscript(self, context=None): | 266 def infer_subscript(self, context=None): |
271 """infer simple subscription such as [1,2,3][0] or (1,2,3)[-1]""" | 267 """infer simple subscription such as [1,2,3][0] or (1,2,3)[-1]""" |
272 value = self.value.infer(context).next() | 268 value = next(self.value.infer(context)) |
273 if value is YES: | 269 if value is YES: |
274 yield YES | 270 yield YES |
275 return | 271 return |
276 | 272 |
277 index = self.slice.infer(context).next() | 273 index = next(self.slice.infer(context)) |
278 if index is YES: | 274 if index is YES: |
279 yield YES | 275 yield YES |
280 return | 276 return |
281 | 277 |
282 if isinstance(index, nodes.Const): | 278 if isinstance(index, nodes.Const): |
283 try: | 279 try: |
284 assigned = value.getitem(index.value, context) | 280 assigned = value.getitem(index.value, context) |
285 except AttributeError: | 281 except AttributeError: |
286 raise InferenceError() | 282 raise InferenceError() |
287 except (IndexError, TypeError): | 283 except (IndexError, TypeError): |
288 yield YES | 284 yield YES |
289 return | 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 |
290 for infered in assigned.infer(context): | 292 for infered in assigned.infer(context): |
291 yield infered | 293 yield infered |
292 else: | 294 else: |
293 raise InferenceError() | 295 raise InferenceError() |
294 nodes.Subscript._infer = path_wrapper(infer_subscript) | 296 nodes.Subscript._infer = path_wrapper(infer_subscript) |
295 nodes.Subscript.infer_lhs = raise_if_nothing_infered(infer_subscript) | 297 nodes.Subscript.infer_lhs = raise_if_nothing_infered(infer_subscript) |
296 | 298 |
297 def infer_unaryop(self, context=None): | 299 def infer_unaryop(self, context=None): |
298 for operand in self.operand.infer(context): | 300 for operand in self.operand.infer(context): |
299 try: | 301 try: |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 for lhs in self.left.infer(context): | 342 for lhs in self.left.infer(context): |
341 for val in _infer_binop(self.op, lhs, self.right, context, failures): | 343 for val in _infer_binop(self.op, lhs, self.right, context, failures): |
342 yield val | 344 yield val |
343 for lhs in failures: | 345 for lhs in failures: |
344 for rhs in self.right.infer(context): | 346 for rhs in self.right.infer(context): |
345 for val in _infer_binop(self.op, rhs, lhs, context): | 347 for val in _infer_binop(self.op, rhs, lhs, context): |
346 yield val | 348 yield val |
347 nodes.BinOp._infer = path_wrapper(infer_binop) | 349 nodes.BinOp._infer = path_wrapper(infer_binop) |
348 | 350 |
349 | 351 |
350 def infer_arguments(self, context=None): | 352 def infer_arguments(self, context=None, lookupname=None): |
351 name = context.lookupname | 353 if lookupname is None: |
352 if name is None: | |
353 raise InferenceError() | 354 raise InferenceError() |
354 return _arguments_infer_argname(self, name, context) | 355 return _arguments_infer_argname(self, lookupname, context) |
355 nodes.Arguments._infer = infer_arguments | 356 nodes.Arguments._infer = infer_arguments |
356 | 357 |
357 | 358 |
358 def infer_ass(self, context=None): | 359 def infer_ass(self, context=None): |
359 """infer a AssName/AssAttr: need to inspect the RHS part of the | 360 """infer a AssName/AssAttr: need to inspect the RHS part of the |
360 assign node | 361 assign node |
361 """ | 362 """ |
362 stmt = self.statement() | 363 stmt = self.statement() |
363 if isinstance(stmt, nodes.AugAssign): | 364 if isinstance(stmt, nodes.AugAssign): |
364 return stmt.infer(context) | 365 return stmt.infer(context) |
(...skipping 26 matching lines...) Expand all Loading... |
391 context=context): | 392 context=context): |
392 yield infered | 393 yield infered |
393 except AstroidError: | 394 except AstroidError: |
394 yield YES | 395 yield YES |
395 nodes.EmptyNode._infer = path_wrapper(infer_empty_node) | 396 nodes.EmptyNode._infer = path_wrapper(infer_empty_node) |
396 | 397 |
397 | 398 |
398 def infer_index(self, context=None): | 399 def infer_index(self, context=None): |
399 return self.value.infer(context) | 400 return self.value.infer(context) |
400 nodes.Index._infer = infer_index | 401 nodes.Index._infer = infer_index |
OLD | NEW |