# HG changeset patch # User Paul Boddie # Date 1381265950 -7200 # Node ID 112b08cc400606d2f6bd7aa6b036197290f23b80 # Parent be4ea92ff0629aa6e2ece116795c475e3e2f5557 Supported relative imports in report output; made get_module_name a common function. diff -r be4ea92ff062 -r 112b08cc4006 micropython/common.py --- a/micropython/common.py Tue Oct 08 22:44:44 2013 +0200 +++ b/micropython/common.py Tue Oct 08 22:59:10 2013 +0200 @@ -230,6 +230,47 @@ return targets +def get_module_name(node, module): + + """ + Using the given From 'node' and 'module' in which it is found, calculate + any relative import information, returning a tuple containing a module + to import along with any names to import based on the node's name + information. + + Where the returned module is given as None, whole module imports should + be performed for the returned modules using the returned names. + """ + + # Absolute import. + + if node.level == 0: + return node.modname, node.names + + # Relative to this module. + + elif node.level == 1: + basename = module.full_name() + + # Relative to an ancestor of this module. + + else: + path = module.full_name().split(".") + if node.level > len(path): + raise InspectError("Relative import %r involves too many levels up from module %r" % ( + ("." * node.level + node.modname), module.full_name())) + basename = ".".join(path[:-node.level+1]) + + # Name imports from a module. + + if node.modname: + return "%s.%s" % (basename, node.modname), node.names + + # Relative whole module imports. + + else: + return None, [("%s.%s" % (basename, name), alias) for name, alias in node.names] + def used_by_unit(node): """ diff -r be4ea92ff062 -r 112b08cc4006 micropython/inspect.py --- a/micropython/inspect.py Tue Oct 08 22:44:44 2013 +0200 +++ b/micropython/inspect.py Tue Oct 08 22:59:10 2013 +0200 @@ -72,7 +72,7 @@ benefits in considering a local to be constant within a single invocation. """ -from micropython.common import ASTVisitor, operator_functions +from micropython.common import ASTVisitor, operator_functions, get_module_name from micropython.data import * from micropython.errors import * import compiler.ast @@ -224,7 +224,7 @@ # Module import declarations. elif isinstance(n, compiler.ast.From): - modname, names = self.get_module_name(n) + modname, names = get_module_name(n, self) # Perform whole module relative imports. @@ -262,45 +262,6 @@ else: self.process_structure(n) - def get_module_name(self, node): - - """ - Using the given From 'node', calculate any relative import information, - returning a tuple containing a module to import along with any names to - import based on the node's name information. - - Where the returned module is given as None, whole module imports should - be performed for the returned modules using the returned names. - """ - - # Absolute import. - - if node.level == 0: - return node.modname, node.names - - # Relative to this module. - - elif node.level == 1: - basename = self.full_name() - - # Relative to an ancestor of this module. - - else: - path = self.full_name().split(".") - if node.level > len(path): - raise InspectError("Relative import %r involves too many levels up from module %r" % (("." * node.level + node.modname), self.full_name())) - basename = ".".join(path[:-node.level+1]) - - # Name imports from a module. - - if node.modname: - return "%s.%s" % (basename, node.modname), node.names - - # Relative whole module imports. - - else: - return None, [("%s.%s" % (basename, name), alias) for name, alias in node.names] - def get_module_paths(self, name): """ @@ -1174,7 +1135,7 @@ self.resume_broken_branches() def visitFrom(self, node): - modname, names = self.get_module_name(node) + modname, names = get_module_name(node, self) if not modname: return self._visitImport(names) diff -r be4ea92ff062 -r 112b08cc4006 micropython/report.py --- a/micropython/report.py Tue Oct 08 22:44:44 2013 +0200 +++ b/micropython/report.py Tue Oct 08 22:59:10 2013 +0200 @@ -292,10 +292,10 @@ classes or "specific-ref", module_name, os.path.extsep, self._attr(full_name), self._text(name))) - def _module_link(self, module_name, classes=None): + def _module_link(self, module_name, label, classes=None): self.stream.write("%s" % ( classes or "name", module_name, os.path.extsep, - self._text(module_name))) + self._text(label))) def _scope(self, scope, attr): self.stream.write("
" @@ -815,17 +815,35 @@ def visitFrom(self, node): self.stream.write("
\n") self._keyword("from") - self._module_link(node.modname) + + # Support relative imports of names and whole modules. + + modname, names = get_module_name(node, self.module) + if modname: + self._module_link(modname, "%s%s" % ("." * node.level, modname)) + else: + self._text("." * node.level) + self._keyword("import", 1) first = True - for name, alias in node.names: + + # Integrate the provided name details with any calculated details + # resulting from whole module imports. + + for (name, alias), (full_name, alias) in zip(node.names, names): if not first: self.stream.write(", ") - self._name(name) + + if modname: + self._name(name) + else: + self._module_link(full_name, name) + if alias: self._keyword("as", 1) self._name(alias) first = False + self.stream.write("
\n") def visitFunction(self, node): @@ -902,7 +920,7 @@ for name, alias in node.names: if not first: self.stream.write(",\n") - self._module_link(name) + self._module_link(name, name) if alias: self._keyword("as", 1) self._name(alias)