diff options
author | Sylvain Thénault <sylvain.thenault@logilab.fr> | 2013-06-18 17:24:28 +0200 |
---|---|---|
committer | Sylvain Thénault <sylvain.thenault@logilab.fr> | 2013-06-18 17:24:28 +0200 |
commit | fc02b9e6bc453e0413e324c7a458b5871277744c (patch) | |
tree | 5447adcc4b02bff14a98817b4e2d4f98cb1b1443 | |
parent | 2682f50ee379e7e6d7a0c5891ba7211fc8829ab3 (diff) | |
download | astroid-git-fc02b9e6bc453e0413e324c7a458b5871277744c.tar.gz |
[inference] introduce (but not use it yet) explicit inference for some node instances
-rw-r--r-- | bases.py | 23 | ||||
-rw-r--r-- | exceptions.py | 5 | ||||
-rw-r--r-- | inference.py | 48 |
3 files changed, 49 insertions, 27 deletions
@@ -24,8 +24,8 @@ __docformat__ = "restructuredtext en" import sys from contextlib import contextmanager -from astroid.exceptions import (InferenceError, AstroidError, - NotFoundError, UnresolvableName) +from astroid.exceptions import (InferenceError, AstroidError, NotFoundError, + UnresolvableName, UseInferenceDefault) if sys.version_info >= (3, 0): @@ -355,6 +355,23 @@ class NodeNG(object): parent = None # attributes containing child node(s) redefined in most concrete classes: _astroid_fields = () + # instance specific inference function infer(node, context) + _explicit_inference = None + + def infer(self, context=None): + """main interface to the interface system, return a generator on infered + values. + + If the instance has some explicit inference function set, it will be + called instead of the default interface. + """ + if self._explicit_inference is not None: + # explicit_inference is not bound, give it self explicitly + try: + return self._explicit_inference(self, context) + except UseInferenceDefault: + pass + return self._infer(context) def _repr_name(self): """return self.name or self.attrname or '' for nice representation""" @@ -543,7 +560,7 @@ class NodeNG(object): # overridden for From, Import, Global, TryExcept and Arguments return None - def infer(self, context=None): + def _infer(self, context=None): """we don't know how to resolve a statement by default""" # this method is overridden by most concrete classes raise InferenceError(self.__class__.__name__) diff --git a/exceptions.py b/exceptions.py index 07fb945e..3889e2e7 100644 --- a/exceptions.py +++ b/exceptions.py @@ -36,6 +36,11 @@ class NotFoundError(ResolveError): class InferenceError(ResolveError): """raised when we are unable to infer a node""" +class UseInferenceDefault(Exception): + """exception to be raised in custom inference function to indicate that it + should go back to the default behaviour + """ + class UnresolvableName(InferenceError): """raised when we are unable to resolve a name""" diff --git a/inference.py b/inference.py index 055b98d3..ce6dd6c7 100644 --- a/inference.py +++ b/inference.py @@ -126,15 +126,15 @@ 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 +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 infer_name(self, context=None): """infer a Name: use name lookup rules""" @@ -144,7 +144,7 @@ def infer_name(self, context=None): context = context.clone() context.lookupname = self.name return _infer_stmts(stmts, context, frame) -nodes.Name.infer = path_wrapper(infer_name) +nodes.Name._infer = path_wrapper(infer_name) nodes.AssName.infer_lhs = infer_name # won't work with a path wrapper @@ -164,7 +164,7 @@ def infer_callfunc(self, context=None): except InferenceError: ## XXX log error ? continue -nodes.CallFunc.infer = path_wrapper(raise_if_nothing_infered(infer_callfunc)) +nodes.CallFunc._infer = path_wrapper(raise_if_nothing_infered(infer_callfunc)) def infer_import(self, context=None, asname=True): @@ -176,7 +176,7 @@ def infer_import(self, context=None, asname=True): yield self.do_import_module(self.real_name(name)) else: yield self.do_import_module(name) -nodes.Import.infer = path_wrapper(infer_import) +nodes.Import._infer = path_wrapper(infer_import) def infer_name_module(self, name): context = InferenceContext() @@ -199,7 +199,7 @@ def infer_from(self, context=None, asname=True): return _infer_stmts(module.getattr(name, ignore_locals=module is self.root()), context) except NotFoundError: raise InferenceError(name) -nodes.From.infer = path_wrapper(infer_from) +nodes.From._infer = path_wrapper(infer_from) def infer_getattr(self, context=None): @@ -219,7 +219,7 @@ def infer_getattr(self, context=None): except AttributeError: # XXX method / function context.boundnode = None -nodes.Getattr.infer = path_wrapper(raise_if_nothing_infered(infer_getattr)) +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 @@ -230,7 +230,7 @@ def infer_global(self, context=None): return _infer_stmts(self.root().getattr(context.lookupname), context) except NotFoundError: raise InferenceError() -nodes.Global.infer = path_wrapper(infer_global) +nodes.Global._infer = path_wrapper(infer_global) def infer_subscript(self, context=None): @@ -257,7 +257,7 @@ def infer_subscript(self, context=None): yield infered else: raise InferenceError() -nodes.Subscript.infer = path_wrapper(infer_subscript) +nodes.Subscript._infer = path_wrapper(infer_subscript) nodes.Subscript.infer_lhs = raise_if_nothing_infered(infer_subscript) @@ -287,7 +287,7 @@ def infer_unaryop(self, context=None): raise except: yield YES -nodes.UnaryOp.infer = path_wrapper(infer_unaryop) +nodes.UnaryOp._infer = path_wrapper(infer_unaryop) BIN_OP_METHOD = {'+': '__add__', @@ -332,7 +332,7 @@ def infer_binop(self, context=None): 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) +nodes.BinOp._infer = path_wrapper(infer_binop) def infer_arguments(self, context=None): @@ -340,7 +340,7 @@ def infer_arguments(self, context=None): if name is None: raise InferenceError() return _arguments_infer_argname(self, name, context) -nodes.Arguments.infer = infer_arguments +nodes.Arguments._infer = infer_arguments def infer_ass(self, context=None): @@ -352,8 +352,8 @@ def infer_ass(self, context=None): 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) +nodes.AssName._infer = path_wrapper(infer_ass) +nodes.AssAttr._infer = path_wrapper(infer_ass) def infer_augassign(self, context=None): failures = [] @@ -364,7 +364,7 @@ def infer_augassign(self, context=None): 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) +nodes.AugAssign._infer = path_wrapper(infer_augassign) # no infer method on DelName and DelAttr (expected InferenceError) @@ -380,9 +380,9 @@ def infer_empty_node(self, context=None): yield infered except AstroidError: yield YES -nodes.EmptyNode.infer = path_wrapper(infer_empty_node) +nodes.EmptyNode._infer = path_wrapper(infer_empty_node) def infer_index(self, context=None): return self.value.infer(context) -nodes.Index.infer = infer_index +nodes.Index._infer = infer_index |