blob: e96ef5477b872ae9e11b83ef95e4da71761ed5d7 [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
150 def _Raise(self, t):
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000151 self.fill("raise")
152 if not t.exc:
153 assert not t.cause
154 return
155 self.write(" ")
156 self.dispatch(t.exc)
157 if t.cause:
158 self.write(" from ")
159 self.dispatch(t.cause)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000160
161 def _TryExcept(self, t):
162 self.fill("try")
163 self.enter()
164 self.dispatch(t.body)
165 self.leave()
166
167 for ex in t.handlers:
168 self.dispatch(ex)
169 if t.orelse:
170 self.fill("else")
171 self.enter()
172 self.dispatch(t.orelse)
173 self.leave()
174
175 def _TryFinally(self, t):
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000176 if len(t.body) == 1 and isinstance(t.body[0], ast.TryExcept):
177 # try-except-finally
178 self.dispatch(t.body)
179 else:
180 self.fill("try")
181 self.enter()
182 self.dispatch(t.body)
183 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000184
185 self.fill("finally")
186 self.enter()
187 self.dispatch(t.finalbody)
188 self.leave()
189
Benjamin Petersonc4fe6f32008-08-19 18:57:56 +0000190 def _ExceptHandler(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000191 self.fill("except")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000192 if t.type:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000193 self.write(" ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000194 self.dispatch(t.type)
195 if t.name:
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000196 self.write(" as ")
197 self.write(t.name)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000198 self.enter()
199 self.dispatch(t.body)
200 self.leave()
201
Tim Peters400cbc32006-02-28 18:44:41 +0000202 def _ClassDef(self, t):
203 self.write("\n")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000204 for deco in t.decorator_list:
205 self.fill("@")
206 self.dispatch(deco)
Tim Peters400cbc32006-02-28 18:44:41 +0000207 self.fill("class "+t.name)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000208 self.write("(")
209 comma = False
210 for e in t.bases:
211 if comma: self.write(", ")
212 else: comma = True
213 self.dispatch(e)
214 for e in t.keywords:
215 if comma: self.write(", ")
216 else: comma = True
217 self.dispatch(e)
218 if t.starargs:
219 if comma: self.write(", ")
220 else: comma = True
221 self.write("*")
222 self.dispatch(t.starargs)
223 if t.kwargs:
224 if comma: self.write(", ")
225 else: comma = True
Mark Dickinson578aa562010-06-29 18:38:59 +0000226 self.write("**")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000227 self.dispatch(t.kwargs)
228 self.write(")")
229
Tim Peters400cbc32006-02-28 18:44:41 +0000230 self.enter()
231 self.dispatch(t.body)
232 self.leave()
233
234 def _FunctionDef(self, t):
235 self.write("\n")
Benjamin Petersonc4fe6f32008-08-19 18:57:56 +0000236 for deco in t.decorator_list:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000237 self.fill("@")
238 self.dispatch(deco)
Tim Peters400cbc32006-02-28 18:44:41 +0000239 self.fill("def "+t.name + "(")
240 self.dispatch(t.args)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000241 self.write(")")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000242 if t.returns:
243 self.write(" -> ")
244 self.dispatch(t.returns)
Tim Peters400cbc32006-02-28 18:44:41 +0000245 self.enter()
246 self.dispatch(t.body)
247 self.leave()
248
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000249 def _For(self, t):
250 self.fill("for ")
251 self.dispatch(t.target)
252 self.write(" in ")
253 self.dispatch(t.iter)
254 self.enter()
255 self.dispatch(t.body)
256 self.leave()
257 if t.orelse:
258 self.fill("else")
259 self.enter()
260 self.dispatch(t.orelse)
Mark Dickinsonae100052010-06-28 19:44:20 +0000261 self.leave()
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000262
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000263 def _If(self, t):
264 self.fill("if ")
265 self.dispatch(t.test)
266 self.enter()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000267 self.dispatch(t.body)
268 self.leave()
Mark Dickinson8d6d7602010-06-30 08:32:11 +0000269 # collapse nested ifs into equivalent elifs.
270 while (t.orelse and len(t.orelse) == 1 and
271 isinstance(t.orelse[0], ast.If)):
272 t = t.orelse[0]
273 self.fill("elif ")
274 self.dispatch(t.test)
275 self.enter()
276 self.dispatch(t.body)
277 self.leave()
278 # final else
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000279 if t.orelse:
280 self.fill("else")
281 self.enter()
282 self.dispatch(t.orelse)
283 self.leave()
284
285 def _While(self, t):
286 self.fill("while ")
287 self.dispatch(t.test)
288 self.enter()
289 self.dispatch(t.body)
290 self.leave()
291 if t.orelse:
292 self.fill("else")
293 self.enter()
294 self.dispatch(t.orelse)
Mark Dickinsonae100052010-06-28 19:44:20 +0000295 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000296
297 def _With(self, t):
298 self.fill("with ")
299 self.dispatch(t.context_expr)
300 if t.optional_vars:
301 self.write(" as ")
302 self.dispatch(t.optional_vars)
303 self.enter()
304 self.dispatch(t.body)
305 self.leave()
306
Tim Peters400cbc32006-02-28 18:44:41 +0000307 # expr
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000308 def _Bytes(self, t):
309 self.write(repr(t.s))
310
Tim Peters400cbc32006-02-28 18:44:41 +0000311 def _Str(self, tree):
312 self.write(repr(tree.s))
313
314 def _Name(self, t):
315 self.write(t.id)
316
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000317 def _Num(self, t):
Mark Dickinsoncba8c102010-06-30 11:45:53 +0000318 # Substitute overflowing decimal literal for AST infinities.
319 self.write(repr(t.n).replace("inf", INFSTR))
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000320
Tim Peters400cbc32006-02-28 18:44:41 +0000321 def _List(self, t):
322 self.write("[")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000323 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Tim Peters400cbc32006-02-28 18:44:41 +0000324 self.write("]")
325
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000326 def _ListComp(self, t):
327 self.write("[")
328 self.dispatch(t.elt)
329 for gen in t.generators:
330 self.dispatch(gen)
331 self.write("]")
332
333 def _GeneratorExp(self, t):
334 self.write("(")
335 self.dispatch(t.elt)
336 for gen in t.generators:
337 self.dispatch(gen)
338 self.write(")")
339
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000340 def _SetComp(self, t):
341 self.write("{")
342 self.dispatch(t.elt)
343 for gen in t.generators:
344 self.dispatch(gen)
345 self.write("}")
346
347 def _DictComp(self, t):
348 self.write("{")
349 self.dispatch(t.key)
350 self.write(": ")
351 self.dispatch(t.value)
352 for gen in t.generators:
353 self.dispatch(gen)
354 self.write("}")
355
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000356 def _comprehension(self, t):
357 self.write(" for ")
358 self.dispatch(t.target)
359 self.write(" in ")
360 self.dispatch(t.iter)
361 for if_clause in t.ifs:
362 self.write(" if ")
363 self.dispatch(if_clause)
364
365 def _IfExp(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000366 self.write("(")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000367 self.dispatch(t.body)
368 self.write(" if ")
369 self.dispatch(t.test)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000370 self.write(" else ")
371 self.dispatch(t.orelse)
372 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000373
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000374 def _Set(self, t):
375 assert(t.elts) # should be at least one element
376 self.write("{")
377 interleave(lambda: self.write(", "), self.dispatch, t.elts)
378 self.write("}")
379
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000380 def _Dict(self, t):
381 self.write("{")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000382 def write_pair(pair):
383 (k, v) = pair
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000384 self.dispatch(k)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000385 self.write(": ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000386 self.dispatch(v)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000387 interleave(lambda: self.write(", "), write_pair, zip(t.keys, t.values))
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000388 self.write("}")
389
390 def _Tuple(self, t):
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000391 self.write("(")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000392 if len(t.elts) == 1:
393 (elt,) = t.elts
394 self.dispatch(elt)
395 self.write(",")
396 else:
397 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000398 self.write(")")
399
Tim Peters400cbc32006-02-28 18:44:41 +0000400 unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}
401 def _UnaryOp(self, t):
Tim Peters400cbc32006-02-28 18:44:41 +0000402 self.write("(")
Mark Dickinsonae100052010-06-28 19:44:20 +0000403 self.write(self.unop[t.op.__class__.__name__])
404 self.write(" ")
Tim Peters400cbc32006-02-28 18:44:41 +0000405 self.dispatch(t.operand)
406 self.write(")")
407
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000408 binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%",
Mark Dickinsonae100052010-06-28 19:44:20 +0000409 "LShift":"<<", "RShift":">>", "BitOr":"|", "BitXor":"^", "BitAnd":"&",
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000410 "FloorDiv":"//", "Pow": "**"}
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000411 def _BinOp(self, t):
412 self.write("(")
413 self.dispatch(t.left)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000414 self.write(" " + self.binop[t.op.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000415 self.dispatch(t.right)
416 self.write(")")
417
418 cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=",
419 "Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"}
420 def _Compare(self, t):
421 self.write("(")
422 self.dispatch(t.left)
423 for o, e in zip(t.ops, t.comparators):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000424 self.write(" " + self.cmpops[o.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000425 self.dispatch(e)
Mark Dickinsonf5451e52010-06-28 20:09:18 +0000426 self.write(")")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000427
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000428 boolops = {ast.And: 'and', ast.Or: 'or'}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000429 def _BoolOp(self, t):
430 self.write("(")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000431 s = " %s " % self.boolops[t.op.__class__]
432 interleave(lambda: self.write(s), self.dispatch, t.values)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000433 self.write(")")
434
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000435 def _Attribute(self,t):
436 self.dispatch(t.value)
Mark Dickinsonb67e15c2010-06-30 09:05:47 +0000437 # Special case: 3.__abs__() is a syntax error, so if t.value
438 # is an integer literal then we need to either parenthesize
439 # it or add an extra space to get 3 .__abs__().
440 if isinstance(t.value, ast.Num) and isinstance(t.value.n, int):
441 self.write(" ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000442 self.write(".")
443 self.write(t.attr)
444
445 def _Call(self, t):
446 self.dispatch(t.func)
447 self.write("(")
448 comma = False
449 for e in t.args:
450 if comma: self.write(", ")
451 else: comma = True
452 self.dispatch(e)
453 for e in t.keywords:
454 if comma: self.write(", ")
455 else: comma = True
456 self.dispatch(e)
457 if t.starargs:
458 if comma: self.write(", ")
459 else: comma = True
460 self.write("*")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000461 self.dispatch(t.starargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000462 if t.kwargs:
463 if comma: self.write(", ")
464 else: comma = True
465 self.write("**")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000466 self.dispatch(t.kwargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000467 self.write(")")
468
469 def _Subscript(self, t):
470 self.dispatch(t.value)
471 self.write("[")
472 self.dispatch(t.slice)
473 self.write("]")
474
475 # slice
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000476 def _Ellipsis(self, t):
477 self.write("...")
478
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000479 def _Index(self, t):
480 self.dispatch(t.value)
481
482 def _Slice(self, t):
483 if t.lower:
484 self.dispatch(t.lower)
485 self.write(":")
486 if t.upper:
487 self.dispatch(t.upper)
488 if t.step:
489 self.write(":")
490 self.dispatch(t.step)
491
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000492 def _ExtSlice(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000493 interleave(lambda: self.write(', '), self.dispatch, t.dims)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000494
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000495 # argument
496 def _arg(self, t):
497 self.write(t.arg)
498 if t.annotation:
499 self.write(": ")
500 self.dispatch(t.annotation)
501
Tim Peters400cbc32006-02-28 18:44:41 +0000502 # others
503 def _arguments(self, t):
504 first = True
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000505 # normal arguments
506 defaults = [None] * (len(t.args) - len(t.defaults)) + t.defaults
507 for a, d in zip(t.args, defaults):
Tim Peters400cbc32006-02-28 18:44:41 +0000508 if first:first = False
509 else: self.write(", ")
510 self.dispatch(a)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000511 if d:
512 self.write("=")
513 self.dispatch(d)
514
515 # varargs, or bare '*' if no varargs but keyword-only arguments present
516 if t.vararg or t.kwonlyargs:
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000517 if first:first = False
518 else: self.write(", ")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000519 self.write("*")
520 if t.vararg:
521 self.write(t.vararg)
522 if t.varargannotation:
523 self.write(": ")
524 self.dispatch(t.varargannotation)
525
526 # keyword-only arguments
527 if t.kwonlyargs:
528 for a, d in zip(t.kwonlyargs, t.kw_defaults):
529 if first:first = False
530 else: self.write(", ")
531 self.dispatch(a),
532 if d:
533 self.write("=")
534 self.dispatch(d)
535
536 # kwargs
Tim Peters400cbc32006-02-28 18:44:41 +0000537 if t.kwarg:
538 if first:first = False
539 else: self.write(", ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000540 self.write("**"+t.kwarg)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000541 if t.kwargannotation:
542 self.write(": ")
543 self.dispatch(t.kwargannotation)
Tim Peters400cbc32006-02-28 18:44:41 +0000544
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000545 def _keyword(self, t):
546 self.write(t.arg)
547 self.write("=")
548 self.dispatch(t.value)
549
550 def _Lambda(self, t):
Mark Dickinson8042e282010-06-29 10:01:48 +0000551 self.write("(")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000552 self.write("lambda ")
553 self.dispatch(t.args)
554 self.write(": ")
555 self.dispatch(t.body)
Mark Dickinson8042e282010-06-29 10:01:48 +0000556 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000557
Guido van Rossumd8faa362007-04-27 19:54:29 +0000558 def _alias(self, t):
559 self.write(t.name)
560 if t.asname:
561 self.write(" as "+t.asname)
562
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000563def roundtrip(filename, output=sys.stdout):
Mark Dickinson82c8d932010-06-29 07:48:23 +0000564 with open(filename, "rb") as pyfile:
565 encoding = tokenize.detect_encoding(pyfile.readline)[0]
566 with open(filename, "r", encoding=encoding) as pyfile:
567 source = pyfile.read()
Mark Dickinson3d1bfbf2010-06-28 21:39:51 +0000568 tree = compile(source, filename, "exec", ast.PyCF_ONLY_AST)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000569 Unparser(tree, output)
570
571
572
573def testdir(a):
574 try:
575 names = [n for n in os.listdir(a) if n.endswith('.py')]
576 except OSError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000577 print("Directory not readable: %s" % a, file=sys.stderr)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000578 else:
579 for n in names:
580 fullname = os.path.join(a, n)
581 if os.path.isfile(fullname):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000582 output = io.StringIO()
583 print('Testing %s' % fullname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000584 try:
585 roundtrip(fullname, output)
Guido van Rossumb940e112007-01-10 16:19:56 +0000586 except Exception as e:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000587 print(' Failed to compile, exception is %s' % repr(e))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000588 elif os.path.isdir(fullname):
589 testdir(fullname)
590
591def main(args):
592 if args[0] == '--testdir':
593 for a in args[1:]:
594 testdir(a)
595 else:
596 for a in args:
597 roundtrip(a)
Tim Peters400cbc32006-02-28 18:44:41 +0000598
599if __name__=='__main__':
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000600 main(sys.argv[1:])