summaryrefslogtreecommitdiff
path: root/builder.py
diff options
context:
space:
mode:
authorEmile Anclin <emile.anclin@logilab.fr>2010-12-09 10:05:30 +0100
committerEmile Anclin <emile.anclin@logilab.fr>2010-12-09 10:05:30 +0100
commit1c174ccb33e1d50e799a422e4fdd0a45eb7e12c6 (patch)
treeb19a977d6d2bdd147ea620432a721d34af5fcef7 /builder.py
parent4fe15c17a46bce12f8398945eed9c782f7644b4e (diff)
downloadastroid-1c174ccb33e1d50e799a422e4fdd0a45eb7e12c6.tar.gz
refactoring for tree rebuilding
rebuilder: move all post build process to builder and don't depend on manager builder: - instanciate ASTNGBuilder's ASTNGManager and TreeRebuilder only once - cleanup build methods; - "_data_build" should become entry point for possible astng pickle cache
Diffstat (limited to 'builder.py')
-rw-r--r--builder.py73
1 files changed, 44 insertions, 29 deletions
diff --git a/builder.py b/builder.py
index 4e855b1..f744d60 100644
--- a/builder.py
+++ b/builder.py
@@ -49,17 +49,17 @@ def parse(string):
# ast NG builder ##############################################################
+MANAGER = ASTNGManager()
+
class ASTNGBuilder:
"""provide astng building methods
"""
+ rebuilder = TreeRebuilder()
def __init__(self, manager=None):
- if manager is None:
- manager = ASTNGManager()
- self._manager = manager
+ self._manager = manager or MANAGER
self._module = None
self._done = None
- self.rebuilder = TreeRebuilder(manager)
self._dyn_modname_map = {'gtk': 'gtk._gtk'}
def module_build(self, module, modname=None):
@@ -117,15 +117,25 @@ class ASTNGBuilder:
node = self.string_build(data, modname, path)
finally:
sys.path.pop(0)
-
return node
def string_build(self, data, modname='', path=None):
- """build astng from a source code stream (i.e. from an ast)"""
- return self.ast_build(parse(data + '\n'), modname, path)
+ """build astng from source code string and return rebuilded astng"""
+ module = self._data_build(data, modname, path)
+ if self._manager is not None:
+ self._manager._cache[module.name] = module
+ # post tree building steps after we stored the module in the cache:
+ for from_node in module._from_nodes:
+ self.add_from_names_to_locals(from_node)
+ # handle delayed assattr nodes
+ for delayed in module._delayed_assattr:
+ self.delayed_assattr(delayed)
+ return module
- def ast_build(self, node, modname='', path=None):
- """build the astng from AST, return the new tree"""
+ def _data_build(self, data, modname, path):
+ """build tree node from data and add some informations"""
+ # this method could be wrapped with a pickle/cache function
+ node = parse(data + '\n')
if path is not None:
node_file = abspath(path)
else:
@@ -135,28 +145,33 @@ class ASTNGBuilder:
package = True
else:
package = path and path.find('__init__.py') > -1 or False
- newnode = self.tree_build(node, modname, node_file, package)
- return newnode
+ self.rebuilder.init()
+ module = self.rebuilder.visit_module(node, modname, package)
+ module.file = module.path = node_file
+ module._from_nodes = self.rebuilder._from_nodes
+ module._delayed_assattr = self.rebuilder._delayed_assattr
+ return module
- def tree_build(self, node, modname, module_file, package):
- """rebuild the tree starting with an Module node;
- return an astng.Module node
+ def add_from_names_to_locals(self, node):
+ """store imported names to the locals;
+ resort the locals if coming from a delayed 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
+
+ _key_func = lambda node: node.fromlineno
+ def sort_locals(my_list):
+ my_list.sort(key=_key_func)
+ for (name, asname) in node.names:
+ if name == '*':
+ try:
+ imported = node.root().import_module(node.modname)
+ except ASTNGBuildingException:
+ continue
+ for name in imported.wildcard_import_names():
+ node.parent.set_local(name, node)
+ sort_locals(node.parent.scope().locals[name])
+ else:
+ node.parent.set_local(asname or name, node)
+ sort_locals(node.parent.scope().locals[asname or name])
def delayed_assattr(self, node):
"""visit a AssAttr node -> add name to locals, handle members