blob: 837cd81aaf8554c63f03f1fd49ec9f5779069c3b [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
Mark Dickinsoncba8c102010-06-30 11:45:53 +00008# Large float and imaginary literals get turned into infinities in the AST.
9# We unparse those infinities to INFSTR.
10INFSTR = "1e" + repr(sys.float_info.max_10_exp + 1)
11
Guido van Rossumd8faa362007-04-27 19:54:29 +000012def interleave(inter, f, seq):
13 """Call f on each item in seq, calling inter() in between.
14 """
15 seq = iter(seq)
16 try:
Collin Winter6f2df4d2007-07-17 20:59:35 +000017 f(next(seq))
Guido van Rossumd8faa362007-04-27 19:54:29 +000018 except StopIteration:
19 pass
20 else:
21 for x in seq:
22 inter()
23 f(x)
24
Tim Peters400cbc32006-02-28 18:44:41 +000025class Unparser:
26 """Methods in this class recursively traverse an AST and
27 output source code for the abstract syntax; original formatting
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000028 is disregarded. """
Tim Peters400cbc32006-02-28 18:44:41 +000029
30 def __init__(self, tree, file = sys.stdout):
31 """Unparser(tree, file=sys.stdout) -> None.
32 Print the source for tree to file."""
33 self.f = file
34 self._indent = 0
35 self.dispatch(tree)
Collin Winter6f2df4d2007-07-17 20:59:35 +000036 print("", file=self.f)
Tim Peters400cbc32006-02-28 18:44:41 +000037 self.f.flush()
38
39 def fill(self, text = ""):
40 "Indent a piece of text, according to the current indentation level"
41 self.f.write("\n"+" "*self._indent + text)
42
43 def write(self, text):
44 "Append a piece of text to the current line."
45 self.f.write(text)
46
47 def enter(self):
48 "Print ':', and increase the indentation."
49 self.write(":")
50 self._indent += 1
51
52 def leave(self):
53 "Decrease the indentation level."
54 self._indent -= 1
55
56 def dispatch(self, tree):
57 "Dispatcher function, dispatching tree type T to method _T."
58 if isinstance(tree, list):
59 for t in tree:
60 self.dispatch(t)
61 return
62 meth = getattr(self, "_"+tree.__class__.__name__)
63 meth(tree)
64
65
66 ############### Unparsing methods ######################
67 # There should be one method per concrete grammar type #
68 # Constructors should be grouped by sum type. Ideally, #
69 # this would follow the order in the grammar, but #
70 # currently doesn't. #
71 ########################################################
72
73 def _Module(self, tree):
74 for stmt in tree.body:
75 self.dispatch(stmt)
76
77 # stmt
78 def _Expr(self, tree):
79 self.fill()
80 self.dispatch(tree.value)
81
82 def _Import(self, t):
83 self.fill("import ")
Guido van Rossumd8faa362007-04-27 19:54:29 +000084 interleave(lambda: self.write(", "), self.dispatch, t.names)
Tim Peters400cbc32006-02-28 18:44:41 +000085
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000086 def _ImportFrom(self, t):
87 self.fill("from ")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000088 self.write("." * t.level)
89 if t.module:
90 self.write(t.module)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000091 self.write(" import ")
Guido van Rossumd8faa362007-04-27 19:54:29 +000092 interleave(lambda: self.write(", "), self.dispatch, t.names)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000093
Tim Peters400cbc32006-02-28 18:44:41 +000094 def _Assign(self, t):
95 self.fill()
96 for target in t.targets:
97 self.dispatch(target)
98 self.write(" = ")
99 self.dispatch(t.value)
100
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000101 def _AugAssign(self, t):
102 self.fill()
103 self.dispatch(t.target)
104 self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
105 self.dispatch(t.value)
106
107 def _Return(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000108 self.fill("return")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000109 if t.value:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000110 self.write(" ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000111 self.dispatch(t.value)
112
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000113 def _Pass(self, t):
114 self.fill("pass")
115
116 def _Break(self, t):
117 self.fill("break")
118
119 def _Continue(self, t):
120 self.fill("continue")
121
122 def _Delete(self, t):
123 self.fill("del ")
Mark Dickinsonae100052010-06-28 19:44:20 +0000124 interleave(lambda: self.write(", "), self.dispatch, t.targets)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000125
126 def _Assert(self, t):
127 self.fill("assert ")
128 self.dispatch(t.test)
129 if t.msg:
130 self.write(", ")
131 self.dispatch(t.msg)
132
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000133 def _Global(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000134 self.fill("global ")
135 interleave(lambda: self.write(", "), self.write, t.names)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000136
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000137 def _Nonlocal(self, t):
138 self.fill("nonlocal ")
139 interleave(lambda: self.write(", "), self.write, t.names)
140
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000141 def _Yield(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000142 self.write("(")
143 self.write("yield")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000144 if t.value:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000145 self.write(" ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000146 self.dispatch(t.value)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000147 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000148
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100149 def _YieldFrom(self, t):
150 self.write("(")
151 self.write("yield from")
152 if t.value:
153 self.write(" ")
154 self.dispatch(t.value)
155 self.write(")")
156
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000157 def _Raise(self, t):
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000158 self.fill("raise")
159 if not t.exc:
160 assert not t.cause
161 return
162 self.write(" ")
163 self.dispatch(t.exc)
164 if t.cause:
165 self.write(" from ")
166 self.dispatch(t.cause)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000167
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100168 def _Try(self, t):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000169 self.fill("try")
170 self.enter()
171 self.dispatch(t.body)
172 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000173 for ex in t.handlers:
174 self.dispatch(ex)
175 if t.orelse:
176 self.fill("else")
177 self.enter()
178 self.dispatch(t.orelse)
179 self.leave()
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100180 if t.finalbody:
181 self.fill("finally")
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000182 self.enter()
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100183 self.dispatch(t.finalbody)
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000184 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000185
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 ")
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100295 interleave(lambda: self.write(", "), self.dispatch, t.items)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000296 self.enter()
297 self.dispatch(t.body)
298 self.leave()
299
Tim Peters400cbc32006-02-28 18:44:41 +0000300 # expr
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000301 def _Bytes(self, t):
302 self.write(repr(t.s))
303
Tim Peters400cbc32006-02-28 18:44:41 +0000304 def _Str(self, tree):
305 self.write(repr(tree.s))
306
307 def _Name(self, t):
308 self.write(t.id)
309
Benjamin Peterson442f2092012-12-06 17:41:04 -0500310 def _NameConstant(self, t):
311 self.write(repr(t.value))
312
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000313 def _Num(self, t):
Mark Dickinsoncba8c102010-06-30 11:45:53 +0000314 # Substitute overflowing decimal literal for AST infinities.
315 self.write(repr(t.n).replace("inf", INFSTR))
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)
Mark Dickinsonb67e15c2010-06-30 09:05:47 +0000433 # Special case: 3.__abs__() is a syntax error, so if t.value
434 # is an integer literal then we need to either parenthesize
435 # it or add an extra space to get 3 .__abs__().
436 if isinstance(t.value, ast.Num) and isinstance(t.value.n, int):
437 self.write(" ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000438 self.write(".")
439 self.write(t.attr)
440
441 def _Call(self, t):
442 self.dispatch(t.func)
443 self.write("(")
444 comma = False
445 for e in t.args:
446 if comma: self.write(", ")
447 else: comma = True
448 self.dispatch(e)
449 for e in t.keywords:
450 if comma: self.write(", ")
451 else: comma = True
452 self.dispatch(e)
453 if t.starargs:
454 if comma: self.write(", ")
455 else: comma = True
456 self.write("*")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000457 self.dispatch(t.starargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000458 if t.kwargs:
459 if comma: self.write(", ")
460 else: comma = True
461 self.write("**")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000462 self.dispatch(t.kwargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000463 self.write(")")
464
465 def _Subscript(self, t):
466 self.dispatch(t.value)
467 self.write("[")
468 self.dispatch(t.slice)
469 self.write("]")
470
Mark Dickinson1b2e9442012-05-06 17:27:39 +0100471 def _Starred(self, t):
472 self.write("*")
473 self.dispatch(t.value)
474
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000475 # 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:
Benjamin Petersoncda75be2013-03-18 10:48:58 -0700521 self.write(t.vararg.arg)
522 if t.vararg.annotation:
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000523 self.write(": ")
Benjamin Petersoncda75be2013-03-18 10:48:58 -0700524 self.dispatch(t.vararg.annotation)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000525
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(", ")
Benjamin Petersoncda75be2013-03-18 10:48:58 -0700540 self.write("**"+t.kwarg.arg)
541 if t.kwarg.annotation:
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000542 self.write(": ")
Benjamin Petersoncda75be2013-03-18 10:48:58 -0700543 self.dispatch(t.kwarg.annotation)
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
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100563 def _withitem(self, t):
564 self.dispatch(t.context_expr)
565 if t.optional_vars:
566 self.write(" as ")
567 self.dispatch(t.optional_vars)
568
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000569def roundtrip(filename, output=sys.stdout):
Mark Dickinson82c8d932010-06-29 07:48:23 +0000570 with open(filename, "rb") as pyfile:
571 encoding = tokenize.detect_encoding(pyfile.readline)[0]
572 with open(filename, "r", encoding=encoding) as pyfile:
573 source = pyfile.read()
Mark Dickinson3d1bfbf2010-06-28 21:39:51 +0000574 tree = compile(source, filename, "exec", ast.PyCF_ONLY_AST)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000575 Unparser(tree, output)
576
577
578
579def testdir(a):
580 try:
581 names = [n for n in os.listdir(a) if n.endswith('.py')]
582 except OSError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000583 print("Directory not readable: %s" % a, file=sys.stderr)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000584 else:
585 for n in names:
586 fullname = os.path.join(a, n)
587 if os.path.isfile(fullname):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000588 output = io.StringIO()
589 print('Testing %s' % fullname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000590 try:
591 roundtrip(fullname, output)
Guido van Rossumb940e112007-01-10 16:19:56 +0000592 except Exception as e:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000593 print(' Failed to compile, exception is %s' % repr(e))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000594 elif os.path.isdir(fullname):
595 testdir(fullname)
596
597def main(args):
598 if args[0] == '--testdir':
599 for a in args[1:]:
600 testdir(a)
601 else:
602 for a in args:
603 roundtrip(a)
Tim Peters400cbc32006-02-28 18:44:41 +0000604
605if __name__=='__main__':
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000606 main(sys.argv[1:])