blob: fa8f43441b618724355b17dc5a355930e3fb144e [file] [log] [blame]
Tim Peters400cbc32006-02-28 18:44:41 +00001"Usage: unparse.py <path to source file>"
2import sys
Mark Dickinson8042e282010-06-29 10:01:48 +00003import math
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +00004import ast
Mark Dickinson82c8d932010-06-29 07:48:23 +00005import tokenize
Collin Winter6f2df4d2007-07-17 20:59:35 +00006import io
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00007import os
Tim Peters400cbc32006-02-28 18:44:41 +00008
Guido van Rossumd8faa362007-04-27 19:54:29 +00009def interleave(inter, f, seq):
10 """Call f on each item in seq, calling inter() in between.
11 """
12 seq = iter(seq)
13 try:
Collin Winter6f2df4d2007-07-17 20:59:35 +000014 f(next(seq))
Guido van Rossumd8faa362007-04-27 19:54:29 +000015 except StopIteration:
16 pass
17 else:
18 for x in seq:
19 inter()
20 f(x)
21
Tim Peters400cbc32006-02-28 18:44:41 +000022class Unparser:
23 """Methods in this class recursively traverse an AST and
24 output source code for the abstract syntax; original formatting
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000025 is disregarded. """
Tim Peters400cbc32006-02-28 18:44:41 +000026
27 def __init__(self, tree, file = sys.stdout):
28 """Unparser(tree, file=sys.stdout) -> None.
29 Print the source for tree to file."""
30 self.f = file
31 self._indent = 0
32 self.dispatch(tree)
Collin Winter6f2df4d2007-07-17 20:59:35 +000033 print("", file=self.f)
Tim Peters400cbc32006-02-28 18:44:41 +000034 self.f.flush()
35
36 def fill(self, text = ""):
37 "Indent a piece of text, according to the current indentation level"
38 self.f.write("\n"+" "*self._indent + text)
39
40 def write(self, text):
41 "Append a piece of text to the current line."
42 self.f.write(text)
43
44 def enter(self):
45 "Print ':', and increase the indentation."
46 self.write(":")
47 self._indent += 1
48
49 def leave(self):
50 "Decrease the indentation level."
51 self._indent -= 1
52
53 def dispatch(self, tree):
54 "Dispatcher function, dispatching tree type T to method _T."
55 if isinstance(tree, list):
56 for t in tree:
57 self.dispatch(t)
58 return
59 meth = getattr(self, "_"+tree.__class__.__name__)
60 meth(tree)
61
62
63 ############### Unparsing methods ######################
64 # There should be one method per concrete grammar type #
65 # Constructors should be grouped by sum type. Ideally, #
66 # this would follow the order in the grammar, but #
67 # currently doesn't. #
68 ########################################################
69
70 def _Module(self, tree):
71 for stmt in tree.body:
72 self.dispatch(stmt)
73
74 # stmt
75 def _Expr(self, tree):
76 self.fill()
77 self.dispatch(tree.value)
78
79 def _Import(self, t):
80 self.fill("import ")
Guido van Rossumd8faa362007-04-27 19:54:29 +000081 interleave(lambda: self.write(", "), self.dispatch, t.names)
Tim Peters400cbc32006-02-28 18:44:41 +000082
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000083 def _ImportFrom(self, t):
84 self.fill("from ")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000085 self.write("." * t.level)
86 if t.module:
87 self.write(t.module)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000088 self.write(" import ")
Guido van Rossumd8faa362007-04-27 19:54:29 +000089 interleave(lambda: self.write(", "), self.dispatch, t.names)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000090
Tim Peters400cbc32006-02-28 18:44:41 +000091 def _Assign(self, t):
92 self.fill()
93 for target in t.targets:
94 self.dispatch(target)
95 self.write(" = ")
96 self.dispatch(t.value)
97
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +000098 def _AugAssign(self, t):
99 self.fill()
100 self.dispatch(t.target)
101 self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
102 self.dispatch(t.value)
103
104 def _Return(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000105 self.fill("return")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000106 if t.value:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000107 self.write(" ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000108 self.dispatch(t.value)
109
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000110 def _Pass(self, t):
111 self.fill("pass")
112
113 def _Break(self, t):
114 self.fill("break")
115
116 def _Continue(self, t):
117 self.fill("continue")
118
119 def _Delete(self, t):
120 self.fill("del ")
Mark Dickinsonae100052010-06-28 19:44:20 +0000121 interleave(lambda: self.write(", "), self.dispatch, t.targets)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000122
123 def _Assert(self, t):
124 self.fill("assert ")
125 self.dispatch(t.test)
126 if t.msg:
127 self.write(", ")
128 self.dispatch(t.msg)
129
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000130 def _Global(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000131 self.fill("global ")
132 interleave(lambda: self.write(", "), self.write, t.names)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000133
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000134 def _Nonlocal(self, t):
135 self.fill("nonlocal ")
136 interleave(lambda: self.write(", "), self.write, t.names)
137
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000138 def _Yield(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000139 self.write("(")
140 self.write("yield")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000141 if t.value:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000142 self.write(" ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000143 self.dispatch(t.value)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000144 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000145
146 def _Raise(self, t):
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000147 self.fill("raise")
148 if not t.exc:
149 assert not t.cause
150 return
151 self.write(" ")
152 self.dispatch(t.exc)
153 if t.cause:
154 self.write(" from ")
155 self.dispatch(t.cause)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000156
157 def _TryExcept(self, t):
158 self.fill("try")
159 self.enter()
160 self.dispatch(t.body)
161 self.leave()
162
163 for ex in t.handlers:
164 self.dispatch(ex)
165 if t.orelse:
166 self.fill("else")
167 self.enter()
168 self.dispatch(t.orelse)
169 self.leave()
170
171 def _TryFinally(self, t):
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000172 if len(t.body) == 1 and isinstance(t.body[0], ast.TryExcept):
173 # try-except-finally
174 self.dispatch(t.body)
175 else:
176 self.fill("try")
177 self.enter()
178 self.dispatch(t.body)
179 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000180
181 self.fill("finally")
182 self.enter()
183 self.dispatch(t.finalbody)
184 self.leave()
185
Benjamin Petersonc4fe6f32008-08-19 18:57:56 +0000186 def _ExceptHandler(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000187 self.fill("except")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000188 if t.type:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000189 self.write(" ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000190 self.dispatch(t.type)
191 if t.name:
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000192 self.write(" as ")
193 self.write(t.name)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000194 self.enter()
195 self.dispatch(t.body)
196 self.leave()
197
Tim Peters400cbc32006-02-28 18:44:41 +0000198 def _ClassDef(self, t):
199 self.write("\n")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000200 for deco in t.decorator_list:
201 self.fill("@")
202 self.dispatch(deco)
Tim Peters400cbc32006-02-28 18:44:41 +0000203 self.fill("class "+t.name)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000204 self.write("(")
205 comma = False
206 for e in t.bases:
207 if comma: self.write(", ")
208 else: comma = True
209 self.dispatch(e)
210 for e in t.keywords:
211 if comma: self.write(", ")
212 else: comma = True
213 self.dispatch(e)
214 if t.starargs:
215 if comma: self.write(", ")
216 else: comma = True
217 self.write("*")
218 self.dispatch(t.starargs)
219 if t.kwargs:
220 if comma: self.write(", ")
221 else: comma = True
Mark Dickinson578aa562010-06-29 18:38:59 +0000222 self.write("**")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000223 self.dispatch(t.kwargs)
224 self.write(")")
225
Tim Peters400cbc32006-02-28 18:44:41 +0000226 self.enter()
227 self.dispatch(t.body)
228 self.leave()
229
230 def _FunctionDef(self, t):
231 self.write("\n")
Benjamin Petersonc4fe6f32008-08-19 18:57:56 +0000232 for deco in t.decorator_list:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000233 self.fill("@")
234 self.dispatch(deco)
Tim Peters400cbc32006-02-28 18:44:41 +0000235 self.fill("def "+t.name + "(")
236 self.dispatch(t.args)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000237 self.write(")")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000238 if t.returns:
239 self.write(" -> ")
240 self.dispatch(t.returns)
Tim Peters400cbc32006-02-28 18:44:41 +0000241 self.enter()
242 self.dispatch(t.body)
243 self.leave()
244
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000245 def _For(self, t):
246 self.fill("for ")
247 self.dispatch(t.target)
248 self.write(" in ")
249 self.dispatch(t.iter)
250 self.enter()
251 self.dispatch(t.body)
252 self.leave()
253 if t.orelse:
254 self.fill("else")
255 self.enter()
256 self.dispatch(t.orelse)
Mark Dickinsonae100052010-06-28 19:44:20 +0000257 self.leave()
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000258
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000259 def _If(self, t):
260 self.fill("if ")
261 self.dispatch(t.test)
262 self.enter()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000263 self.dispatch(t.body)
264 self.leave()
Mark Dickinson8d6d7602010-06-30 08:32:11 +0000265 # collapse nested ifs into equivalent elifs.
266 while (t.orelse and len(t.orelse) == 1 and
267 isinstance(t.orelse[0], ast.If)):
268 t = t.orelse[0]
269 self.fill("elif ")
270 self.dispatch(t.test)
271 self.enter()
272 self.dispatch(t.body)
273 self.leave()
274 # final else
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000275 if t.orelse:
276 self.fill("else")
277 self.enter()
278 self.dispatch(t.orelse)
279 self.leave()
280
281 def _While(self, t):
282 self.fill("while ")
283 self.dispatch(t.test)
284 self.enter()
285 self.dispatch(t.body)
286 self.leave()
287 if t.orelse:
288 self.fill("else")
289 self.enter()
290 self.dispatch(t.orelse)
Mark Dickinsonae100052010-06-28 19:44:20 +0000291 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000292
293 def _With(self, t):
294 self.fill("with ")
295 self.dispatch(t.context_expr)
296 if t.optional_vars:
297 self.write(" as ")
298 self.dispatch(t.optional_vars)
299 self.enter()
300 self.dispatch(t.body)
301 self.leave()
302
Tim Peters400cbc32006-02-28 18:44:41 +0000303 # expr
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000304 def _Bytes(self, t):
305 self.write(repr(t.s))
306
Tim Peters400cbc32006-02-28 18:44:41 +0000307 def _Str(self, tree):
308 self.write(repr(tree.s))
309
310 def _Name(self, t):
311 self.write(t.id)
312
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000313 def _Repr(self, t):
314 self.write("`")
315 self.dispatch(t.value)
316 self.write("`")
317
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000318 def _Num(self, t):
Mark Dickinson8042e282010-06-29 10:01:48 +0000319 if isinstance(t.n, float):
320 # A float literal should be nonnegative, and not a nan.
321 # It could be an infinity, though; in that case we
322 # substitute an overflowing decimal value.
323 assert not math.isnan(t.n)
324 assert math.copysign(1.0, t.n) > 0.0
325 if math.isinf(t.n):
326 self.write("1e" + repr(sys.float_info.max_10_exp + 1))
327 else:
328 self.write(repr(t.n))
329 else:
330 # Parenthesize integer literals to avoid turning
331 # "3 .__abs__()" into "3.__abs__()".
332 self.write("(")
333 self.write(repr(t.n))
334 self.write(")")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000335
Tim Peters400cbc32006-02-28 18:44:41 +0000336 def _List(self, t):
337 self.write("[")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000338 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Tim Peters400cbc32006-02-28 18:44:41 +0000339 self.write("]")
340
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000341 def _ListComp(self, t):
342 self.write("[")
343 self.dispatch(t.elt)
344 for gen in t.generators:
345 self.dispatch(gen)
346 self.write("]")
347
348 def _GeneratorExp(self, t):
349 self.write("(")
350 self.dispatch(t.elt)
351 for gen in t.generators:
352 self.dispatch(gen)
353 self.write(")")
354
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000355 def _SetComp(self, t):
356 self.write("{")
357 self.dispatch(t.elt)
358 for gen in t.generators:
359 self.dispatch(gen)
360 self.write("}")
361
362 def _DictComp(self, t):
363 self.write("{")
364 self.dispatch(t.key)
365 self.write(": ")
366 self.dispatch(t.value)
367 for gen in t.generators:
368 self.dispatch(gen)
369 self.write("}")
370
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000371 def _comprehension(self, t):
372 self.write(" for ")
373 self.dispatch(t.target)
374 self.write(" in ")
375 self.dispatch(t.iter)
376 for if_clause in t.ifs:
377 self.write(" if ")
378 self.dispatch(if_clause)
379
380 def _IfExp(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000381 self.write("(")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000382 self.dispatch(t.body)
383 self.write(" if ")
384 self.dispatch(t.test)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000385 self.write(" else ")
386 self.dispatch(t.orelse)
387 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000388
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000389 def _Set(self, t):
390 assert(t.elts) # should be at least one element
391 self.write("{")
392 interleave(lambda: self.write(", "), self.dispatch, t.elts)
393 self.write("}")
394
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000395 def _Dict(self, t):
396 self.write("{")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000397 def write_pair(pair):
398 (k, v) = pair
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000399 self.dispatch(k)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000400 self.write(": ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000401 self.dispatch(v)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000402 interleave(lambda: self.write(", "), write_pair, zip(t.keys, t.values))
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000403 self.write("}")
404
405 def _Tuple(self, t):
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000406 self.write("(")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000407 if len(t.elts) == 1:
408 (elt,) = t.elts
409 self.dispatch(elt)
410 self.write(",")
411 else:
412 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000413 self.write(")")
414
Tim Peters400cbc32006-02-28 18:44:41 +0000415 unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}
416 def _UnaryOp(self, t):
Tim Peters400cbc32006-02-28 18:44:41 +0000417 self.write("(")
Mark Dickinsonae100052010-06-28 19:44:20 +0000418 self.write(self.unop[t.op.__class__.__name__])
419 self.write(" ")
Tim Peters400cbc32006-02-28 18:44:41 +0000420 self.dispatch(t.operand)
421 self.write(")")
422
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000423 binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%",
Mark Dickinsonae100052010-06-28 19:44:20 +0000424 "LShift":"<<", "RShift":">>", "BitOr":"|", "BitXor":"^", "BitAnd":"&",
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000425 "FloorDiv":"//", "Pow": "**"}
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000426 def _BinOp(self, t):
427 self.write("(")
428 self.dispatch(t.left)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000429 self.write(" " + self.binop[t.op.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000430 self.dispatch(t.right)
431 self.write(")")
432
433 cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=",
434 "Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"}
435 def _Compare(self, t):
436 self.write("(")
437 self.dispatch(t.left)
438 for o, e in zip(t.ops, t.comparators):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000439 self.write(" " + self.cmpops[o.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000440 self.dispatch(e)
Mark Dickinsonf5451e52010-06-28 20:09:18 +0000441 self.write(")")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000442
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000443 boolops = {ast.And: 'and', ast.Or: 'or'}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000444 def _BoolOp(self, t):
445 self.write("(")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000446 s = " %s " % self.boolops[t.op.__class__]
447 interleave(lambda: self.write(s), self.dispatch, t.values)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000448 self.write(")")
449
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000450 def _Attribute(self,t):
451 self.dispatch(t.value)
452 self.write(".")
453 self.write(t.attr)
454
455 def _Call(self, t):
456 self.dispatch(t.func)
457 self.write("(")
458 comma = False
459 for e in t.args:
460 if comma: self.write(", ")
461 else: comma = True
462 self.dispatch(e)
463 for e in t.keywords:
464 if comma: self.write(", ")
465 else: comma = True
466 self.dispatch(e)
467 if t.starargs:
468 if comma: self.write(", ")
469 else: comma = True
470 self.write("*")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000471 self.dispatch(t.starargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000472 if t.kwargs:
473 if comma: self.write(", ")
474 else: comma = True
475 self.write("**")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000476 self.dispatch(t.kwargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000477 self.write(")")
478
479 def _Subscript(self, t):
480 self.dispatch(t.value)
481 self.write("[")
482 self.dispatch(t.slice)
483 self.write("]")
484
485 # slice
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000486 def _Ellipsis(self, t):
487 self.write("...")
488
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000489 def _Index(self, t):
490 self.dispatch(t.value)
491
492 def _Slice(self, t):
493 if t.lower:
494 self.dispatch(t.lower)
495 self.write(":")
496 if t.upper:
497 self.dispatch(t.upper)
498 if t.step:
499 self.write(":")
500 self.dispatch(t.step)
501
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000502 def _ExtSlice(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000503 interleave(lambda: self.write(', '), self.dispatch, t.dims)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000504
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000505 # argument
506 def _arg(self, t):
507 self.write(t.arg)
508 if t.annotation:
509 self.write(": ")
510 self.dispatch(t.annotation)
511
Tim Peters400cbc32006-02-28 18:44:41 +0000512 # others
513 def _arguments(self, t):
514 first = True
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000515 # normal arguments
516 defaults = [None] * (len(t.args) - len(t.defaults)) + t.defaults
517 for a, d in zip(t.args, defaults):
Tim Peters400cbc32006-02-28 18:44:41 +0000518 if first:first = False
519 else: self.write(", ")
520 self.dispatch(a)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000521 if d:
522 self.write("=")
523 self.dispatch(d)
524
525 # varargs, or bare '*' if no varargs but keyword-only arguments present
526 if t.vararg or t.kwonlyargs:
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000527 if first:first = False
528 else: self.write(", ")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000529 self.write("*")
530 if t.vararg:
531 self.write(t.vararg)
532 if t.varargannotation:
533 self.write(": ")
534 self.dispatch(t.varargannotation)
535
536 # keyword-only arguments
537 if t.kwonlyargs:
538 for a, d in zip(t.kwonlyargs, t.kw_defaults):
539 if first:first = False
540 else: self.write(", ")
541 self.dispatch(a),
542 if d:
543 self.write("=")
544 self.dispatch(d)
545
546 # kwargs
Tim Peters400cbc32006-02-28 18:44:41 +0000547 if t.kwarg:
548 if first:first = False
549 else: self.write(", ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000550 self.write("**"+t.kwarg)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000551 if t.kwargannotation:
552 self.write(": ")
553 self.dispatch(t.kwargannotation)
Tim Peters400cbc32006-02-28 18:44:41 +0000554
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000555 def _keyword(self, t):
556 self.write(t.arg)
557 self.write("=")
558 self.dispatch(t.value)
559
560 def _Lambda(self, t):
Mark Dickinson8042e282010-06-29 10:01:48 +0000561 self.write("(")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000562 self.write("lambda ")
563 self.dispatch(t.args)
564 self.write(": ")
565 self.dispatch(t.body)
Mark Dickinson8042e282010-06-29 10:01:48 +0000566 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000567
Guido van Rossumd8faa362007-04-27 19:54:29 +0000568 def _alias(self, t):
569 self.write(t.name)
570 if t.asname:
571 self.write(" as "+t.asname)
572
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000573def roundtrip(filename, output=sys.stdout):
Mark Dickinson82c8d932010-06-29 07:48:23 +0000574 with open(filename, "rb") as pyfile:
575 encoding = tokenize.detect_encoding(pyfile.readline)[0]
576 with open(filename, "r", encoding=encoding) as pyfile:
577 source = pyfile.read()
Mark Dickinson3d1bfbf2010-06-28 21:39:51 +0000578 tree = compile(source, filename, "exec", ast.PyCF_ONLY_AST)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000579 Unparser(tree, output)
580
581
582
583def testdir(a):
584 try:
585 names = [n for n in os.listdir(a) if n.endswith('.py')]
586 except OSError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000587 print("Directory not readable: %s" % a, file=sys.stderr)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000588 else:
589 for n in names:
590 fullname = os.path.join(a, n)
591 if os.path.isfile(fullname):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000592 output = io.StringIO()
593 print('Testing %s' % fullname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000594 try:
595 roundtrip(fullname, output)
Guido van Rossumb940e112007-01-10 16:19:56 +0000596 except Exception as e:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000597 print(' Failed to compile, exception is %s' % repr(e))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000598 elif os.path.isdir(fullname):
599 testdir(fullname)
600
601def main(args):
602 if args[0] == '--testdir':
603 for a in args[1:]:
604 testdir(a)
605 else:
606 for a in args:
607 roundtrip(a)
Tim Peters400cbc32006-02-28 18:44:41 +0000608
609if __name__=='__main__':
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000610 main(sys.argv[1:])