blob: d48ddd1b2832b3633452511a84452c9047781302 [file] [log] [blame]
Tim Peters400cbc32006-02-28 18:44:41 +00001"Usage: unparse.py <path to source file>"
2import sys
Martin v. Löwis3fa6c092006-04-10 12:43:55 +00003import _ast
4import cStringIO
5import os
Tim Peters400cbc32006-02-28 18:44:41 +00006
Georg Brandl124df832007-03-19 19:02:48 +00007def interleave(inter, f, seq):
8 """Call f on each item in seq, calling inter() in between.
9 """
10 seq = iter(seq)
11 try:
12 f(seq.next())
Tim Peters35c7bb22007-04-25 18:47:18 +000013 except StopIteration:
Georg Brandl124df832007-03-19 19:02:48 +000014 pass
15 else:
16 for x in seq:
17 inter()
18 f(x)
19
Tim Peters400cbc32006-02-28 18:44:41 +000020class Unparser:
21 """Methods in this class recursively traverse an AST and
22 output source code for the abstract syntax; original formatting
23 is disregarged. """
24
25 def __init__(self, tree, file = sys.stdout):
26 """Unparser(tree, file=sys.stdout) -> None.
27 Print the source for tree to file."""
28 self.f = file
29 self._indent = 0
30 self.dispatch(tree)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +000031 print >>self.f,""
Tim Peters400cbc32006-02-28 18:44:41 +000032 self.f.flush()
33
34 def fill(self, text = ""):
35 "Indent a piece of text, according to the current indentation level"
36 self.f.write("\n"+" "*self._indent + text)
37
38 def write(self, text):
39 "Append a piece of text to the current line."
40 self.f.write(text)
41
42 def enter(self):
43 "Print ':', and increase the indentation."
44 self.write(":")
45 self._indent += 1
46
47 def leave(self):
48 "Decrease the indentation level."
49 self._indent -= 1
50
51 def dispatch(self, tree):
52 "Dispatcher function, dispatching tree type T to method _T."
53 if isinstance(tree, list):
54 for t in tree:
55 self.dispatch(t)
56 return
57 meth = getattr(self, "_"+tree.__class__.__name__)
58 meth(tree)
59
60
61 ############### Unparsing methods ######################
62 # There should be one method per concrete grammar type #
63 # Constructors should be grouped by sum type. Ideally, #
64 # this would follow the order in the grammar, but #
65 # currently doesn't. #
66 ########################################################
67
68 def _Module(self, tree):
69 for stmt in tree.body:
70 self.dispatch(stmt)
71
72 # stmt
73 def _Expr(self, tree):
74 self.fill()
75 self.dispatch(tree.value)
76
77 def _Import(self, t):
78 self.fill("import ")
Georg Brandl124df832007-03-19 19:02:48 +000079 interleave(lambda: self.write(", "), self.dispatch, t.names)
Tim Peters3daf3042006-04-10 20:28:40 +000080
Martin v. Löwis3fa6c092006-04-10 12:43:55 +000081 def _ImportFrom(self, t):
82 self.fill("from ")
83 self.write(t.module)
84 self.write(" import ")
Georg Brandl124df832007-03-19 19:02:48 +000085 interleave(lambda: self.write(", "), self.dispatch, t.names)
Martin v. Löwis3fa6c092006-04-10 12:43:55 +000086 # XXX(jpe) what is level for?
Tim Peters400cbc32006-02-28 18:44:41 +000087
88 def _Assign(self, t):
89 self.fill()
90 for target in t.targets:
91 self.dispatch(target)
92 self.write(" = ")
93 self.dispatch(t.value)
94
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +000095 def _AugAssign(self, t):
96 self.fill()
97 self.dispatch(t.target)
98 self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
99 self.dispatch(t.value)
100
101 def _Return(self, t):
Georg Brandl124df832007-03-19 19:02:48 +0000102 self.fill("return")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000103 if t.value:
Georg Brandl124df832007-03-19 19:02:48 +0000104 self.write(" ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000105 self.dispatch(t.value)
106
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000107 def _Pass(self, t):
108 self.fill("pass")
Tim Peters3daf3042006-04-10 20:28:40 +0000109
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000110 def _Break(self, t):
111 self.fill("break")
112
113 def _Continue(self, t):
114 self.fill("continue")
Tim Peters3daf3042006-04-10 20:28:40 +0000115
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000116 def _Delete(self, t):
117 self.fill("del ")
Mark Dickinson623b9792010-06-28 19:31:41 +0000118 interleave(lambda: self.write(", "), self.dispatch, t.targets)
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000119
120 def _Assert(self, t):
121 self.fill("assert ")
122 self.dispatch(t.test)
123 if t.msg:
124 self.write(", ")
125 self.dispatch(t.msg)
Tim Peters3daf3042006-04-10 20:28:40 +0000126
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000127 def _Exec(self, t):
128 self.fill("exec ")
129 self.dispatch(t.body)
130 if t.globals:
131 self.write(" in ")
132 self.dispatch(t.globals)
133 if t.locals:
134 self.write(", ")
135 self.dispatch(t.locals)
136
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000137 def _Print(self, t):
138 self.fill("print ")
139 do_comma = False
140 if t.dest:
141 self.write(">>")
142 self.dispatch(t.dest)
143 do_comma = True
144 for e in t.values:
145 if do_comma:self.write(", ")
146 else:do_comma=True
147 self.dispatch(e)
148 if not t.nl:
149 self.write(",")
150
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000151 def _Global(self, t):
Georg Brandl124df832007-03-19 19:02:48 +0000152 self.fill("global ")
153 interleave(lambda: self.write(", "), self.write, t.names)
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000154
155 def _Yield(self, t):
Georg Brandl124df832007-03-19 19:02:48 +0000156 self.write("(")
157 self.write("yield")
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000158 if t.value:
Georg Brandl124df832007-03-19 19:02:48 +0000159 self.write(" ")
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000160 self.dispatch(t.value)
Georg Brandl124df832007-03-19 19:02:48 +0000161 self.write(")")
Tim Peters3daf3042006-04-10 20:28:40 +0000162
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000163 def _Raise(self, t):
164 self.fill('raise ')
165 if t.type:
166 self.dispatch(t.type)
167 if t.inst:
168 self.write(", ")
169 self.dispatch(t.inst)
170 if t.tback:
171 self.write(", ")
172 self.dispatch(t.tback)
Tim Peters3daf3042006-04-10 20:28:40 +0000173
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000174 def _TryExcept(self, t):
175 self.fill("try")
176 self.enter()
177 self.dispatch(t.body)
178 self.leave()
Tim Peters3daf3042006-04-10 20:28:40 +0000179
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000180 for ex in t.handlers:
181 self.dispatch(ex)
182 if t.orelse:
183 self.fill("else")
184 self.enter()
185 self.dispatch(t.orelse)
186 self.leave()
187
188 def _TryFinally(self, t):
189 self.fill("try")
190 self.enter()
191 self.dispatch(t.body)
192 self.leave()
193
194 self.fill("finally")
195 self.enter()
196 self.dispatch(t.finalbody)
197 self.leave()
198
Benjamin Peterson7c972f92008-08-19 17:59:23 +0000199 def _ExceptHandler(self, t):
Georg Brandl124df832007-03-19 19:02:48 +0000200 self.fill("except")
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000201 if t.type:
Georg Brandl124df832007-03-19 19:02:48 +0000202 self.write(" ")
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000203 self.dispatch(t.type)
204 if t.name:
205 self.write(", ")
206 self.dispatch(t.name)
207 self.enter()
208 self.dispatch(t.body)
209 self.leave()
Tim Peters3daf3042006-04-10 20:28:40 +0000210
Tim Peters400cbc32006-02-28 18:44:41 +0000211 def _ClassDef(self, t):
212 self.write("\n")
213 self.fill("class "+t.name)
214 if t.bases:
215 self.write("(")
216 for a in t.bases:
217 self.dispatch(a)
218 self.write(", ")
219 self.write(")")
220 self.enter()
221 self.dispatch(t.body)
222 self.leave()
223
224 def _FunctionDef(self, t):
225 self.write("\n")
Benjamin Peterson7c972f92008-08-19 17:59:23 +0000226 for deco in t.decorator_list:
Georg Brandl27562782006-10-27 20:39:43 +0000227 self.fill("@")
228 self.dispatch(deco)
Tim Peters400cbc32006-02-28 18:44:41 +0000229 self.fill("def "+t.name + "(")
230 self.dispatch(t.args)
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000231 self.write(")")
Tim Peters400cbc32006-02-28 18:44:41 +0000232 self.enter()
233 self.dispatch(t.body)
234 self.leave()
235
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000236 def _For(self, t):
237 self.fill("for ")
238 self.dispatch(t.target)
239 self.write(" in ")
240 self.dispatch(t.iter)
241 self.enter()
242 self.dispatch(t.body)
243 self.leave()
244 if t.orelse:
245 self.fill("else")
246 self.enter()
247 self.dispatch(t.orelse)
Mark Dickinson623b9792010-06-28 19:31:41 +0000248 self.leave()
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000249
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000250 def _If(self, t):
251 self.fill("if ")
252 self.dispatch(t.test)
253 self.enter()
254 # XXX elif?
255 self.dispatch(t.body)
256 self.leave()
257 if t.orelse:
258 self.fill("else")
259 self.enter()
260 self.dispatch(t.orelse)
261 self.leave()
262
263 def _While(self, t):
264 self.fill("while ")
265 self.dispatch(t.test)
266 self.enter()
267 self.dispatch(t.body)
268 self.leave()
269 if t.orelse:
270 self.fill("else")
271 self.enter()
272 self.dispatch(t.orelse)
Mark Dickinson623b9792010-06-28 19:31:41 +0000273 self.leave()
Tim Peters3daf3042006-04-10 20:28:40 +0000274
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000275 def _With(self, t):
276 self.fill("with ")
277 self.dispatch(t.context_expr)
278 if t.optional_vars:
279 self.write(" as ")
280 self.dispatch(t.optional_vars)
281 self.enter()
282 self.dispatch(t.body)
283 self.leave()
284
Tim Peters400cbc32006-02-28 18:44:41 +0000285 # expr
286 def _Str(self, tree):
287 self.write(repr(tree.s))
288
289 def _Name(self, t):
290 self.write(t.id)
291
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000292 def _Repr(self, t):
293 self.write("`")
294 self.dispatch(t.value)
295 self.write("`")
Tim Peters3daf3042006-04-10 20:28:40 +0000296
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000297 def _Num(self, t):
Mark Dickinson623b9792010-06-28 19:31:41 +0000298 # There are no negative numeric literals in Python; however,
299 # some optimizations produce a negative Num in the AST. Add
300 # parentheses to avoid turning (-1)**2 into -1**2.
301 strnum = repr(t.n)
302 if strnum.startswith("-"):
303 self.write("(")
304 self.write(strnum)
305 self.write(")")
306 else:
307 self.write(repr(t.n))
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000308
Tim Peters400cbc32006-02-28 18:44:41 +0000309 def _List(self, t):
310 self.write("[")
Georg Brandl124df832007-03-19 19:02:48 +0000311 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Tim Peters400cbc32006-02-28 18:44:41 +0000312 self.write("]")
313
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000314 def _ListComp(self, t):
315 self.write("[")
316 self.dispatch(t.elt)
317 for gen in t.generators:
318 self.dispatch(gen)
319 self.write("]")
Tim Peters3daf3042006-04-10 20:28:40 +0000320
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000321 def _GeneratorExp(self, t):
322 self.write("(")
323 self.dispatch(t.elt)
324 for gen in t.generators:
325 self.dispatch(gen)
326 self.write(")")
Tim Peters3daf3042006-04-10 20:28:40 +0000327
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000328 def _comprehension(self, t):
329 self.write(" for ")
330 self.dispatch(t.target)
331 self.write(" in ")
332 self.dispatch(t.iter)
333 for if_clause in t.ifs:
334 self.write(" if ")
335 self.dispatch(if_clause)
336
337 def _IfExp(self, t):
Georg Brandl124df832007-03-19 19:02:48 +0000338 self.write("(")
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000339 self.dispatch(t.body)
340 self.write(" if ")
341 self.dispatch(t.test)
Georg Brandl124df832007-03-19 19:02:48 +0000342 self.write(" else ")
343 self.dispatch(t.orelse)
344 self.write(")")
Tim Peters3daf3042006-04-10 20:28:40 +0000345
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000346 def _Dict(self, t):
347 self.write("{")
Georg Brandl124df832007-03-19 19:02:48 +0000348 def writem((k, v)):
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000349 self.dispatch(k)
Georg Brandl124df832007-03-19 19:02:48 +0000350 self.write(": ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000351 self.dispatch(v)
Georg Brandl124df832007-03-19 19:02:48 +0000352 interleave(lambda: self.write(", "), writem, zip(t.keys, t.values))
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000353 self.write("}")
354
355 def _Tuple(self, t):
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000356 self.write("(")
Georg Brandl124df832007-03-19 19:02:48 +0000357 if len(t.elts) == 1:
358 (elt,) = t.elts
359 self.dispatch(elt)
360 self.write(",")
361 else:
362 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000363 self.write(")")
364
Tim Peters400cbc32006-02-28 18:44:41 +0000365 unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}
366 def _UnaryOp(self, t):
Tim Peters400cbc32006-02-28 18:44:41 +0000367 self.write("(")
Mark Dickinson623b9792010-06-28 19:31:41 +0000368 self.write(self.unop[t.op.__class__.__name__])
369 self.write(" ")
Tim Peters400cbc32006-02-28 18:44:41 +0000370 self.dispatch(t.operand)
371 self.write(")")
372
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000373 binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%",
Mark Dickinson623b9792010-06-28 19:31:41 +0000374 "LShift":"<<", "RShift":">>", "BitOr":"|", "BitXor":"^", "BitAnd":"&",
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000375 "FloorDiv":"//", "Pow": "**"}
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000376 def _BinOp(self, t):
377 self.write("(")
378 self.dispatch(t.left)
Georg Brandl124df832007-03-19 19:02:48 +0000379 self.write(" " + self.binop[t.op.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000380 self.dispatch(t.right)
381 self.write(")")
382
383 cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=",
384 "Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"}
385 def _Compare(self, t):
386 self.write("(")
387 self.dispatch(t.left)
388 for o, e in zip(t.ops, t.comparators):
Georg Brandl124df832007-03-19 19:02:48 +0000389 self.write(" " + self.cmpops[o.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000390 self.dispatch(e)
391 self.write(")")
392
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000393 boolops = {_ast.And: 'and', _ast.Or: 'or'}
394 def _BoolOp(self, t):
395 self.write("(")
Georg Brandl124df832007-03-19 19:02:48 +0000396 s = " %s " % self.boolops[t.op.__class__]
397 interleave(lambda: self.write(s), self.dispatch, t.values)
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000398 self.write(")")
Tim Peters3daf3042006-04-10 20:28:40 +0000399
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000400 def _Attribute(self,t):
401 self.dispatch(t.value)
402 self.write(".")
403 self.write(t.attr)
404
405 def _Call(self, t):
406 self.dispatch(t.func)
407 self.write("(")
408 comma = False
409 for e in t.args:
410 if comma: self.write(", ")
411 else: comma = True
412 self.dispatch(e)
413 for e in t.keywords:
414 if comma: self.write(", ")
415 else: comma = True
416 self.dispatch(e)
417 if t.starargs:
418 if comma: self.write(", ")
419 else: comma = True
420 self.write("*")
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000421 self.dispatch(t.starargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000422 if t.kwargs:
423 if comma: self.write(", ")
424 else: comma = True
425 self.write("**")
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000426 self.dispatch(t.kwargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000427 self.write(")")
428
429 def _Subscript(self, t):
430 self.dispatch(t.value)
431 self.write("[")
432 self.dispatch(t.slice)
433 self.write("]")
434
435 # slice
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000436 def _Ellipsis(self, t):
437 self.write("...")
Tim Peters3daf3042006-04-10 20:28:40 +0000438
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000439 def _Index(self, t):
440 self.dispatch(t.value)
441
442 def _Slice(self, t):
443 if t.lower:
444 self.dispatch(t.lower)
445 self.write(":")
446 if t.upper:
447 self.dispatch(t.upper)
448 if t.step:
449 self.write(":")
450 self.dispatch(t.step)
451
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000452 def _ExtSlice(self, t):
Georg Brandl124df832007-03-19 19:02:48 +0000453 interleave(lambda: self.write(', '), self.dispatch, t.dims)
Tim Peters3daf3042006-04-10 20:28:40 +0000454
Tim Peters400cbc32006-02-28 18:44:41 +0000455 # others
456 def _arguments(self, t):
457 first = True
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000458 nonDef = len(t.args)-len(t.defaults)
459 for a in t.args[0:nonDef]:
Tim Peters400cbc32006-02-28 18:44:41 +0000460 if first:first = False
461 else: self.write(", ")
462 self.dispatch(a)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000463 for a,d in zip(t.args[nonDef:], t.defaults):
464 if first:first = False
465 else: self.write(", ")
466 self.dispatch(a),
467 self.write("=")
468 self.dispatch(d)
Tim Peters400cbc32006-02-28 18:44:41 +0000469 if t.vararg:
470 if first:first = False
471 else: self.write(", ")
472 self.write("*"+t.vararg)
473 if t.kwarg:
474 if first:first = False
475 else: self.write(", ")
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000476 self.write("**"+t.kwarg)
Tim Peters400cbc32006-02-28 18:44:41 +0000477
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000478 def _keyword(self, t):
479 self.write(t.arg)
480 self.write("=")
481 self.dispatch(t.value)
Tim Peters3daf3042006-04-10 20:28:40 +0000482
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000483 def _Lambda(self, t):
484 self.write("lambda ")
485 self.dispatch(t.args)
486 self.write(": ")
487 self.dispatch(t.body)
Tim Peters3daf3042006-04-10 20:28:40 +0000488
Georg Brandl124df832007-03-19 19:02:48 +0000489 def _alias(self, t):
490 self.write(t.name)
491 if t.asname:
492 self.write(" as "+t.asname)
493
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000494def roundtrip(filename, output=sys.stdout):
Tim Peters400cbc32006-02-28 18:44:41 +0000495 source = open(filename).read()
Georg Brandl124df832007-03-19 19:02:48 +0000496 tree = compile(source, filename, "exec", _ast.PyCF_ONLY_AST)
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000497 Unparser(tree, output)
Tim Peters400cbc32006-02-28 18:44:41 +0000498
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000499
500
501def testdir(a):
502 try:
503 names = [n for n in os.listdir(a) if n.endswith('.py')]
504 except OSError:
505 print >> sys.stderr, "Directory not readable: %s" % a
506 else:
507 for n in names:
508 fullname = os.path.join(a, n)
509 if os.path.isfile(fullname):
510 output = cStringIO.StringIO()
511 print 'Testing %s' % fullname
512 try:
513 roundtrip(fullname, output)
514 except Exception, e:
515 print ' Failed to compile, exception is %s' % repr(e)
516 elif os.path.isdir(fullname):
517 testdir(fullname)
518
519def main(args):
520 if args[0] == '--testdir':
521 for a in args[1:]:
522 testdir(a)
523 else:
524 for a in args:
525 roundtrip(a)
Tim Peters3daf3042006-04-10 20:28:40 +0000526
Tim Peters400cbc32006-02-28 18:44:41 +0000527if __name__=='__main__':
Martin v. Löwis3fa6c092006-04-10 12:43:55 +0000528 main(sys.argv[1:])