summaryrefslogtreecommitdiff
path: root/builder.py
diff options
context:
space:
mode:
authorEmile Anclin <emile.anclin@logilab.fr>2010-12-01 10:36:29 +0100
committerEmile Anclin <emile.anclin@logilab.fr>2010-12-01 10:36:29 +0100
commit8bcd9961171735cca123a0424def58c505cdd8e5 (patch)
tree85b9ef6f4a2d155a0579a282a2f5e66fd6e4f71b /builder.py
parentd038ae380bfd3291aa2ceddc9f1eb365e2fb3942 (diff)
downloadastroid-git-8bcd9961171735cca123a0424def58c505cdd8e5.tar.gz
cleanup: move some rebuilder stuff to builder; fix _delayed_assattr cache
indeed, _delayed_assattr was not reset before building a tree !
Diffstat (limited to 'builder.py')
-rw-r--r--builder.py64
1 files changed, 61 insertions, 3 deletions
diff --git a/builder.py b/builder.py
index 83035045..77cc6ff0 100644
--- a/builder.py
+++ b/builder.py
@@ -35,16 +35,17 @@ from inspect import isdatadescriptor
from logilab.common.modutils import modpath_from_file
-from logilab.astng._exceptions import ASTNGBuildingException
+from logilab.astng._exceptions import ASTNGBuildingException, InferenceError
from logilab.astng.raw_building import build_module, object_build_class, \
object_build_function, object_build_datadescriptor, attach_dummy_node, \
object_build_methoddescriptor, attach_const_node, attach_import_node
+from logilab.astng.rebuilder import TreeRebuilder
from logilab.astng.manager import ASTNGManager
+from logilab.astng.bases import YES, Instance
from _ast import PyCF_ONLY_AST
def parse(string):
return compile(string, "<string>", 'exec', PyCF_ONLY_AST)
-from logilab.astng.rebuilder import TreeRebuilder
# ast NG builder ##############################################################
@@ -134,9 +135,66 @@ class ASTNGBuilder:
package = True
else:
package = path and path.find('__init__.py') > -1 or False
- newnode = self.rebuilder.build(node, modname, node_file, package)
+ newnode = self.build(node, modname, node_file, package)
return newnode
+ def build(self, node, modname, module_file, package):
+ """rebuild the tree starting with an Module node;
+ return an astng.Module node
+ """
+ rebuilder = self.rebuilder
+ rebuilder.init()
+ module = rebuilder.visit_module(node, modname, package)
+ module.file = module.path = module_file
+ # init module cache here else we may get some infinite recursion
+ # errors while infering delayed assignments
+ if self._manager is not None:
+ self._manager._cache[module.name] = module
+ # handle delayed assattr nodes
+ for from_node in rebuilder._from_nodes:
+ rebuilder.add_from_names_to_locals(from_node, delayed=True)
+ delay_assattr = self.delayed_assattr
+ for delayed in rebuilder._delayed_assattr:
+ delay_assattr(delayed)
+ return module
+
+ def delayed_assattr(self, node):
+ """visit a AssAttr node -> add name to locals, handle members
+ definition
+ """
+ try:
+ frame = node.frame()
+ for infered in node.expr.infer():
+ if infered is YES:
+ continue
+ try:
+ if infered.__class__ is Instance:
+ infered = infered._proxied
+ iattrs = infered.instance_attrs
+ elif isinstance(infered, Instance):
+ # Const, Tuple, ... we may be wrong, may be not, but
+ # anyway we don't want to pollute builtin's namespace
+ continue
+ else:
+ iattrs = infered.locals
+ except AttributeError:
+ # XXX log error
+ #import traceback
+ #traceback.print_exc()
+ continue
+ values = iattrs.setdefault(node.attrname, [])
+ if node in values:
+ continue
+ # get assign in __init__ first XXX useful ?
+ if frame.name == '__init__' and values and not \
+ values[0].frame().name == '__init__':
+ values.insert(0, node)
+ else:
+ values.append(node)
+ except InferenceError:
+ pass
+
+
# astng from living objects ###############################################
#
# this is actually a really minimal representation, including only Module,