519 lines · 13.5 KB · Python
RawDownload
"Usage: unparse.py <path to source file>"import sysimport _astimport cStringIOimport os class Unparser:    """Methods in this class recursively traverse an AST and    output source code for the abstract syntax; original formatting    is disregarged. """     def __init__(self, tree, file = sys.stdout):        """Unparser(tree, file=sys.stdout) -> None.         Print the source for tree to file."""        self.f = file        self._indent = 0        self.dispatch(tree)        print >>self.f,""        self.f.flush()     def fill(self, text = ""):        "Indent a piece of text, according to the current indentation level"        self.f.write("\n"+"    "*self._indent + text)     def write(self, text):        "Append a piece of text to the current line."        self.f.write(text)     def enter(self):        "Print ':', and increase the indentation."        self.write(":")        self._indent += 1     def leave(self):        "Decrease the indentation level."        self._indent -= 1     def dispatch(self, tree):        "Dispatcher function, dispatching tree type T to method _T."        if isinstance(tree, list):            for t in tree:                self.dispatch(t)            return        meth = getattr(self, "_"+tree.__class__.__name__)        meth(tree)      ############### Unparsing methods ######################    # There should be one method per concrete grammar type #    # Constructors should be grouped by sum type. Ideally, #    # this would follow the order in the grammar, but      #    # currently doesn't.                                   #    ########################################################     def _Module(self, tree):        for stmt in tree.body:            self.dispatch(stmt)     # stmt    def _Expr(self, tree):        self.fill()        self.dispatch(tree.value)     def _Import(self, t):        self.fill("import ")        first = True        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):        self.fill("from ")        self.write(t.module)        self.write(" import ")        for i, a in enumerate(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?     def _Assign(self, t):        self.fill()        for target in t.targets:            self.dispatch(target)            self.write(" = ")        self.dispatch(t.value)     def _AugAssign(self, t):        self.fill()        self.dispatch(t.target)        self.write(" "+self.binop[t.op.__class__.__name__]+"= ")        self.dispatch(t.value)     def _Return(self, t):        self.fill("return ")        if t.value:            self.dispatch(t.value)     def _Pass(self, t):        self.fill("pass")     def _Break(self, t):        self.fill("break")     def _Continue(self, t):        self.fill("continue")     def _Delete(self, t):        self.fill("del ")        self.dispatch(t.targets)     def _Assert(self, t):        self.fill("assert ")        self.dispatch(t.test)        if t.msg:            self.write(", ")            self.dispatch(t.msg)     def _Exec(self, t):        self.fill("exec ")        self.dispatch(t.body)        if t.globals:            self.write(" in ")            self.dispatch(t.globals)        if t.locals:            self.write(", ")            self.dispatch(t.locals)     def _Print(self, t):        self.fill("print ")        do_comma = False        if t.dest:            self.write(">>")            self.dispatch(t.dest)            do_comma = True        for e in t.values:            if do_comma:self.write(", ")            else:do_comma=True            self.dispatch(e)        if not t.nl:            self.write(",")     def _Global(self, t):        self.fill("global")        for i, n in enumerate(t.names):            if i != 0:                self.write(",")            self.write(" " + n)     def _Yield(self, t):        self.fill("yield")        if t.value:            self.write(" (")            self.dispatch(t.value)            self.write(")")     def _Raise(self, t):        self.fill('raise ')        if t.type:            self.dispatch(t.type)        if t.inst:            self.write(", ")            self.dispatch(t.inst)        if t.tback:            self.write(", ")            self.dispatch(t.tback)     def _TryExcept(self, t):        self.fill("try")        self.enter()        self.dispatch(t.body)        self.leave()         for ex in t.handlers:            self.dispatch(ex)        if t.orelse:            self.fill("else")            self.enter()            self.dispatch(t.orelse)            self.leave()     def _TryFinally(self, t):        self.fill("try")        self.enter()        self.dispatch(t.body)        self.leave()         self.fill("finally")        self.enter()        self.dispatch(t.finalbody)        self.leave()     def _excepthandler(self, t):        self.fill("except ")        if t.type:            self.dispatch(t.type)        if t.name:            self.write(", ")            self.dispatch(t.name)        self.enter()        self.dispatch(t.body)        self.leave()     def _ClassDef(self, t):        self.write("\n")        self.fill("class "+t.name)        if t.bases:            self.write("(")            for a in t.bases:                self.dispatch(a)                self.write(", ")            self.write(")")        self.enter()        self.dispatch(t.body)        self.leave()     def _FunctionDef(self, t):        self.write("\n")        for deco in t.decorators:            self.fill("@")            self.dispatch(deco)        self.fill("def "+t.name + "(")        self.dispatch(t.args)        self.write(")")        self.enter()        self.dispatch(t.body)        self.leave()     def _For(self, t):        self.fill("for ")        self.dispatch(t.target)        self.write(" in ")        self.dispatch(t.iter)        self.enter()        self.dispatch(t.body)        self.leave()        if t.orelse:            self.fill("else")            self.enter()            self.dispatch(t.orelse)            self.leave     def _If(self, t):        self.fill("if ")        self.dispatch(t.test)        self.enter()        # XXX elif?        self.dispatch(t.body)        self.leave()        if t.orelse:            self.fill("else")            self.enter()            self.dispatch(t.orelse)            self.leave()     def _While(self, t):        self.fill("while ")        self.dispatch(t.test)        self.enter()        self.dispatch(t.body)        self.leave()        if t.orelse:            self.fill("else")            self.enter()            self.dispatch(t.orelse)            self.leave     def _With(self, t):        self.fill("with ")        self.dispatch(t.context_expr)        if t.optional_vars:            self.write(" as ")            self.dispatch(t.optional_vars)        self.enter()        self.dispatch(t.body)        self.leave()     # expr    def _Str(self, tree):        self.write(repr(tree.s))     def _Name(self, t):        self.write(t.id)     def _Repr(self, t):        self.write("`")        self.dispatch(t.value)        self.write("`")     def _Num(self, t):        self.write(repr(t.n))     def _List(self, t):        self.write("[")        for e in t.elts:            self.dispatch(e)            self.write(", ")        self.write("]")     def _ListComp(self, t):        self.write("[")        self.dispatch(t.elt)        for gen in t.generators:            self.dispatch(gen)        self.write("]")     def _GeneratorExp(self, t):        self.write("(")        self.dispatch(t.elt)        for gen in t.generators:            self.dispatch(gen)        self.write(")")     def _comprehension(self, t):        self.write(" for ")        self.dispatch(t.target)        self.write(" in ")        self.dispatch(t.iter)        for if_clause in t.ifs:            self.write(" if ")            self.dispatch(if_clause)     def _IfExp(self, t):        self.dispatch(t.body)        self.write(" if ")        self.dispatch(t.test)        if t.orelse:            self.write(" else ")            self.dispatch(t.orelse)     def _Dict(self, t):        self.write("{")        for k,v in zip(t.keys, t.values):            self.dispatch(k)            self.write(" : ")            self.dispatch(v)            self.write(", ")        self.write("}")     def _Tuple(self, t):        if not t.elts:            self.write("()")            return        self.write("(")        for e in t.elts:            self.dispatch(e)            self.write(", ")        self.write(")")     unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}    def _UnaryOp(self, t):        self.write(self.unop[t.op.__class__.__name__])        self.write("(")        self.dispatch(t.operand)        self.write(")")     binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%",                    "LShift":">>", "RShift":"<<", "BitOr":"|", "BitXor":"^", "BitAnd":"&",                    "FloorDiv":"//", "Pow": "**"}    def _BinOp(self, t):        self.write("(")        self.dispatch(t.left)        self.write(")" + self.binop[t.op.__class__.__name__] + "(")        self.dispatch(t.right)        self.write(")")     cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=",                        "Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"}    def _Compare(self, t):        self.write("(")        self.dispatch(t.left)        for o, e in zip(t.ops, t.comparators):            self.write(") " +self.cmpops[o.__class__.__name__] + " (")            self.dispatch(e)            self.write(")")     boolops = {_ast.And: 'and', _ast.Or: 'or'}    def _BoolOp(self, t):        self.write("(")        self.dispatch(t.values[0])        for v in t.values[1:]:            self.write(" %s " % self.boolops[t.op.__class__])            self.dispatch(v)        self.write(")")     def _Attribute(self,t):        self.dispatch(t.value)        self.write(".")        self.write(t.attr)     def _Call(self, t):        self.dispatch(t.func)        self.write("(")        comma = False        for e in t.args:            if comma: self.write(", ")            else: comma = True            self.dispatch(e)        for e in t.keywords:            if comma: self.write(", ")            else: comma = True            self.dispatch(e)        if t.starargs:            if comma: self.write(", ")            else: comma = True            self.write("*")            self.dispatch(t.starargs)        if t.kwargs:            if comma: self.write(", ")            else: comma = True            self.write("**")            self.dispatch(t.kwargs)        self.write(")")     def _Subscript(self, t):        self.dispatch(t.value)        self.write("[")        self.dispatch(t.slice)        self.write("]")     # slice    def _Ellipsis(self, t):        self.write("...")     def _Index(self, t):        self.dispatch(t.value)     def _Slice(self, t):        if t.lower:            self.dispatch(t.lower)        self.write(":")        if t.upper:            self.dispatch(t.upper)        if t.step:            self.write(":")            self.dispatch(t.step)     def _ExtSlice(self, t):        for i, d in enumerate(t.dims):            if i != 0:                self.write(': ')            self.dispatch(d)     # others    def _arguments(self, t):        first = True        nonDef = len(t.args)-len(t.defaults)        for a in t.args[0:nonDef]:            if first:first = False            else: self.write(", ")            self.dispatch(a)        for a,d in zip(t.args[nonDef:], t.defaults):            if first:first = False            else: self.write(", ")            self.dispatch(a),            self.write("=")            self.dispatch(d)        if t.vararg:            if first:first = False            else: self.write(", ")            self.write("*"+t.vararg)        if t.kwarg:            if first:first = False            else: self.write(", ")            self.write("**"+t.kwarg)     def _keyword(self, t):        self.write(t.arg)        self.write("=")        self.dispatch(t.value)     def _Lambda(self, t):        self.write("lambda ")        self.dispatch(t.args)        self.write(": ")        self.dispatch(t.body) def roundtrip(filename, output=sys.stdout):    source = open(filename).read()    tree = compile(source, filename, "exec", 0x400)    Unparser(tree, output)   def testdir(a):    try:        names = [n for n in os.listdir(a) if n.endswith('.py')]    except OSError:        print >> sys.stderr, "Directory not readable: %s" % a    else:        for n in names:            fullname = os.path.join(a, n)            if os.path.isfile(fullname):

Lines 1–500 of 519.