blob: 715f98b514fc2aba2daddf5411d0ab84872dae47 [file] [log] [blame]
Tim Peters400cbc32006-02-28 18:44:41 +00001"Usage: unparse.py <path to source file>"
2import sys
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +00003import ast
Collin Winter6f2df4d2007-07-17 20:59:35 +00004import io
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005import os
Tim Peters400cbc32006-02-28 18:44:41 +00006
Guido van Rossumd8faa362007-04-27 19:54:29 +00007def interleave(inter, f, seq):
8 """Call f on each item in seq, calling inter() in between.
9 """
10 seq = iter(seq)
11 try:
Collin Winter6f2df4d2007-07-17 20:59:35 +000012 f(next(seq))
Guido van Rossumd8faa362007-04-27 19:54:29 +000013 except StopIteration:
14 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
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000023 is disregarded. """
Tim Peters400cbc32006-02-28 18:44:41 +000024
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)
Collin Winter6f2df4d2007-07-17 20:59:35 +000031 print("", file=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 ")
Guido van Rossumd8faa362007-04-27 19:54:29 +000079 interleave(lambda: self.write(", "), self.dispatch, t.names)
Tim Peters400cbc32006-02-28 18:44:41 +000080
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000081 def _ImportFrom(self, t):
82 self.fill("from ")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000083 self.write("." * t.level)
84 if t.module:
85 self.write(t.module)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000086 self.write(" import ")
Guido van Rossumd8faa362007-04-27 19:54:29 +000087 interleave(lambda: self.write(", "), self.dispatch, t.names)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000088
Tim Peters400cbc32006-02-28 18:44:41 +000089 def _Assign(self, t):
90 self.fill()
91 for target in t.targets:
92 self.dispatch(target)
93 self.write(" = ")
94 self.dispatch(t.value)
95
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +000096 def _AugAssign(self, t):
97 self.fill()
98 self.dispatch(t.target)
99 self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
100 self.dispatch(t.value)
101
102 def _Return(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000103 self.fill("return")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000104 if t.value:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000105 self.write(" ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000106 self.dispatch(t.value)
107
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000108 def _Pass(self, t):
109 self.fill("pass")
110
111 def _Break(self, t):
112 self.fill("break")
113
114 def _Continue(self, t):
115 self.fill("continue")
116
117 def _Delete(self, t):
118 self.fill("del ")
Mark Dickinsonae100052010-06-28 19:44:20 +0000119 interleave(lambda: self.write(", "), self.dispatch, t.targets)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000120
121 def _Assert(self, t):
122 self.fill("assert ")
123 self.dispatch(t.test)
124 if t.msg:
125 self.write(", ")
126 self.dispatch(t.msg)
127
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000128 def _Global(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000129 self.fill("global ")
130 interleave(lambda: self.write(", "), self.write, t.names)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000131
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000132 def _Nonlocal(self, t):
133 self.fill("nonlocal ")
134 interleave(lambda: self.write(", "), self.write, t.names)
135
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000136 def _Yield(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000137 self.write("(")
138 self.write("yield")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000139 if t.value:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000140 self.write(" ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000141 self.dispatch(t.value)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000142 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000143
144 def _Raise(self, t):
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000145 self.fill("raise")
146 if not t.exc:
147 assert not t.cause
148 return
149 self.write(" ")
150 self.dispatch(t.exc)
151 if t.cause:
152 self.write(" from ")
153 self.dispatch(t.cause)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000154
155 def _TryExcept(self, t):
156 self.fill("try")
157 self.enter()
158 self.dispatch(t.body)
159 self.leave()
160
161 for ex in t.handlers:
162 self.dispatch(ex)
163 if t.orelse:
164 self.fill("else")
165 self.enter()
166 self.dispatch(t.orelse)
167 self.leave()
168
169 def _TryFinally(self, t):
170 self.fill("try")
171 self.enter()
172 self.dispatch(t.body)
173 self.leave()
174
175 self.fill("finally")
176 self.enter()
177 self.dispatch(t.finalbody)
178 self.leave()
179
Benjamin Petersonc4fe6f32008-08-19 18:57:56 +0000180 def _ExceptHandler(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000181 self.fill("except")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000182 if t.type:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000183 self.write(" ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000184 self.dispatch(t.type)
185 if t.name:
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000186 self.write(" as ")
187 self.write(t.name)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000188 self.enter()
189 self.dispatch(t.body)
190 self.leave()
191
Tim Peters400cbc32006-02-28 18:44:41 +0000192 def _ClassDef(self, t):
193 self.write("\n")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000194 for deco in t.decorator_list:
195 self.fill("@")
196 self.dispatch(deco)
Tim Peters400cbc32006-02-28 18:44:41 +0000197 self.fill("class "+t.name)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000198 self.write("(")
199 comma = False
200 for e in t.bases:
201 if comma: self.write(", ")
202 else: comma = True
203 self.dispatch(e)
204 for e in t.keywords:
205 if comma: self.write(", ")
206 else: comma = True
207 self.dispatch(e)
208 if t.starargs:
209 if comma: self.write(", ")
210 else: comma = True
211 self.write("*")
212 self.dispatch(t.starargs)
213 if t.kwargs:
214 if comma: self.write(", ")
215 else: comma = True
216 self.write("*")
217 self.dispatch(t.kwargs)
218 self.write(")")
219
Tim Peters400cbc32006-02-28 18:44:41 +0000220 self.enter()
221 self.dispatch(t.body)
222 self.leave()
223
224 def _FunctionDef(self, t):
225 self.write("\n")
Benjamin Petersonc4fe6f32008-08-19 18:57:56 +0000226 for deco in t.decorator_list:
Thomas Wouters89f507f2006-12-13 04:49:30 +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)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000231 self.write(")")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000232 if t.returns:
233 self.write(" -> ")
234 self.dispatch(t.returns)
Tim Peters400cbc32006-02-28 18:44:41 +0000235 self.enter()
236 self.dispatch(t.body)
237 self.leave()
238
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000239 def _For(self, t):
240 self.fill("for ")
241 self.dispatch(t.target)
242 self.write(" in ")
243 self.dispatch(t.iter)
244 self.enter()
245 self.dispatch(t.body)
246 self.leave()
247 if t.orelse:
248 self.fill("else")
249 self.enter()
250 self.dispatch(t.orelse)
Mark Dickinsonae100052010-06-28 19:44:20 +0000251 self.leave()
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000252
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000253 def _If(self, t):
254 self.fill("if ")
255 self.dispatch(t.test)
256 self.enter()
257 # XXX elif?
258 self.dispatch(t.body)
259 self.leave()
260 if t.orelse:
261 self.fill("else")
262 self.enter()
263 self.dispatch(t.orelse)
264 self.leave()
265
266 def _While(self, t):
267 self.fill("while ")
268 self.dispatch(t.test)
269 self.enter()
270 self.dispatch(t.body)
271 self.leave()
272 if t.orelse:
273 self.fill("else")
274 self.enter()
275 self.dispatch(t.orelse)
Mark Dickinsonae100052010-06-28 19:44:20 +0000276 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000277
278 def _With(self, t):
279 self.fill("with ")
280 self.dispatch(t.context_expr)
281 if t.optional_vars:
282 self.write(" as ")
283 self.dispatch(t.optional_vars)
284 self.enter()
285 self.dispatch(t.body)
286 self.leave()
287
Tim Peters400cbc32006-02-28 18:44:41 +0000288 # expr
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000289 def _Bytes(self, t):
290 self.write(repr(t.s))
291
Tim Peters400cbc32006-02-28 18:44:41 +0000292 def _Str(self, tree):
293 self.write(repr(tree.s))
294
295 def _Name(self, t):
296 self.write(t.id)
297
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000298 def _Repr(self, t):
299 self.write("`")
300 self.dispatch(t.value)
301 self.write("`")
302
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000303 def _Num(self, t):
Mark Dickinsonae100052010-06-28 19:44:20 +0000304 # There are no negative numeric literals in Python; however,
305 # some optimizations produce a negative Num in the AST. Add
306 # parentheses to avoid turning (-1)**2 into -1**2.
307 strnum = repr(t.n)
308 if strnum.startswith("-"):
309 self.write("(")
310 self.write(strnum)
311 self.write(")")
312 else:
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000313 self.write(strnum)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000314
Tim Peters400cbc32006-02-28 18:44:41 +0000315 def _List(self, t):
316 self.write("[")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000317 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Tim Peters400cbc32006-02-28 18:44:41 +0000318 self.write("]")
319
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000320 def _ListComp(self, t):
321 self.write("[")
322 self.dispatch(t.elt)
323 for gen in t.generators:
324 self.dispatch(gen)
325 self.write("]")
326
327 def _GeneratorExp(self, t):
328 self.write("(")
329 self.dispatch(t.elt)
330 for gen in t.generators:
331 self.dispatch(gen)
332 self.write(")")
333
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000334 def _SetComp(self, t):
335 self.write("{")
336 self.dispatch(t.elt)
337 for gen in t.generators:
338 self.dispatch(gen)
339 self.write("}")
340
341 def _DictComp(self, t):
342 self.write("{")
343 self.dispatch(t.key)
344 self.write(": ")
345 self.dispatch(t.value)
346 for gen in t.generators:
347 self.dispatch(gen)
348 self.write("}")
349
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000350 def _comprehension(self, t):
351 self.write(" for ")
352 self.dispatch(t.target)
353 self.write(" in ")
354 self.dispatch(t.iter)
355 for if_clause in t.ifs:
356 self.write(" if ")
357 self.dispatch(if_clause)
358
359 def _IfExp(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000360 self.write("(")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000361 self.dispatch(t.body)
362 self.write(" if ")
363 self.dispatch(t.test)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000364 self.write(" else ")
365 self.dispatch(t.orelse)
366 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000367
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000368 def _Set(self, t):
369 assert(t.elts) # should be at least one element
370 self.write("{")
371 interleave(lambda: self.write(", "), self.dispatch, t.elts)
372 self.write("}")
373
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000374 def _Dict(self, t):
375 self.write("{")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000376 def write_pair(pair):
377 (k, v) = pair
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000378 self.dispatch(k)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000379 self.write(": ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000380 self.dispatch(v)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000381 interleave(lambda: self.write(", "), write_pair, zip(t.keys, t.values))
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000382 self.write("}")
383
384 def _Tuple(self, t):
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000385 self.write("(")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000386 if len(t.elts) == 1:
387 (elt,) = t.elts
388 self.dispatch(elt)
389 self.write(",")
390 else:
391 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000392 self.write(")")
393
Tim Peters400cbc32006-02-28 18:44:41 +0000394 unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}
395 def _UnaryOp(self, t):
Tim Peters400cbc32006-02-28 18:44:41 +0000396 self.write("(")
Mark Dickinsonae100052010-06-28 19:44:20 +0000397 self.write(self.unop[t.op.__class__.__name__])
398 self.write(" ")
Tim Peters400cbc32006-02-28 18:44:41 +0000399 self.dispatch(t.operand)
400 self.write(")")
401
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000402 binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%",
Mark Dickinsonae100052010-06-28 19:44:20 +0000403 "LShift":"<<", "RShift":">>", "BitOr":"|", "BitXor":"^", "BitAnd":"&",
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000404 "FloorDiv":"//", "Pow": "**"}
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000405 def _BinOp(self, t):
406 self.write("(")
407 self.dispatch(t.left)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000408 self.write(" " + self.binop[t.op.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000409 self.dispatch(t.right)
410 self.write(")")
411
412 cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=",
413 "Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"}
414 def _Compare(self, t):
415 self.write("(")
416 self.dispatch(t.left)
417 for o, e in zip(t.ops, t.comparators):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000418 self.write(" " + self.cmpops[o.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000419 self.dispatch(e)
Mark Dickinsonf5451e52010-06-28 20:09:18 +0000420 self.write(")")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000421
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000422 boolops = {ast.And: 'and', ast.Or: 'or'}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000423 def _BoolOp(self, t):
424 self.write("(")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000425 s = " %s " % self.boolops[t.op.__class__]
426 interleave(lambda: self.write(s), self.dispatch, t.values)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000427 self.write(")")
428
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000429 def _Attribute(self,t):
430 self.dispatch(t.value)
431 self.write(".")
432 self.write(t.attr)
433
434 def _Call(self, t):
435 self.dispatch(t.func)
436 self.write("(")
437 comma = False
438 for e in t.args:
439 if comma: self.write(", ")
440 else: comma = True
441 self.dispatch(e)
442 for e in t.keywords:
443 if comma: self.write(", ")
444 else: comma = True
445 self.dispatch(e)
446 if t.starargs:
447 if comma: self.write(", ")
448 else: comma = True
449 self.write("*")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000450 self.dispatch(t.starargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000451 if t.kwargs:
452 if comma: self.write(", ")
453 else: comma = True
454 self.write("**")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000455 self.dispatch(t.kwargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000456 self.write(")")
457
458 def _Subscript(self, t):
459 self.dispatch(t.value)
460 self.write("[")
461 self.dispatch(t.slice)
462 self.write("]")
463
464 # slice
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000465 def _Ellipsis(self, t):
466 self.write("...")
467
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000468 def _Index(self, t):
469 self.dispatch(t.value)
470
471 def _Slice(self, t):
472 if t.lower:
473 self.dispatch(t.lower)
474 self.write(":")
475 if t.upper:
476 self.dispatch(t.upper)
477 if t.step:
478 self.write(":")
479 self.dispatch(t.step)
480
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000481 def _ExtSlice(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000482 interleave(lambda: self.write(', '), self.dispatch, t.dims)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000483
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000484 # argument
485 def _arg(self, t):
486 self.write(t.arg)
487 if t.annotation:
488 self.write(": ")
489 self.dispatch(t.annotation)
490
Tim Peters400cbc32006-02-28 18:44:41 +0000491 # others
492 def _arguments(self, t):
493 first = True
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000494 # normal arguments
495 defaults = [None] * (len(t.args) - len(t.defaults)) + t.defaults
496 for a, d in zip(t.args, defaults):
Tim Peters400cbc32006-02-28 18:44:41 +0000497 if first:first = False
498 else: self.write(", ")
499 self.dispatch(a)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000500 if d:
501 self.write("=")
502 self.dispatch(d)
503
504 # varargs, or bare '*' if no varargs but keyword-only arguments present
505 if t.vararg or t.kwonlyargs:
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000506 if first:first = False
507 else: self.write(", ")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000508 self.write("*")
509 if t.vararg:
510 self.write(t.vararg)
511 if t.varargannotation:
512 self.write(": ")
513 self.dispatch(t.varargannotation)
514
515 # keyword-only arguments
516 if t.kwonlyargs:
517 for a, d in zip(t.kwonlyargs, t.kw_defaults):
518 if first:first = False
519 else: self.write(", ")
520 self.dispatch(a),
521 if d:
522 self.write("=")
523 self.dispatch(d)
524
525 # kwargs
Tim Peters400cbc32006-02-28 18:44:41 +0000526 if t.kwarg:
527 if first:first = False
528 else: self.write(", ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000529 self.write("**"+t.kwarg)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000530 if t.kwargannotation:
531 self.write(": ")
532 self.dispatch(t.kwargannotation)
Tim Peters400cbc32006-02-28 18:44:41 +0000533
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000534 def _keyword(self, t):
535 self.write(t.arg)
536 self.write("=")
537 self.dispatch(t.value)
538
539 def _Lambda(self, t):
540 self.write("lambda ")
541 self.dispatch(t.args)
542 self.write(": ")
543 self.dispatch(t.body)
544
Guido van Rossumd8faa362007-04-27 19:54:29 +0000545 def _alias(self, t):
546 self.write(t.name)
547 if t.asname:
548 self.write(" as "+t.asname)
549
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000550def roundtrip(filename, output=sys.stdout):
Tim Peters400cbc32006-02-28 18:44:41 +0000551 source = open(filename).read()
Guido van Rossumd8faa362007-04-27 19:54:29 +0000552 tree = compile(source, filename, "exec", _ast.PyCF_ONLY_AST)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000553 Unparser(tree, output)
554
555
556
557def testdir(a):
558 try:
559 names = [n for n in os.listdir(a) if n.endswith('.py')]
560 except OSError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000561 print("Directory not readable: %s" % a, file=sys.stderr)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000562 else:
563 for n in names:
564 fullname = os.path.join(a, n)
565 if os.path.isfile(fullname):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000566 output = io.StringIO()
567 print('Testing %s' % fullname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000568 try:
569 roundtrip(fullname, output)
Guido van Rossumb940e112007-01-10 16:19:56 +0000570 except Exception as e:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000571 print(' Failed to compile, exception is %s' % repr(e))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000572 elif os.path.isdir(fullname):
573 testdir(fullname)
574
575def main(args):
576 if args[0] == '--testdir':
577 for a in args[1:]:
578 testdir(a)
579 else:
580 for a in args:
581 roundtrip(a)
Tim Peters400cbc32006-02-28 18:44:41 +0000582
583if __name__=='__main__':
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000584 main(sys.argv[1:])