diff options
author | Torsten Marek <shlomme@gmail.com> | 2014-11-08 23:47:14 +0100 |
---|---|---|
committer | Torsten Marek <shlomme@gmail.com> | 2014-11-08 23:47:14 +0100 |
commit | 477b5ee2a3d0594504ca9fc2fe0f0f9cbeccd01b (patch) | |
tree | 532231f1ecb5df4b4af6d3c12c91b684c8629673 /inference.py | |
parent | e10cd03c08aaf46308504330b180107e421350d6 (diff) | |
download | astroid-git-477b5ee2a3d0594504ca9fc2fe0f0f9cbeccd01b.tar.gz |
Move all astroid modules into a its own directory, which is now the package.
python setup.py develop now works.
Diffstat (limited to 'inference.py')
-rw-r--r-- | inference.py | 395 |
1 files changed, 0 insertions, 395 deletions
diff --git a/inference.py b/inference.py deleted file mode 100644 index 6cd4b787..00000000 --- a/inference.py +++ /dev/null @@ -1,395 +0,0 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr -# -# This file is part of astroid. -# -# astroid is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 2.1 of the License, or (at your -# option) any later version. -# -# astroid is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License -# for more details. -# -# You should have received a copy of the GNU Lesser General Public License along -# with astroid. If not, see <http://www.gnu.org/licenses/>. -"""this module contains a set of functions to handle inference on astroid trees -""" - -__doctype__ = "restructuredtext en" - -from itertools import chain - -from astroid import nodes - -from astroid.manager import AstroidManager -from astroid.exceptions import (AstroidError, InferenceError, NoDefault, - NotFoundError, UnresolvableName) -from astroid.bases import (YES, Instance, InferenceContext, - _infer_stmts, path_wrapper, - raise_if_nothing_infered) -from astroid.protocols import ( - _arguments_infer_argname, - BIN_OP_METHOD, UNARY_OP_METHOD) - -MANAGER = AstroidManager() - - -class CallContext(object): - """when inferring a function call, this class is used to remember values - given as argument - """ - def __init__(self, args, starargs, dstarargs): - self.args = [] - self.nargs = {} - for arg in args: - if isinstance(arg, nodes.Keyword): - self.nargs[arg.arg] = arg.value - else: - self.args.append(arg) - self.starargs = starargs - self.dstarargs = dstarargs - - def infer_argument(self, funcnode, name, context): - """infer a function argument value according to the call context""" - # 1. search in named keywords - try: - return self.nargs[name].infer(context) - except KeyError: - # Function.args.args can be None in astroid (means that we don't have - # information on argnames) - argindex = funcnode.args.find_argname(name)[0] - if argindex is not None: - # 2. first argument of instance/class method - if argindex == 0 and funcnode.type in ('method', 'classmethod'): - if context.boundnode is not None: - boundnode = context.boundnode - else: - # XXX can do better ? - boundnode = funcnode.parent.frame() - if funcnode.type == 'method': - if not isinstance(boundnode, Instance): - boundnode = Instance(boundnode) - return iter((boundnode,)) - if funcnode.type == 'classmethod': - return iter((boundnode,)) - # if we have a method, extract one position - # from the index, so we'll take in account - # the extra parameter represented by `self` or `cls` - if funcnode.type in ('method', 'classmethod'): - argindex -= 1 - # 2. search arg index - try: - return self.args[argindex].infer(context) - except IndexError: - pass - # 3. search in *args (.starargs) - if self.starargs is not None: - its = [] - for infered in self.starargs.infer(context): - if infered is YES: - its.append((YES,)) - continue - try: - its.append(infered.getitem(argindex, context).infer(context)) - except (InferenceError, AttributeError): - its.append((YES,)) - except (IndexError, TypeError): - continue - if its: - return chain(*its) - # 4. XXX search in **kwargs (.dstarargs) - if self.dstarargs is not None: - its = [] - for infered in self.dstarargs.infer(context): - if infered is YES: - its.append((YES,)) - continue - try: - its.append(infered.getitem(name, context).infer(context)) - except (InferenceError, AttributeError): - its.append((YES,)) - except (IndexError, TypeError): - continue - if its: - return chain(*its) - # 5. */** argument, (Tuple or Dict) - if name == funcnode.args.vararg: - return iter((nodes.const_factory(()))) - if name == funcnode.args.kwarg: - return iter((nodes.const_factory({}))) - # 6. return default value if any - try: - return funcnode.args.default_value(name).infer(context) - except NoDefault: - raise InferenceError(name) - - -# .infer method ############################################################### - - -def infer_end(self, context=None): - """inference's end for node such as Module, Class, Function, Const... - """ - yield self -nodes.Module._infer = infer_end -nodes.Class._infer = infer_end -nodes.Function._infer = infer_end -nodes.Lambda._infer = infer_end -nodes.Const._infer = infer_end -nodes.List._infer = infer_end -nodes.Tuple._infer = infer_end -nodes.Dict._infer = infer_end -nodes.Set._infer = infer_end - -def _higher_function_scope(node): - """ Search for the first function which encloses the given - scope. This can be used for looking up in that function's - scope, in case looking up in a lower scope for a particular - name fails. - - :param node: A scope node. - :returns: - ``None``, if no parent function scope was found, - otherwise an instance of :class:`astroid.scoped_nodes.Function`, - which encloses the given node. - """ - current = node - while current.parent and not isinstance(current.parent, nodes.Function): - current = current.parent - if current and current.parent: - return current.parent - -def infer_name(self, context=None): - """infer a Name: use name lookup rules""" - frame, stmts = self.lookup(self.name) - if not stmts: - # Try to see if the name is enclosed in a nested function - # and use the higher (first function) scope for searching. - # TODO: should this be promoted to other nodes as well? - parent_function = _higher_function_scope(self.scope()) - if parent_function: - _, stmts = parent_function.lookup(self.name) - - if not stmts: - raise UnresolvableName(self.name) - return _infer_stmts(stmts, context, frame, self.name) -nodes.Name._infer = path_wrapper(infer_name) -nodes.AssName.infer_lhs = infer_name # won't work with a path wrapper - - -def infer_callfunc(self, context=None): - """infer a CallFunc node by trying to guess what the function returns""" - if context is None: - context = InferenceContext() - for callee in self.func.infer(context): - with context.scope( - callcontext=CallContext(self.args, self.starargs, self.kwargs), - boundnode=None, - ): - if callee is YES: - yield callee - continue - try: - if hasattr(callee, 'infer_call_result'): - for infered in callee.infer_call_result(self, context): - yield infered - except InferenceError: - ## XXX log error ? - continue -nodes.CallFunc._infer = path_wrapper(raise_if_nothing_infered(infer_callfunc)) - - -def infer_import(self, context=None, asname=True, lookupname=None): - """infer an Import node: return the imported module/object""" - if lookupname is None: - raise InferenceError() - if asname: - yield self.do_import_module(self.real_name(lookupname)) - else: - yield self.do_import_module(lookupname) -nodes.Import._infer = path_wrapper(infer_import) - -def infer_name_module(self, name): - context = InferenceContext() - return self.infer(context, asname=False, lookupname=name) -nodes.Import.infer_name_module = infer_name_module - - -def infer_from(self, context=None, asname=True, lookupname=None): - """infer a From nodes: return the imported module/object""" - if lookupname is None: - raise InferenceError() - if asname: - lookupname = self.real_name(lookupname) - module = self.do_import_module() - try: - return _infer_stmts(module.getattr(lookupname, ignore_locals=module is self.root()), context, lookupname=lookupname) - except NotFoundError: - raise InferenceError(lookupname) -nodes.From._infer = path_wrapper(infer_from) - - -def infer_getattr(self, context=None): - """infer a Getattr node by using getattr on the associated object""" - if not context: - context = InferenceContext() - for owner in self.expr.infer(context): - if owner is YES: - yield owner - continue - try: - with context.scope(boundnode=owner): - for obj in owner.igetattr(self.attrname, context): - yield obj - except (NotFoundError, InferenceError): - pass - except AttributeError: - # XXX method / function - pass -nodes.Getattr._infer = path_wrapper(raise_if_nothing_infered(infer_getattr)) -nodes.AssAttr.infer_lhs = raise_if_nothing_infered(infer_getattr) # # won't work with a path wrapper - - -def infer_global(self, context=None, lookupname=None): - if lookupname is None: - raise InferenceError() - try: - return _infer_stmts(self.root().getattr(lookupname), context) - except NotFoundError: - raise InferenceError() -nodes.Global._infer = path_wrapper(infer_global) - - -def infer_subscript(self, context=None): - """infer simple subscription such as [1,2,3][0] or (1,2,3)[-1]""" - value = next(self.value.infer(context)) - if value is YES: - yield YES - return - - index = next(self.slice.infer(context)) - if index is YES: - yield YES - return - - if isinstance(index, nodes.Const): - try: - assigned = value.getitem(index.value, context) - except AttributeError: - raise InferenceError() - except (IndexError, TypeError): - yield YES - return - for infered in assigned.infer(context): - yield infered - else: - raise InferenceError() -nodes.Subscript._infer = path_wrapper(infer_subscript) -nodes.Subscript.infer_lhs = raise_if_nothing_infered(infer_subscript) - -def infer_unaryop(self, context=None): - for operand in self.operand.infer(context): - try: - yield operand.infer_unary_op(self.op) - except TypeError: - continue - except AttributeError: - meth = UNARY_OP_METHOD[self.op] - if meth is None: - yield YES - else: - try: - # XXX just suppose if the type implement meth, returned type - # will be the same - operand.getattr(meth) - yield operand - except GeneratorExit: - raise - except: - yield YES -nodes.UnaryOp._infer = path_wrapper(infer_unaryop) - -def _infer_binop(operator, operand1, operand2, context, failures=None): - if operand1 is YES: - yield operand1 - return - try: - for valnode in operand1.infer_binary_op(operator, operand2, context): - yield valnode - except AttributeError: - try: - # XXX just suppose if the type implement meth, returned type - # will be the same - operand1.getattr(BIN_OP_METHOD[operator]) - yield operand1 - except: - if failures is None: - yield YES - else: - failures.append(operand1) - -def infer_binop(self, context=None): - failures = [] - for lhs in self.left.infer(context): - for val in _infer_binop(self.op, lhs, self.right, context, failures): - yield val - for lhs in failures: - for rhs in self.right.infer(context): - for val in _infer_binop(self.op, rhs, lhs, context): - yield val -nodes.BinOp._infer = path_wrapper(infer_binop) - - -def infer_arguments(self, context=None, lookupname=None): - if lookupname is None: - raise InferenceError() - return _arguments_infer_argname(self, lookupname, context) -nodes.Arguments._infer = infer_arguments - - -def infer_ass(self, context=None): - """infer a AssName/AssAttr: need to inspect the RHS part of the - assign node - """ - stmt = self.statement() - if isinstance(stmt, nodes.AugAssign): - return stmt.infer(context) - stmts = list(self.assigned_stmts(context=context)) - return _infer_stmts(stmts, context) -nodes.AssName._infer = path_wrapper(infer_ass) -nodes.AssAttr._infer = path_wrapper(infer_ass) - -def infer_augassign(self, context=None): - failures = [] - for lhs in self.target.infer_lhs(context): - for val in _infer_binop(self.op, lhs, self.value, context, failures): - yield val - for lhs in failures: - for rhs in self.value.infer(context): - for val in _infer_binop(self.op, rhs, lhs, context): - yield val -nodes.AugAssign._infer = path_wrapper(infer_augassign) - - -# no infer method on DelName and DelAttr (expected InferenceError) - - -def infer_empty_node(self, context=None): - if not self.has_underlying_object(): - yield YES - else: - try: - for infered in MANAGER.infer_ast_from_something(self.object, - context=context): - yield infered - except AstroidError: - yield YES -nodes.EmptyNode._infer = path_wrapper(infer_empty_node) - - -def infer_index(self, context=None): - return self.value.infer(context) -nodes.Index._infer = infer_index |