diff options
author | Emile Anclin <emile.anclin@logilab.fr> | 2010-12-09 10:05:30 +0100 |
---|---|---|
committer | Emile Anclin <emile.anclin@logilab.fr> | 2010-12-09 10:05:30 +0100 |
commit | 1c174ccb33e1d50e799a422e4fdd0a45eb7e12c6 (patch) | |
tree | b19a977d6d2bdd147ea620432a721d34af5fcef7 /builder.py | |
parent | 4fe15c17a46bce12f8398945eed9c782f7644b4e (diff) | |
download | astroid-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.py | 73 |
1 files changed, 44 insertions, 29 deletions
@@ -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 |