blob: 9ae5b469490f0970ab39510e918a71642fe322b7 [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
Mark Dickinsoncba8c102010-06-30 11:45:53 +00009# Large float and imaginary literals get turned into infinities in the AST.
10# We unparse those infinities to INFSTR.
11INFSTR = "1e" + repr(sys.float_info.max_10_exp + 1)
12
Guido van Rossumd8faa362007-04-27 19:54:29 +000013def interleave(inter, f, seq):
14 """Call f on each item in seq, calling inter() in between.
15 """
16 seq = iter(seq)
17 try:
Collin Winter6f2df4d2007-07-17 20:59:35 +000018 f(next(seq))
Guido van Rossumd8faa362007-04-27 19:54:29 +000019 except StopIteration:
20 pass
21 else:
22 for x in seq:
23 inter()
24 f(x)
25
Tim Peters400cbc32006-02-28 18:44:41 +000026class Unparser:
27 """Methods in this class recursively traverse an AST and
28 output source code for the abstract syntax; original formatting
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000029 is disregarded. """
Tim Peters400cbc32006-02-28 18:44:41 +000030
31 def __init__(self, tree, file = sys.stdout):
32 """Unparser(tree, file=sys.stdout) -> None.
33 Print the source for tree to file."""
34 self.f = file
35 self._indent = 0
36 self.dispatch(tree)
Collin Winter6f2df4d2007-07-17 20:59:35 +000037 print("", file=self.f)
Tim Peters400cbc32006-02-28 18:44:41 +000038 self.f.flush()
39
40 def fill(self, text = ""):
41 "Indent a piece of text, according to the current indentation level"
42 self.f.write("\n"+" "*self._indent + text)
43
44 def write(self, text):
45 "Append a piece of text to the current line."
46 self.f.write(text)
47
48 def enter(self):
49 "Print ':', and increase the indentation."
50 self.write(":")
51 self._indent += 1
52
53 def leave(self):
54 "Decrease the indentation level."
55 self._indent -= 1
56
57 def dispatch(self, tree):
58 "Dispatcher function, dispatching tree type T to method _T."
59 if isinstance(tree, list):
60 for t in tree:
61 self.dispatch(t)
62 return
63 meth = getattr(self, "_"+tree.__class__.__name__)
64 meth(tree)
65
66
67 ############### Unparsing methods ######################
68 # There should be one method per concrete grammar type #
69 # Constructors should be grouped by sum type. Ideally, #
70 # this would follow the order in the grammar, but #
71 # currently doesn't. #
72 ########################################################
73
74 def _Module(self, tree):
75 for stmt in tree.body:
76 self.dispatch(stmt)
77
78 # stmt
79 def _Expr(self, tree):
80 self.fill()
81 self.dispatch(tree.value)
82
83 def _Import(self, t):
84 self.fill("import ")
Guido van Rossumd8faa362007-04-27 19:54:29 +000085 interleave(lambda: self.write(", "), self.dispatch, t.names)
Tim Peters400cbc32006-02-28 18:44:41 +000086
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000087 def _ImportFrom(self, t):
88 self.fill("from ")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000089 self.write("." * t.level)
90 if t.module:
91 self.write(t.module)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000092 self.write(" import ")
Guido van Rossumd8faa362007-04-27 19:54:29 +000093 interleave(lambda: self.write(", "), self.dispatch, t.names)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000094
Tim Peters400cbc32006-02-28 18:44:41 +000095 def _Assign(self, t):
96 self.fill()
97 for target in t.targets:
98 self.dispatch(target)
99 self.write(" = ")
100 self.dispatch(t.value)
101
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000102 def _AugAssign(self, t):
103 self.fill()
104 self.dispatch(t.target)
105 self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
106 self.dispatch(t.value)
107
108 def _Return(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000109 self.fill("return")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000110 if t.value:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000111 self.write(" ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000112 self.dispatch(t.value)
113
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000114 def _Pass(self, t):
115 self.fill("pass")
116
117 def _Break(self, t):
118 self.fill("break")
119
120 def _Continue(self, t):
121 self.fill("continue")
122
123 def _Delete(self, t):
124 self.fill("del ")
Mark Dickinsonae100052010-06-28 19:44:20 +0000125 interleave(lambda: self.write(", "), self.dispatch, t.targets)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000126
127 def _Assert(self, t):
128 self.fill("assert ")
129 self.dispatch(t.test)
130 if t.msg:
131 self.write(", ")
132 self.dispatch(t.msg)
133
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000134 def _Global(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000135 self.fill("global ")
136 interleave(lambda: self.write(", "), self.write, t.names)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000137
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000138 def _Nonlocal(self, t):
139 self.fill("nonlocal ")
140 interleave(lambda: self.write(", "), self.write, t.names)
141
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000142 def _Yield(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000143 self.write("(")
144 self.write("yield")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000145 if t.value:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000146 self.write(" ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000147 self.dispatch(t.value)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000148 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000149
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100150 def _YieldFrom(self, t):
151 self.write("(")
152 self.write("yield from")
153 if t.value:
154 self.write(" ")
155 self.dispatch(t.value)
156 self.write(")")
157
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000158 def _Raise(self, t):
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000159 self.fill("raise")
160 if not t.exc:
161 assert not t.cause
162 return
163 self.write(" ")
164 self.dispatch(t.exc)
165 if t.cause:
166 self.write(" from ")
167 self.dispatch(t.cause)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000168
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100169 def _Try(self, t):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000170 self.fill("try")
171 self.enter()
172 self.dispatch(t.body)
173 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000174 for ex in t.handlers:
175 self.dispatch(ex)
176 if t.orelse:
177 self.fill("else")
178 self.enter()
179 self.dispatch(t.orelse)
180 self.leave()
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100181 if t.finalbody:
182 self.fill("finally")
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000183 self.enter()
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100184 self.dispatch(t.finalbody)
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000185 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000186
Benjamin Petersonc4fe6f32008-08-19 18:57:56 +0000187 def _ExceptHandler(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000188 self.fill("except")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000189 if t.type:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000190 self.write(" ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000191 self.dispatch(t.type)
192 if t.name:
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000193 self.write(" as ")
194 self.write(t.name)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000195 self.enter()
196 self.dispatch(t.body)
197 self.leave()
198
Tim Peters400cbc32006-02-28 18:44:41 +0000199 def _ClassDef(self, t):
200 self.write("\n")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000201 for deco in t.decorator_list:
202 self.fill("@")
203 self.dispatch(deco)
Tim Peters400cbc32006-02-28 18:44:41 +0000204 self.fill("class "+t.name)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000205 self.write("(")
206 comma = False
207 for e in t.bases:
208 if comma: self.write(", ")
209 else: comma = True
210 self.dispatch(e)
211 for e in t.keywords:
212 if comma: self.write(", ")
213 else: comma = True
214 self.dispatch(e)
215 if t.starargs:
216 if comma: self.write(", ")
217 else: comma = True
218 self.write("*")
219 self.dispatch(t.starargs)
220 if t.kwargs:
221 if comma: self.write(", ")
222 else: comma = True
Mark Dickinson578aa562010-06-29 18:38:59 +0000223 self.write("**")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000224 self.dispatch(t.kwargs)
225 self.write(")")
226
Tim Peters400cbc32006-02-28 18:44:41 +0000227 self.enter()
228 self.dispatch(t.body)
229 self.leave()
230
231 def _FunctionDef(self, t):
232 self.write("\n")
Benjamin Petersonc4fe6f32008-08-19 18:57:56 +0000233 for deco in t.decorator_list:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000234 self.fill("@")
235 self.dispatch(deco)
Tim Peters400cbc32006-02-28 18:44:41 +0000236 self.fill("def "+t.name + "(")
237 self.dispatch(t.args)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000238 self.write(")")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000239 if t.returns:
240 self.write(" -> ")
241 self.dispatch(t.returns)
Tim Peters400cbc32006-02-28 18:44:41 +0000242 self.enter()
243 self.dispatch(t.body)
244 self.leave()
245
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000246 def _For(self, t):
247 self.fill("for ")
248 self.dispatch(t.target)
249 self.write(" in ")
250 self.dispatch(t.iter)
251 self.enter()
252 self.dispatch(t.body)
253 self.leave()
254 if t.orelse:
255 self.fill("else")
256 self.enter()
257 self.dispatch(t.orelse)
Mark Dickinsonae100052010-06-28 19:44:20 +0000258 self.leave()
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000259
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000260 def _If(self, t):
261 self.fill("if ")
262 self.dispatch(t.test)
263 self.enter()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000264 self.dispatch(t.body)
265 self.leave()
Mark Dickinson8d6d7602010-06-30 08:32:11 +0000266 # collapse nested ifs into equivalent elifs.
267 while (t.orelse and len(t.orelse) == 1 and
268 isinstance(t.orelse[0], ast.If)):
269 t = t.orelse[0]
270 self.fill("elif ")
271 self.dispatch(t.test)
272 self.enter()
273 self.dispatch(t.body)
274 self.leave()
275 # final else
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000276 if t.orelse:
277 self.fill("else")
278 self.enter()
279 self.dispatch(t.orelse)
280 self.leave()
281
282 def _While(self, t):
283 self.fill("while ")
284 self.dispatch(t.test)
285 self.enter()
286 self.dispatch(t.body)
287 self.leave()
288 if t.orelse:
289 self.fill("else")
290 self.enter()
291 self.dispatch(t.orelse)
Mark Dickinsonae100052010-06-28 19:44:20 +0000292 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000293
294 def _With(self, t):
295 self.fill("with ")
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100296 interleave(lambda: self.write(", "), self.dispatch, t.items)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000297 self.enter()
298 self.dispatch(t.body)
299 self.leave()
300
Tim Peters400cbc32006-02-28 18:44:41 +0000301 # expr
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000302 def _Bytes(self, t):
303 self.write(repr(t.s))
304
Tim Peters400cbc32006-02-28 18:44:41 +0000305 def _Str(self, tree):
306 self.write(repr(tree.s))
307
308 def _Name(self, t):
309 self.write(t.id)
310
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000311 def _Num(self, t):
Mark Dickinsoncba8c102010-06-30 11:45:53 +0000312 # Substitute overflowing decimal literal for AST infinities.
313 self.write(repr(t.n).replace("inf", INFSTR))
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)
Mark Dickinsonb67e15c2010-06-30 09:05:47 +0000431 # Special case: 3.__abs__() is a syntax error, so if t.value
432 # is an integer literal then we need to either parenthesize
433 # it or add an extra space to get 3 .__abs__().
434 if isinstance(t.value, ast.Num) and isinstance(t.value.n, int):
435 self.write(" ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000436 self.write(".")
437 self.write(t.attr)
438
439 def _Call(self, t):
440 self.dispatch(t.func)
441 self.write("(")
442 comma = False
443 for e in t.args:
444 if comma: self.write(", ")
445 else: comma = True
446 self.dispatch(e)
447 for e in t.keywords:
448 if comma: self.write(", ")
449 else: comma = True
450 self.dispatch(e)
451 if t.starargs:
452 if comma: self.write(", ")
453 else: comma = True
454 self.write("*")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000455 self.dispatch(t.starargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000456 if t.kwargs:
457 if comma: self.write(", ")
458 else: comma = True
459 self.write("**")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000460 self.dispatch(t.kwargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000461 self.write(")")
462
463 def _Subscript(self, t):
464 self.dispatch(t.value)
465 self.write("[")
466 self.dispatch(t.slice)
467 self.write("]")
468
Mark Dickinson1b2e9442012-05-06 17:27:39 +0100469 def _Starred(self, t):
470 self.write("*")
471 self.dispatch(t.value)
472
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000473 # slice
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000474 def _Ellipsis(self, t):
475 self.write("...")
476
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000477 def _Index(self, t):
478 self.dispatch(t.value)
479
480 def _Slice(self, t):
481 if t.lower:
482 self.dispatch(t.lower)
483 self.write(":")
484 if t.upper:
485 self.dispatch(t.upper)
486 if t.step:
487 self.write(":")
488 self.dispatch(t.step)
489
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000490 def _ExtSlice(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000491 interleave(lambda: self.write(', '), self.dispatch, t.dims)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000492
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000493 # argument
494 def _arg(self, t):
495 self.write(t.arg)
496 if t.annotation:
497 self.write(": ")
498 self.dispatch(t.annotation)
499
Tim Peters400cbc32006-02-28 18:44:41 +0000500 # others
501 def _arguments(self, t):
502 first = True
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000503 # normal arguments
504 defaults = [None] * (len(t.args) - len(t.defaults)) + t.defaults
505 for a, d in zip(t.args, defaults):
Tim Peters400cbc32006-02-28 18:44:41 +0000506 if first:first = False
507 else: self.write(", ")
508 self.dispatch(a)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000509 if d:
510 self.write("=")
511 self.dispatch(d)
512
513 # varargs, or bare '*' if no varargs but keyword-only arguments present
514 if t.vararg or t.kwonlyargs:
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000515 if first:first = False
516 else: self.write(", ")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000517 self.write("*")
518 if t.vararg:
519 self.write(t.vararg)
520 if t.varargannotation:
521 self.write(": ")
522 self.dispatch(t.varargannotation)
523
524 # keyword-only arguments
525 if t.kwonlyargs:
526 for a, d in zip(t.kwonlyargs, t.kw_defaults):
527 if first:first = False
528 else: self.write(", ")
529 self.dispatch(a),
530 if d:
531 self.write("=")
532 self.dispatch(d)
533
534 # kwargs
Tim Peters400cbc32006-02-28 18:44:41 +0000535 if t.kwarg:
536 if first:first = False
537 else: self.write(", ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000538 self.write("**"+t.kwarg)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000539 if t.kwargannotation:
540 self.write(": ")
541 self.dispatch(t.kwargannotation)
Tim Peters400cbc32006-02-28 18:44:41 +0000542
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000543 def _keyword(self, t):
544 self.write(t.arg)
545 self.write("=")
546 self.dispatch(t.value)
547
548 def _Lambda(self, t):
Mark Dickinson8042e282010-06-29 10:01:48 +0000549 self.write("(")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000550 self.write("lambda ")
551 self.dispatch(t.args)
552 self.write(": ")
553 self.dispatch(t.body)
Mark Dickinson8042e282010-06-29 10:01:48 +0000554 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000555
Guido van Rossumd8faa362007-04-27 19:54:29 +0000556 def _alias(self, t):
557 self.write(t.name)
558 if t.asname:
559 self.write(" as "+t.asname)
560
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100561 def _withitem(self, t):
562 self.dispatch(t.context_expr)
563 if t.optional_vars:
564 self.write(" as ")
565 self.dispatch(t.optional_vars)
566
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000567def roundtrip(filename, output=sys.stdout):
Mark Dickinson82c8d932010-06-29 07:48:23 +0000568 with open(filename, "rb") as pyfile:
569 encoding = tokenize.detect_encoding(pyfile.readline)[0]
570 with open(filename, "r", encoding=encoding) as pyfile:
571 source = pyfile.read()
Mark Dickinson3d1bfbf2010-06-28 21:39:51 +0000572 tree = compile(source, filename, "exec", ast.PyCF_ONLY_AST)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000573 Unparser(tree, output)
574
575
576
577def testdir(a):
578 try:
579 names = [n for n in os.listdir(a) if n.endswith('.py')]
580 except OSError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000581 print("Directory not readable: %s" % a, file=sys.stderr)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000582 else:
583 for n in names:
584 fullname = os.path.join(a, n)
585 if os.path.isfile(fullname):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000586 output = io.StringIO()
587 print('Testing %s' % fullname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000588 try:
589 roundtrip(fullname, output)
Guido van Rossumb940e112007-01-10 16:19:56 +0000590 except Exception as e:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000591 print(' Failed to compile, exception is %s' % repr(e))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000592 elif os.path.isdir(fullname):
593 testdir(fullname)
594
595def main(args):
596 if args[0] == '--testdir':
597 for a in args[1:]:
598 testdir(a)
599 else:
600 for a in args:
601 roundtrip(a)
Tim Peters400cbc32006-02-28 18:44:41 +0000602
603if __name__=='__main__':
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000604 main(sys.argv[1:])