blob: 2c383a5eaced94daeb62b50bfecf67ed8806e69e [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
Mark Dickinson82c8d932010-06-29 07:48:23 +00004import tokenize
Collin Winter6f2df4d2007-07-17 20:59:35 +00005import io
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00006import os
Tim Peters400cbc32006-02-28 18:44:41 +00007
Guido van Rossumd8faa362007-04-27 19:54:29 +00008def interleave(inter, f, seq):
9 """Call f on each item in seq, calling inter() in between.
10 """
11 seq = iter(seq)
12 try:
Collin Winter6f2df4d2007-07-17 20:59:35 +000013 f(next(seq))
Guido van Rossumd8faa362007-04-27 19:54:29 +000014 except StopIteration:
15 pass
16 else:
17 for x in seq:
18 inter()
19 f(x)
20
Tim Peters400cbc32006-02-28 18:44:41 +000021class Unparser:
22 """Methods in this class recursively traverse an AST and
23 output source code for the abstract syntax; original formatting
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000024 is disregarded. """
Tim Peters400cbc32006-02-28 18:44:41 +000025
26 def __init__(self, tree, file = sys.stdout):
27 """Unparser(tree, file=sys.stdout) -> None.
28 Print the source for tree to file."""
29 self.f = file
30 self._indent = 0
31 self.dispatch(tree)
Collin Winter6f2df4d2007-07-17 20:59:35 +000032 print("", file=self.f)
Tim Peters400cbc32006-02-28 18:44:41 +000033 self.f.flush()
34
35 def fill(self, text = ""):
36 "Indent a piece of text, according to the current indentation level"
37 self.f.write("\n"+" "*self._indent + text)
38
39 def write(self, text):
40 "Append a piece of text to the current line."
41 self.f.write(text)
42
43 def enter(self):
44 "Print ':', and increase the indentation."
45 self.write(":")
46 self._indent += 1
47
48 def leave(self):
49 "Decrease the indentation level."
50 self._indent -= 1
51
52 def dispatch(self, tree):
53 "Dispatcher function, dispatching tree type T to method _T."
54 if isinstance(tree, list):
55 for t in tree:
56 self.dispatch(t)
57 return
58 meth = getattr(self, "_"+tree.__class__.__name__)
59 meth(tree)
60
61
62 ############### Unparsing methods ######################
63 # There should be one method per concrete grammar type #
64 # Constructors should be grouped by sum type. Ideally, #
65 # this would follow the order in the grammar, but #
66 # currently doesn't. #
67 ########################################################
68
69 def _Module(self, tree):
70 for stmt in tree.body:
71 self.dispatch(stmt)
72
73 # stmt
74 def _Expr(self, tree):
75 self.fill()
76 self.dispatch(tree.value)
77
78 def _Import(self, t):
79 self.fill("import ")
Guido van Rossumd8faa362007-04-27 19:54:29 +000080 interleave(lambda: self.write(", "), self.dispatch, t.names)
Tim Peters400cbc32006-02-28 18:44:41 +000081
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000082 def _ImportFrom(self, t):
83 self.fill("from ")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000084 self.write("." * t.level)
85 if t.module:
86 self.write(t.module)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000087 self.write(" import ")
Guido van Rossumd8faa362007-04-27 19:54:29 +000088 interleave(lambda: self.write(", "), self.dispatch, t.names)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000089
Tim Peters400cbc32006-02-28 18:44:41 +000090 def _Assign(self, t):
91 self.fill()
92 for target in t.targets:
93 self.dispatch(target)
94 self.write(" = ")
95 self.dispatch(t.value)
96
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +000097 def _AugAssign(self, t):
98 self.fill()
99 self.dispatch(t.target)
100 self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
101 self.dispatch(t.value)
102
103 def _Return(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000104 self.fill("return")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000105 if t.value:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000106 self.write(" ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000107 self.dispatch(t.value)
108
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000109 def _Pass(self, t):
110 self.fill("pass")
111
112 def _Break(self, t):
113 self.fill("break")
114
115 def _Continue(self, t):
116 self.fill("continue")
117
118 def _Delete(self, t):
119 self.fill("del ")
Mark Dickinsonae100052010-06-28 19:44:20 +0000120 interleave(lambda: self.write(", "), self.dispatch, t.targets)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000121
122 def _Assert(self, t):
123 self.fill("assert ")
124 self.dispatch(t.test)
125 if t.msg:
126 self.write(", ")
127 self.dispatch(t.msg)
128
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000129 def _Global(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000130 self.fill("global ")
131 interleave(lambda: self.write(", "), self.write, t.names)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000132
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000133 def _Nonlocal(self, t):
134 self.fill("nonlocal ")
135 interleave(lambda: self.write(", "), self.write, t.names)
136
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000137 def _Yield(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000138 self.write("(")
139 self.write("yield")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000140 if t.value:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000141 self.write(" ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000142 self.dispatch(t.value)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000143 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000144
145 def _Raise(self, t):
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000146 self.fill("raise")
147 if not t.exc:
148 assert not t.cause
149 return
150 self.write(" ")
151 self.dispatch(t.exc)
152 if t.cause:
153 self.write(" from ")
154 self.dispatch(t.cause)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000155
156 def _TryExcept(self, t):
157 self.fill("try")
158 self.enter()
159 self.dispatch(t.body)
160 self.leave()
161
162 for ex in t.handlers:
163 self.dispatch(ex)
164 if t.orelse:
165 self.fill("else")
166 self.enter()
167 self.dispatch(t.orelse)
168 self.leave()
169
170 def _TryFinally(self, t):
171 self.fill("try")
172 self.enter()
173 self.dispatch(t.body)
174 self.leave()
175
176 self.fill("finally")
177 self.enter()
178 self.dispatch(t.finalbody)
179 self.leave()
180
Benjamin Petersonc4fe6f32008-08-19 18:57:56 +0000181 def _ExceptHandler(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000182 self.fill("except")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000183 if t.type:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000184 self.write(" ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000185 self.dispatch(t.type)
186 if t.name:
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000187 self.write(" as ")
188 self.write(t.name)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000189 self.enter()
190 self.dispatch(t.body)
191 self.leave()
192
Tim Peters400cbc32006-02-28 18:44:41 +0000193 def _ClassDef(self, t):
194 self.write("\n")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000195 for deco in t.decorator_list:
196 self.fill("@")
197 self.dispatch(deco)
Tim Peters400cbc32006-02-28 18:44:41 +0000198 self.fill("class "+t.name)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000199 self.write("(")
200 comma = False
201 for e in t.bases:
202 if comma: self.write(", ")
203 else: comma = True
204 self.dispatch(e)
205 for e in t.keywords:
206 if comma: self.write(", ")
207 else: comma = True
208 self.dispatch(e)
209 if t.starargs:
210 if comma: self.write(", ")
211 else: comma = True
212 self.write("*")
213 self.dispatch(t.starargs)
214 if t.kwargs:
215 if comma: self.write(", ")
216 else: comma = True
217 self.write("*")
218 self.dispatch(t.kwargs)
219 self.write(")")
220
Tim Peters400cbc32006-02-28 18:44:41 +0000221 self.enter()
222 self.dispatch(t.body)
223 self.leave()
224
225 def _FunctionDef(self, t):
226 self.write("\n")
Benjamin Petersonc4fe6f32008-08-19 18:57:56 +0000227 for deco in t.decorator_list:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000228 self.fill("@")
229 self.dispatch(deco)
Tim Peters400cbc32006-02-28 18:44:41 +0000230 self.fill("def "+t.name + "(")
231 self.dispatch(t.args)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000232 self.write(")")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000233 if t.returns:
234 self.write(" -> ")
235 self.dispatch(t.returns)
Tim Peters400cbc32006-02-28 18:44:41 +0000236 self.enter()
237 self.dispatch(t.body)
238 self.leave()
239
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000240 def _For(self, t):
241 self.fill("for ")
242 self.dispatch(t.target)
243 self.write(" in ")
244 self.dispatch(t.iter)
245 self.enter()
246 self.dispatch(t.body)
247 self.leave()
248 if t.orelse:
249 self.fill("else")
250 self.enter()
251 self.dispatch(t.orelse)
Mark Dickinsonae100052010-06-28 19:44:20 +0000252 self.leave()
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000253
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000254 def _If(self, t):
255 self.fill("if ")
256 self.dispatch(t.test)
257 self.enter()
258 # XXX elif?
259 self.dispatch(t.body)
260 self.leave()
261 if t.orelse:
262 self.fill("else")
263 self.enter()
264 self.dispatch(t.orelse)
265 self.leave()
266
267 def _While(self, t):
268 self.fill("while ")
269 self.dispatch(t.test)
270 self.enter()
271 self.dispatch(t.body)
272 self.leave()
273 if t.orelse:
274 self.fill("else")
275 self.enter()
276 self.dispatch(t.orelse)
Mark Dickinsonae100052010-06-28 19:44:20 +0000277 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000278
279 def _With(self, t):
280 self.fill("with ")
281 self.dispatch(t.context_expr)
282 if t.optional_vars:
283 self.write(" as ")
284 self.dispatch(t.optional_vars)
285 self.enter()
286 self.dispatch(t.body)
287 self.leave()
288
Tim Peters400cbc32006-02-28 18:44:41 +0000289 # expr
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000290 def _Bytes(self, t):
291 self.write(repr(t.s))
292
Tim Peters400cbc32006-02-28 18:44:41 +0000293 def _Str(self, tree):
294 self.write(repr(tree.s))
295
296 def _Name(self, t):
297 self.write(t.id)
298
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000299 def _Repr(self, t):
300 self.write("`")
301 self.dispatch(t.value)
302 self.write("`")
303
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000304 def _Num(self, t):
Mark Dickinson3eb02902010-06-29 08:52:36 +0000305 # Add parentheses around numeric literals to avoid:
306 #
307 # (1) turning (-1)**2 into -1**2, and
308 # (2) turning 3 .__abs__() into 3.__abs__()
309 #
310 # For (1), note that Python doesn't actually have negative
311 # numeric literals, but (at least in Python 2.x) there's a CST
312 # transformation that can produce negative Nums in the AST.
313 self.write("(")
314 self.write(repr(t.n))
315 self.write(")")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000316
Tim Peters400cbc32006-02-28 18:44:41 +0000317 def _List(self, t):
318 self.write("[")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000319 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Tim Peters400cbc32006-02-28 18:44:41 +0000320 self.write("]")
321
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000322 def _ListComp(self, t):
323 self.write("[")
324 self.dispatch(t.elt)
325 for gen in t.generators:
326 self.dispatch(gen)
327 self.write("]")
328
329 def _GeneratorExp(self, t):
330 self.write("(")
331 self.dispatch(t.elt)
332 for gen in t.generators:
333 self.dispatch(gen)
334 self.write(")")
335
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000336 def _SetComp(self, t):
337 self.write("{")
338 self.dispatch(t.elt)
339 for gen in t.generators:
340 self.dispatch(gen)
341 self.write("}")
342
343 def _DictComp(self, t):
344 self.write("{")
345 self.dispatch(t.key)
346 self.write(": ")
347 self.dispatch(t.value)
348 for gen in t.generators:
349 self.dispatch(gen)
350 self.write("}")
351
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000352 def _comprehension(self, t):
353 self.write(" for ")
354 self.dispatch(t.target)
355 self.write(" in ")
356 self.dispatch(t.iter)
357 for if_clause in t.ifs:
358 self.write(" if ")
359 self.dispatch(if_clause)
360
361 def _IfExp(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000362 self.write("(")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000363 self.dispatch(t.body)
364 self.write(" if ")
365 self.dispatch(t.test)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000366 self.write(" else ")
367 self.dispatch(t.orelse)
368 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000369
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000370 def _Set(self, t):
371 assert(t.elts) # should be at least one element
372 self.write("{")
373 interleave(lambda: self.write(", "), self.dispatch, t.elts)
374 self.write("}")
375
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000376 def _Dict(self, t):
377 self.write("{")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000378 def write_pair(pair):
379 (k, v) = pair
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000380 self.dispatch(k)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000381 self.write(": ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000382 self.dispatch(v)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000383 interleave(lambda: self.write(", "), write_pair, zip(t.keys, t.values))
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000384 self.write("}")
385
386 def _Tuple(self, t):
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000387 self.write("(")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000388 if len(t.elts) == 1:
389 (elt,) = t.elts
390 self.dispatch(elt)
391 self.write(",")
392 else:
393 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000394 self.write(")")
395
Tim Peters400cbc32006-02-28 18:44:41 +0000396 unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}
397 def _UnaryOp(self, t):
Tim Peters400cbc32006-02-28 18:44:41 +0000398 self.write("(")
Mark Dickinsonae100052010-06-28 19:44:20 +0000399 self.write(self.unop[t.op.__class__.__name__])
400 self.write(" ")
Tim Peters400cbc32006-02-28 18:44:41 +0000401 self.dispatch(t.operand)
402 self.write(")")
403
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000404 binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%",
Mark Dickinsonae100052010-06-28 19:44:20 +0000405 "LShift":"<<", "RShift":">>", "BitOr":"|", "BitXor":"^", "BitAnd":"&",
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000406 "FloorDiv":"//", "Pow": "**"}
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000407 def _BinOp(self, t):
408 self.write("(")
409 self.dispatch(t.left)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000410 self.write(" " + self.binop[t.op.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000411 self.dispatch(t.right)
412 self.write(")")
413
414 cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=",
415 "Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"}
416 def _Compare(self, t):
417 self.write("(")
418 self.dispatch(t.left)
419 for o, e in zip(t.ops, t.comparators):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000420 self.write(" " + self.cmpops[o.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000421 self.dispatch(e)
Mark Dickinsonf5451e52010-06-28 20:09:18 +0000422 self.write(")")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000423
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000424 boolops = {ast.And: 'and', ast.Or: 'or'}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000425 def _BoolOp(self, t):
426 self.write("(")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000427 s = " %s " % self.boolops[t.op.__class__]
428 interleave(lambda: self.write(s), self.dispatch, t.values)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000429 self.write(")")
430
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000431 def _Attribute(self,t):
432 self.dispatch(t.value)
433 self.write(".")
434 self.write(t.attr)
435
436 def _Call(self, t):
437 self.dispatch(t.func)
438 self.write("(")
439 comma = False
440 for e in t.args:
441 if comma: self.write(", ")
442 else: comma = True
443 self.dispatch(e)
444 for e in t.keywords:
445 if comma: self.write(", ")
446 else: comma = True
447 self.dispatch(e)
448 if t.starargs:
449 if comma: self.write(", ")
450 else: comma = True
451 self.write("*")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000452 self.dispatch(t.starargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000453 if t.kwargs:
454 if comma: self.write(", ")
455 else: comma = True
456 self.write("**")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000457 self.dispatch(t.kwargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000458 self.write(")")
459
460 def _Subscript(self, t):
461 self.dispatch(t.value)
462 self.write("[")
463 self.dispatch(t.slice)
464 self.write("]")
465
466 # slice
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000467 def _Ellipsis(self, t):
468 self.write("...")
469
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000470 def _Index(self, t):
471 self.dispatch(t.value)
472
473 def _Slice(self, t):
474 if t.lower:
475 self.dispatch(t.lower)
476 self.write(":")
477 if t.upper:
478 self.dispatch(t.upper)
479 if t.step:
480 self.write(":")
481 self.dispatch(t.step)
482
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000483 def _ExtSlice(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000484 interleave(lambda: self.write(', '), self.dispatch, t.dims)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000485
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000486 # argument
487 def _arg(self, t):
488 self.write(t.arg)
489 if t.annotation:
490 self.write(": ")
491 self.dispatch(t.annotation)
492
Tim Peters400cbc32006-02-28 18:44:41 +0000493 # others
494 def _arguments(self, t):
495 first = True
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000496 # normal arguments
497 defaults = [None] * (len(t.args) - len(t.defaults)) + t.defaults
498 for a, d in zip(t.args, defaults):
Tim Peters400cbc32006-02-28 18:44:41 +0000499 if first:first = False
500 else: self.write(", ")
501 self.dispatch(a)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000502 if d:
503 self.write("=")
504 self.dispatch(d)
505
506 # varargs, or bare '*' if no varargs but keyword-only arguments present
507 if t.vararg or t.kwonlyargs:
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000508 if first:first = False
509 else: self.write(", ")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000510 self.write("*")
511 if t.vararg:
512 self.write(t.vararg)
513 if t.varargannotation:
514 self.write(": ")
515 self.dispatch(t.varargannotation)
516
517 # keyword-only arguments
518 if t.kwonlyargs:
519 for a, d in zip(t.kwonlyargs, t.kw_defaults):
520 if first:first = False
521 else: self.write(", ")
522 self.dispatch(a),
523 if d:
524 self.write("=")
525 self.dispatch(d)
526
527 # kwargs
Tim Peters400cbc32006-02-28 18:44:41 +0000528 if t.kwarg:
529 if first:first = False
530 else: self.write(", ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000531 self.write("**"+t.kwarg)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000532 if t.kwargannotation:
533 self.write(": ")
534 self.dispatch(t.kwargannotation)
Tim Peters400cbc32006-02-28 18:44:41 +0000535
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000536 def _keyword(self, t):
537 self.write(t.arg)
538 self.write("=")
539 self.dispatch(t.value)
540
541 def _Lambda(self, t):
542 self.write("lambda ")
543 self.dispatch(t.args)
544 self.write(": ")
545 self.dispatch(t.body)
546
Guido van Rossumd8faa362007-04-27 19:54:29 +0000547 def _alias(self, t):
548 self.write(t.name)
549 if t.asname:
550 self.write(" as "+t.asname)
551
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000552def roundtrip(filename, output=sys.stdout):
Mark Dickinson82c8d932010-06-29 07:48:23 +0000553 with open(filename, "rb") as pyfile:
554 encoding = tokenize.detect_encoding(pyfile.readline)[0]
555 with open(filename, "r", encoding=encoding) as pyfile:
556 source = pyfile.read()
Mark Dickinson3d1bfbf2010-06-28 21:39:51 +0000557 tree = compile(source, filename, "exec", ast.PyCF_ONLY_AST)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000558 Unparser(tree, output)
559
560
561
562def testdir(a):
563 try:
564 names = [n for n in os.listdir(a) if n.endswith('.py')]
565 except OSError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000566 print("Directory not readable: %s" % a, file=sys.stderr)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000567 else:
568 for n in names:
569 fullname = os.path.join(a, n)
570 if os.path.isfile(fullname):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000571 output = io.StringIO()
572 print('Testing %s' % fullname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000573 try:
574 roundtrip(fullname, output)
Guido van Rossumb940e112007-01-10 16:19:56 +0000575 except Exception as e:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000576 print(' Failed to compile, exception is %s' % repr(e))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000577 elif os.path.isdir(fullname):
578 testdir(fullname)
579
580def main(args):
581 if args[0] == '--testdir':
582 for a in args[1:]:
583 testdir(a)
584 else:
585 for a in args:
586 roundtrip(a)
Tim Peters400cbc32006-02-28 18:44:41 +0000587
588if __name__=='__main__':
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000589 main(sys.argv[1:])