diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py index 9d9b9825518..a4c9e5b18f5 100644 --- a/Lib/compiler/pycodegen.py +++ b/Lib/compiler/pycodegen.py @@ -1,6 +1,7 @@ import os import marshal import stat +import string import struct import types from cStringIO import StringIO @@ -44,7 +45,7 @@ def dump(self, f): f.write(self.getPycHeader()) marshal.dump(self.code, f) - MAGIC = (50811 | (ord('\r')<<16) | (ord('\n')<<24)) + MAGIC = (50823 | (ord('\r')<<16) | (ord('\n')<<24)) def getPycHeader(self): # compile.c uses marshal to write a long directly, with @@ -420,19 +421,32 @@ def visitPass(self, node): def visitImport(self, node): self.set_lineno(node) - for name in node.names: + for name, alias in node.names: + self.emit('LOAD_CONST', None) self.emit('IMPORT_NAME', name) - self.storeName(name) + self._resolveDots(name) + self.storeName(alias or name) def visitFrom(self, node): self.set_lineno(node) + fromlist = map(lambda (name, alias): name, node.names) + self.emit('LOAD_CONST', tuple(fromlist)) self.emit('IMPORT_NAME', node.modname) - for name in node.names: + for name, alias in node.names: if name == '*': self.namespace = 0 self.emit('IMPORT_FROM', name) + self._resolveDots(name) + self.storeName(alias or name) self.emit('POP_TOP') + def _resolveDots(self, name): + elts = string.split(name, ".") + if len(elts) == 1: + return + for elt in elts[1:]: + self.emit('LOAD_ATTR', elt) + def visitGetattr(self, node): self.visit(node.expr) self.emit('LOAD_ATTR', node.attrname) @@ -787,12 +801,12 @@ def visitLambda(self, node): pass def visitImport(self, node): - for name in node.names: - self.names.add(name) + for name, alias in node.names: + self.names.add(alias or name) def visitFrom(self, node): - for name in node.names: - self.names.add(name) + for name, alias in node.names: + self.names.add(alias or name) def visitClass(self, node): self.names.add(node.name) diff --git a/Lib/compiler/transformer.py b/Lib/compiler/transformer.py index 16d1d8ba4c6..9562aa68a68 100644 --- a/Lib/compiler/transformer.py +++ b/Lib/compiler/transformer.py @@ -402,19 +402,20 @@ def raise_stmt(self, nodelist): return n def import_stmt(self, nodelist): - # import: dotted_name (',' dotted_name)* | - # from: dotted_name 'import' ('*' | NAME (',' NAME)*) - names = [ ] - if nodelist[0][1][0] == 'f': + # import_stmt: 'import' dotted_as_name (',' dotted_as_name)* | + # from: 'from' dotted_name 'import' + # ('*' | import_as_name (',' import_as_name)*) + names = [] + is_as = 0 + if nodelist[0][1] == 'from': for i in range(3, len(nodelist), 2): - # note: nodelist[i] could be (token.STAR, '*') or (token.NAME, name) - names.append(nodelist[i][1]) + names.append(self.com_import_as_name(nodelist[i][1])) n = Node('from', self.com_dotted_name(nodelist[1]), names) n.lineno = nodelist[0][2] return n for i in range(1, len(nodelist), 2): - names.append(self.com_dotted_name(nodelist[i])) + names.append(self.com_dotted_as_name(nodelist[i])) n = Node('import', names) n.lineno = nodelist[0][2] return n @@ -738,6 +739,7 @@ def com_node(self, node): if node[0] not in _legal_node_types: raise error, 'illegal node passed to com_node: %s' % node[0] +# print "dispatch", self._dispatch[node[0]].__name__, node return self._dispatch[node[0]](node[1:]) def com_arglist(self, nodelist): @@ -814,6 +816,22 @@ def com_dotted_name(self, node): name = name + n[1] + '.' return name[:-1] + def com_dotted_as_name(self, node): + dot = self.com_dotted_name(node[1]) + if len(node) == 2: + return dot, None + assert node[2][1] == 'as' + assert node[3][0] == token.NAME + return dot, node[3][1] + + def com_import_as_name(self, node): + if node[0] == token.NAME: + return node[1], None + assert len(node) == 4 + assert node[2][1] == 'as' + assert node[3][0] == token.NAME + return node[1][1], node[3][1] + def com_bases(self, node): bases = [ ] for i in range(1, len(node), 2): diff --git a/Tools/compiler/compiler/pycodegen.py b/Tools/compiler/compiler/pycodegen.py index 9d9b9825518..a4c9e5b18f5 100644 --- a/Tools/compiler/compiler/pycodegen.py +++ b/Tools/compiler/compiler/pycodegen.py @@ -1,6 +1,7 @@ import os import marshal import stat +import string import struct import types from cStringIO import StringIO @@ -44,7 +45,7 @@ def dump(self, f): f.write(self.getPycHeader()) marshal.dump(self.code, f) - MAGIC = (50811 | (ord('\r')<<16) | (ord('\n')<<24)) + MAGIC = (50823 | (ord('\r')<<16) | (ord('\n')<<24)) def getPycHeader(self): # compile.c uses marshal to write a long directly, with @@ -420,19 +421,32 @@ def visitPass(self, node): def visitImport(self, node): self.set_lineno(node) - for name in node.names: + for name, alias in node.names: + self.emit('LOAD_CONST', None) self.emit('IMPORT_NAME', name) - self.storeName(name) + self._resolveDots(name) + self.storeName(alias or name) def visitFrom(self, node): self.set_lineno(node) + fromlist = map(lambda (name, alias): name, node.names) + self.emit('LOAD_CONST', tuple(fromlist)) self.emit('IMPORT_NAME', node.modname) - for name in node.names: + for name, alias in node.names: if name == '*': self.namespace = 0 self.emit('IMPORT_FROM', name) + self._resolveDots(name) + self.storeName(alias or name) self.emit('POP_TOP') + def _resolveDots(self, name): + elts = string.split(name, ".") + if len(elts) == 1: + return + for elt in elts[1:]: + self.emit('LOAD_ATTR', elt) + def visitGetattr(self, node): self.visit(node.expr) self.emit('LOAD_ATTR', node.attrname) @@ -787,12 +801,12 @@ def visitLambda(self, node): pass def visitImport(self, node): - for name in node.names: - self.names.add(name) + for name, alias in node.names: + self.names.add(alias or name) def visitFrom(self, node): - for name in node.names: - self.names.add(name) + for name, alias in node.names: + self.names.add(alias or name) def visitClass(self, node): self.names.add(node.name) diff --git a/Tools/compiler/compiler/transformer.py b/Tools/compiler/compiler/transformer.py index 16d1d8ba4c6..9562aa68a68 100644 --- a/Tools/compiler/compiler/transformer.py +++ b/Tools/compiler/compiler/transformer.py @@ -402,19 +402,20 @@ def raise_stmt(self, nodelist): return n def import_stmt(self, nodelist): - # import: dotted_name (',' dotted_name)* | - # from: dotted_name 'import' ('*' | NAME (',' NAME)*) - names = [ ] - if nodelist[0][1][0] == 'f': + # import_stmt: 'import' dotted_as_name (',' dotted_as_name)* | + # from: 'from' dotted_name 'import' + # ('*' | import_as_name (',' import_as_name)*) + names = [] + is_as = 0 + if nodelist[0][1] == 'from': for i in range(3, len(nodelist), 2): - # note: nodelist[i] could be (token.STAR, '*') or (token.NAME, name) - names.append(nodelist[i][1]) + names.append(self.com_import_as_name(nodelist[i][1])) n = Node('from', self.com_dotted_name(nodelist[1]), names) n.lineno = nodelist[0][2] return n for i in range(1, len(nodelist), 2): - names.append(self.com_dotted_name(nodelist[i])) + names.append(self.com_dotted_as_name(nodelist[i])) n = Node('import', names) n.lineno = nodelist[0][2] return n @@ -738,6 +739,7 @@ def com_node(self, node): if node[0] not in _legal_node_types: raise error, 'illegal node passed to com_node: %s' % node[0] +# print "dispatch", self._dispatch[node[0]].__name__, node return self._dispatch[node[0]](node[1:]) def com_arglist(self, nodelist): @@ -814,6 +816,22 @@ def com_dotted_name(self, node): name = name + n[1] + '.' return name[:-1] + def com_dotted_as_name(self, node): + dot = self.com_dotted_name(node[1]) + if len(node) == 2: + return dot, None + assert node[2][1] == 'as' + assert node[3][0] == token.NAME + return dot, node[3][1] + + def com_import_as_name(self, node): + if node[0] == token.NAME: + return node[1], None + assert len(node) == 4 + assert node[2][1] == 'as' + assert node[3][0] == token.NAME + return node[1][1], node[3][1] + def com_bases(self, node): bases = [ ] for i in range(1, len(node), 2):