Commit 124df839 authored by Georg Brandl's avatar Georg Brandl

Patch #1683328: fixes and enhancements for "unparse" demo.

parent a8785cc2
...@@ -4,6 +4,19 @@ import _ast ...@@ -4,6 +4,19 @@ import _ast
import cStringIO import cStringIO
import os import os
def interleave(inter, f, seq):
"""Call f on each item in seq, calling inter() in between.
"""
seq = iter(seq)
try:
f(seq.next())
except StopIteration:
pass
else:
for x in seq:
inter()
f(x)
class Unparser: class Unparser:
"""Methods in this class recursively traverse an AST and """Methods in this class recursively traverse an AST and
output source code for the abstract syntax; original formatting output source code for the abstract syntax; original formatting
...@@ -63,26 +76,13 @@ class Unparser: ...@@ -63,26 +76,13 @@ class Unparser:
def _Import(self, t): def _Import(self, t):
self.fill("import ") self.fill("import ")
first = True interleave(lambda: self.write(", "), self.dispatch, t.names)
for a in t.names:
if first:
first = False
else:
self.write(", ")
self.write(a.name)
if a.asname:
self.write(" as "+a.asname)
def _ImportFrom(self, t): def _ImportFrom(self, t):
self.fill("from ") self.fill("from ")
self.write(t.module) self.write(t.module)
self.write(" import ") self.write(" import ")
for i, a in enumerate(t.names): interleave(lambda: self.write(", "), self.dispatch, t.names)
if i == 0:
self.write(", ")
self.write(a.name)
if a.asname:
self.write(" as "+a.asname)
# XXX(jpe) what is level for? # XXX(jpe) what is level for?
def _Assign(self, t): def _Assign(self, t):
...@@ -99,8 +99,9 @@ class Unparser: ...@@ -99,8 +99,9 @@ class Unparser:
self.dispatch(t.value) self.dispatch(t.value)
def _Return(self, t): def _Return(self, t):
self.fill("return ") self.fill("return")
if t.value: if t.value:
self.write(" ")
self.dispatch(t.value) self.dispatch(t.value)
def _Pass(self, t): def _Pass(self, t):
...@@ -148,16 +149,14 @@ class Unparser: ...@@ -148,16 +149,14 @@ class Unparser:
self.write(",") self.write(",")
def _Global(self, t): def _Global(self, t):
self.fill("global") self.fill("global ")
for i, n in enumerate(t.names): interleave(lambda: self.write(", "), self.write, t.names)
if i != 0:
self.write(",")
self.write(" " + n)
def _Yield(self, t): def _Yield(self, t):
self.fill("yield") self.write("(")
self.write("yield")
if t.value: if t.value:
self.write(" (") self.write(" ")
self.dispatch(t.value) self.dispatch(t.value)
self.write(")") self.write(")")
...@@ -198,8 +197,9 @@ class Unparser: ...@@ -198,8 +197,9 @@ class Unparser:
self.leave() self.leave()
def _excepthandler(self, t): def _excepthandler(self, t):
self.fill("except ") self.fill("except")
if t.type: if t.type:
self.write(" ")
self.dispatch(t.type) self.dispatch(t.type)
if t.name: if t.name:
self.write(", ") self.write(", ")
...@@ -299,9 +299,7 @@ class Unparser: ...@@ -299,9 +299,7 @@ class Unparser:
def _List(self, t): def _List(self, t):
self.write("[") self.write("[")
for e in t.elts: interleave(lambda: self.write(", "), self.dispatch, t.elts)
self.dispatch(e)
self.write(", ")
self.write("]") self.write("]")
def _ListComp(self, t): def _ListComp(self, t):
...@@ -328,30 +326,31 @@ class Unparser: ...@@ -328,30 +326,31 @@ class Unparser:
self.dispatch(if_clause) self.dispatch(if_clause)
def _IfExp(self, t): def _IfExp(self, t):
self.write("(")
self.dispatch(t.body) self.dispatch(t.body)
self.write(" if ") self.write(" if ")
self.dispatch(t.test) self.dispatch(t.test)
if t.orelse:
self.write(" else ") self.write(" else ")
self.dispatch(t.orelse) self.dispatch(t.orelse)
self.write(")")
def _Dict(self, t): def _Dict(self, t):
self.write("{") self.write("{")
for k,v in zip(t.keys, t.values): def writem((k, v)):
self.dispatch(k) self.dispatch(k)
self.write(" : ") self.write(": ")
self.dispatch(v) self.dispatch(v)
self.write(", ") interleave(lambda: self.write(", "), writem, zip(t.keys, t.values))
self.write("}") self.write("}")
def _Tuple(self, t): def _Tuple(self, t):
if not t.elts:
self.write("()")
return
self.write("(") self.write("(")
for e in t.elts: if len(t.elts) == 1:
self.dispatch(e) (elt,) = t.elts
self.write(", ") self.dispatch(elt)
self.write(",")
else:
interleave(lambda: self.write(", "), self.dispatch, t.elts)
self.write(")") self.write(")")
unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"} unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}
...@@ -367,7 +366,7 @@ class Unparser: ...@@ -367,7 +366,7 @@ class Unparser:
def _BinOp(self, t): def _BinOp(self, t):
self.write("(") self.write("(")
self.dispatch(t.left) self.dispatch(t.left)
self.write(")" + self.binop[t.op.__class__.__name__] + "(") self.write(" " + self.binop[t.op.__class__.__name__] + " ")
self.dispatch(t.right) self.dispatch(t.right)
self.write(")") self.write(")")
...@@ -377,17 +376,15 @@ class Unparser: ...@@ -377,17 +376,15 @@ class Unparser:
self.write("(") self.write("(")
self.dispatch(t.left) self.dispatch(t.left)
for o, e in zip(t.ops, t.comparators): for o, e in zip(t.ops, t.comparators):
self.write(") " +self.cmpops[o.__class__.__name__] + " (") self.write(" " + self.cmpops[o.__class__.__name__] + " ")
self.dispatch(e) self.dispatch(e)
self.write(")") self.write(")")
boolops = {_ast.And: 'and', _ast.Or: 'or'} boolops = {_ast.And: 'and', _ast.Or: 'or'}
def _BoolOp(self, t): def _BoolOp(self, t):
self.write("(") self.write("(")
self.dispatch(t.values[0]) s = " %s " % self.boolops[t.op.__class__]
for v in t.values[1:]: interleave(lambda: self.write(s), self.dispatch, t.values)
self.write(" %s " % self.boolops[t.op.__class__])
self.dispatch(v)
self.write(")") self.write(")")
def _Attribute(self,t): def _Attribute(self,t):
...@@ -443,10 +440,7 @@ class Unparser: ...@@ -443,10 +440,7 @@ class Unparser:
self.dispatch(t.step) self.dispatch(t.step)
def _ExtSlice(self, t): def _ExtSlice(self, t):
for i, d in enumerate(t.dims): interleave(lambda: self.write(', '), self.dispatch, t.dims)
if i != 0:
self.write(': ')
self.dispatch(d)
# others # others
def _arguments(self, t): def _arguments(self, t):
...@@ -482,9 +476,14 @@ class Unparser: ...@@ -482,9 +476,14 @@ class Unparser:
self.write(": ") self.write(": ")
self.dispatch(t.body) self.dispatch(t.body)
def _alias(self, t):
self.write(t.name)
if t.asname:
self.write(" as "+t.asname)
def roundtrip(filename, output=sys.stdout): def roundtrip(filename, output=sys.stdout):
source = open(filename).read() source = open(filename).read()
tree = compile(source, filename, "exec", 0x400) tree = compile(source, filename, "exec", _ast.PyCF_ONLY_AST)
Unparser(tree, output) Unparser(tree, output)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment