blob: 3fac1c05e12c71d49aecb4b070898f6fb9bdda77 [file] [log] [blame]
Mark Dickinson50b79a82010-06-30 11:13:36 +00001#! /usr/bin/env python3.1
Tim Peters400cbc32006-02-28 18:44:41 +00002"Usage: unparse.py <path to source file>"
3import sys
Mark Dickinson8042e282010-06-29 10:01:48 +00004import math
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +00005import ast
Mark Dickinson82c8d932010-06-29 07:48:23 +00006import tokenize
Collin Winter6f2df4d2007-07-17 20:59:35 +00007import io
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00008import os
Tim Peters400cbc32006-02-28 18:44:41 +00009
Guido van Rossumd8faa362007-04-27 19:54:29 +000010def interleave(inter, f, seq):
11 """Call f on each item in seq, calling inter() in between.
12 """
13 seq = iter(seq)
14 try:
Collin Winter6f2df4d2007-07-17 20:59:35 +000015 f(next(seq))
Guido van Rossumd8faa362007-04-27 19:54:29 +000016 except StopIteration:
17 pass
18 else:
19 for x in seq:
20 inter()
21 f(x)
22
Tim Peters400cbc32006-02-28 18:44:41 +000023class Unparser:
24 """Methods in this class recursively traverse an AST and
25 output source code for the abstract syntax; original formatting
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000026 is disregarded. """
Tim Peters400cbc32006-02-28 18:44:41 +000027
28 def __init__(self, tree, file = sys.stdout):
29 """Unparser(tree, file=sys.stdout) -> None.
30 Print the source for tree to file."""
31 self.f = file
32 self._indent = 0
33 self.dispatch(tree)
Collin Winter6f2df4d2007-07-17 20:59:35 +000034 print("", file=self.f)
Tim Peters400cbc32006-02-28 18:44:41 +000035 self.f.flush()
36
37 def fill(self, text = ""):
38 "Indent a piece of text, according to the current indentation level"
39 self.f.write("\n"+" "*self._indent + text)
40
41 def write(self, text):
42 "Append a piece of text to the current line."
43 self.f.write(text)
44
45 def enter(self):
46 "Print ':', and increase the indentation."
47 self.write(":")
48 self._indent += 1
49
50 def leave(self):
51 "Decrease the indentation level."
52 self._indent -= 1
53
54 def dispatch(self, tree):
55 "Dispatcher function, dispatching tree type T to method _T."
56 if isinstance(tree, list):
57 for t in tree:
58 self.dispatch(t)
59 return
60 meth = getattr(self, "_"+tree.__class__.__name__)
61 meth(tree)
62
63
64 ############### Unparsing methods ######################
65 # There should be one method per concrete grammar type #
66 # Constructors should be grouped by sum type. Ideally, #
67 # this would follow the order in the grammar, but #
68 # currently doesn't. #
69 ########################################################
70
71 def _Module(self, tree):
72 for stmt in tree.body:
73 self.dispatch(stmt)
74
75 # stmt
76 def _Expr(self, tree):
77 self.fill()
78 self.dispatch(tree.value)
79
80 def _Import(self, t):
81 self.fill("import ")
Guido van Rossumd8faa362007-04-27 19:54:29 +000082 interleave(lambda: self.write(", "), self.dispatch, t.names)
Tim Peters400cbc32006-02-28 18:44:41 +000083
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000084 def _ImportFrom(self, t):
85 self.fill("from ")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000086 self.write("." * t.level)
87 if t.module:
88 self.write(t.module)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000089 self.write(" import ")
Guido van Rossumd8faa362007-04-27 19:54:29 +000090 interleave(lambda: self.write(", "), self.dispatch, t.names)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000091
Tim Peters400cbc32006-02-28 18:44:41 +000092 def _Assign(self, t):
93 self.fill()
94 for target in t.targets:
95 self.dispatch(target)
96 self.write(" = ")
97 self.dispatch(t.value)
98
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +000099 def _AugAssign(self, t):
100 self.fill()
101 self.dispatch(t.target)
102 self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
103 self.dispatch(t.value)
104
105 def _Return(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000106 self.fill("return")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000107 if t.value:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000108 self.write(" ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000109 self.dispatch(t.value)
110
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000111 def _Pass(self, t):
112 self.fill("pass")
113
114 def _Break(self, t):
115 self.fill("break")
116
117 def _Continue(self, t):
118 self.fill("continue")
119
120 def _Delete(self, t):
121 self.fill("del ")
Mark Dickinsonae100052010-06-28 19:44:20 +0000122 interleave(lambda: self.write(", "), self.dispatch, t.targets)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000123
124 def _Assert(self, t):
125 self.fill("assert ")
126 self.dispatch(t.test)
127 if t.msg:
128 self.write(", ")
129 self.dispatch(t.msg)
130
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000131 def _Global(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000132 self.fill("global ")
133 interleave(lambda: self.write(", "), self.write, t.names)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000134
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000135 def _Nonlocal(self, t):
136 self.fill("nonlocal ")
137 interleave(lambda: self.write(", "), self.write, t.names)
138
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000139 def _Yield(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000140 self.write("(")
141 self.write("yield")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000142 if t.value:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000143 self.write(" ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000144 self.dispatch(t.value)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000145 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000146
147 def _Raise(self, t):
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000148 self.fill("raise")
149 if not t.exc:
150 assert not t.cause
151 return
152 self.write(" ")
153 self.dispatch(t.exc)
154 if t.cause:
155 self.write(" from ")
156 self.dispatch(t.cause)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000157
158 def _TryExcept(self, t):
159 self.fill("try")
160 self.enter()
161 self.dispatch(t.body)
162 self.leave()
163
164 for ex in t.handlers:
165 self.dispatch(ex)
166 if t.orelse:
167 self.fill("else")
168 self.enter()
169 self.dispatch(t.orelse)
170 self.leave()
171
172 def _TryFinally(self, t):
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000173 if len(t.body) == 1 and isinstance(t.body[0], ast.TryExcept):
174 # try-except-finally
175 self.dispatch(t.body)
176 else:
177 self.fill("try")
178 self.enter()
179 self.dispatch(t.body)
180 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000181
182 self.fill("finally")
183 self.enter()
184 self.dispatch(t.finalbody)
185 self.leave()
186
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 ")
296 self.dispatch(t.context_expr)
297 if t.optional_vars:
298 self.write(" as ")
299 self.dispatch(t.optional_vars)
300 self.enter()
301 self.dispatch(t.body)
302 self.leave()
303
Tim Peters400cbc32006-02-28 18:44:41 +0000304 # expr
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000305 def _Bytes(self, t):
306 self.write(repr(t.s))
307
Tim Peters400cbc32006-02-28 18:44:41 +0000308 def _Str(self, tree):
309 self.write(repr(tree.s))
310
311 def _Name(self, t):
312 self.write(t.id)
313
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000314 def _Num(self, t):
Mark Dickinson50b79a82010-06-30 11:13:36 +0000315 # Python doesn't have negative numeric literals, but in Python
316 # 2.x and early versions of Python 3.1, there's a compile-time
317 # operation that turns "-<number>" into a single _Num, instead
318 # of an unary minus applied to a _Num. Here we reverse that.
319 infstr = "1e" + repr(sys.float_info.max_10_exp + 1)
320
321 if isinstance(t.n, complex):
322 # check that real part is as expected: 0 with appropriate sign
323 print(t.n)
324 print(str(t.n.real), str(math.copysign(0.0, t.n.imag)))
325 assert str(t.n.real) == str(math.copysign(0.0, t.n.imag))
326 negate = math.copysign(1.0, t.n.imag) < 0
327 elif isinstance(t.n, float):
328 negate = math.copysign(1.0, t.n) < 0
329 elif isinstance(t.n, int):
330 negate = t.n < 0
331
332 if negate:
333 self.write("(- ")
334 val = -t.n
Mark Dickinson8042e282010-06-29 10:01:48 +0000335 else:
Mark Dickinson50b79a82010-06-30 11:13:36 +0000336 val = t.n
337
338 # Subsitute an overflowing decimal literal for an AST infinity
339 self.write(repr(t.n).replace("inf", infstr))
340
341 if negate:
342 self.write(")")
343
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000344
Tim Peters400cbc32006-02-28 18:44:41 +0000345 def _List(self, t):
346 self.write("[")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000347 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Tim Peters400cbc32006-02-28 18:44:41 +0000348 self.write("]")
349
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000350 def _ListComp(self, t):
351 self.write("[")
352 self.dispatch(t.elt)
353 for gen in t.generators:
354 self.dispatch(gen)
355 self.write("]")
356
357 def _GeneratorExp(self, t):
358 self.write("(")
359 self.dispatch(t.elt)
360 for gen in t.generators:
361 self.dispatch(gen)
362 self.write(")")
363
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000364 def _SetComp(self, t):
365 self.write("{")
366 self.dispatch(t.elt)
367 for gen in t.generators:
368 self.dispatch(gen)
369 self.write("}")
370
371 def _DictComp(self, t):
372 self.write("{")
373 self.dispatch(t.key)
374 self.write(": ")
375 self.dispatch(t.value)
376 for gen in t.generators:
377 self.dispatch(gen)
378 self.write("}")
379
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000380 def _comprehension(self, t):
381 self.write(" for ")
382 self.dispatch(t.target)
383 self.write(" in ")
384 self.dispatch(t.iter)
385 for if_clause in t.ifs:
386 self.write(" if ")
387 self.dispatch(if_clause)
388
389 def _IfExp(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000390 self.write("(")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000391 self.dispatch(t.body)
392 self.write(" if ")
393 self.dispatch(t.test)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000394 self.write(" else ")
395 self.dispatch(t.orelse)
396 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000397
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000398 def _Set(self, t):
399 assert(t.elts) # should be at least one element
400 self.write("{")
401 interleave(lambda: self.write(", "), self.dispatch, t.elts)
402 self.write("}")
403
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000404 def _Dict(self, t):
405 self.write("{")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000406 def write_pair(pair):
407 (k, v) = pair
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000408 self.dispatch(k)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000409 self.write(": ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000410 self.dispatch(v)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000411 interleave(lambda: self.write(", "), write_pair, zip(t.keys, t.values))
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000412 self.write("}")
413
414 def _Tuple(self, t):
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000415 self.write("(")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000416 if len(t.elts) == 1:
417 (elt,) = t.elts
418 self.dispatch(elt)
419 self.write(",")
420 else:
421 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000422 self.write(")")
423
Tim Peters400cbc32006-02-28 18:44:41 +0000424 unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}
425 def _UnaryOp(self, t):
Tim Peters400cbc32006-02-28 18:44:41 +0000426 self.write("(")
Mark Dickinsonae100052010-06-28 19:44:20 +0000427 self.write(self.unop[t.op.__class__.__name__])
428 self.write(" ")
Tim Peters400cbc32006-02-28 18:44:41 +0000429 self.dispatch(t.operand)
430 self.write(")")
431
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000432 binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%",
Mark Dickinsonae100052010-06-28 19:44:20 +0000433 "LShift":"<<", "RShift":">>", "BitOr":"|", "BitXor":"^", "BitAnd":"&",
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000434 "FloorDiv":"//", "Pow": "**"}
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000435 def _BinOp(self, t):
436 self.write("(")
437 self.dispatch(t.left)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000438 self.write(" " + self.binop[t.op.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000439 self.dispatch(t.right)
440 self.write(")")
441
442 cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=",
443 "Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"}
444 def _Compare(self, t):
445 self.write("(")
446 self.dispatch(t.left)
447 for o, e in zip(t.ops, t.comparators):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000448 self.write(" " + self.cmpops[o.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000449 self.dispatch(e)
Mark Dickinsonf5451e52010-06-28 20:09:18 +0000450 self.write(")")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000451
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000452 boolops = {ast.And: 'and', ast.Or: 'or'}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000453 def _BoolOp(self, t):
454 self.write("(")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000455 s = " %s " % self.boolops[t.op.__class__]
456 interleave(lambda: self.write(s), self.dispatch, t.values)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000457 self.write(")")
458
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000459 def _Attribute(self,t):
460 self.dispatch(t.value)
Mark Dickinsonb67e15c2010-06-30 09:05:47 +0000461 # Special case: 3.__abs__() is a syntax error, so if t.value
462 # is an integer literal then we need to either parenthesize
463 # it or add an extra space to get 3 .__abs__().
464 if isinstance(t.value, ast.Num) and isinstance(t.value.n, int):
465 self.write(" ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000466 self.write(".")
467 self.write(t.attr)
468
469 def _Call(self, t):
470 self.dispatch(t.func)
471 self.write("(")
472 comma = False
473 for e in t.args:
474 if comma: self.write(", ")
475 else: comma = True
476 self.dispatch(e)
477 for e in t.keywords:
478 if comma: self.write(", ")
479 else: comma = True
480 self.dispatch(e)
481 if t.starargs:
482 if comma: self.write(", ")
483 else: comma = True
484 self.write("*")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000485 self.dispatch(t.starargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000486 if t.kwargs:
487 if comma: self.write(", ")
488 else: comma = True
489 self.write("**")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000490 self.dispatch(t.kwargs)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000491 self.write(")")
492
493 def _Subscript(self, t):
494 self.dispatch(t.value)
495 self.write("[")
496 self.dispatch(t.slice)
497 self.write("]")
498
499 # slice
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000500 def _Ellipsis(self, t):
501 self.write("...")
502
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000503 def _Index(self, t):
504 self.dispatch(t.value)
505
506 def _Slice(self, t):
507 if t.lower:
508 self.dispatch(t.lower)
509 self.write(":")
510 if t.upper:
511 self.dispatch(t.upper)
512 if t.step:
513 self.write(":")
514 self.dispatch(t.step)
515
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000516 def _ExtSlice(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000517 interleave(lambda: self.write(', '), self.dispatch, t.dims)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000518
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000519 # argument
520 def _arg(self, t):
521 self.write(t.arg)
522 if t.annotation:
523 self.write(": ")
524 self.dispatch(t.annotation)
525
Tim Peters400cbc32006-02-28 18:44:41 +0000526 # others
527 def _arguments(self, t):
528 first = True
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000529 # normal arguments
530 defaults = [None] * (len(t.args) - len(t.defaults)) + t.defaults
531 for a, d in zip(t.args, defaults):
Tim Peters400cbc32006-02-28 18:44:41 +0000532 if first:first = False
533 else: self.write(", ")
534 self.dispatch(a)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000535 if d:
536 self.write("=")
537 self.dispatch(d)
538
539 # varargs, or bare '*' if no varargs but keyword-only arguments present
540 if t.vararg or t.kwonlyargs:
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000541 if first:first = False
542 else: self.write(", ")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000543 self.write("*")
544 if t.vararg:
545 self.write(t.vararg)
546 if t.varargannotation:
547 self.write(": ")
548 self.dispatch(t.varargannotation)
549
550 # keyword-only arguments
551 if t.kwonlyargs:
552 for a, d in zip(t.kwonlyargs, t.kw_defaults):
553 if first:first = False
554 else: self.write(", ")
555 self.dispatch(a),
556 if d:
557 self.write("=")
558 self.dispatch(d)
559
560 # kwargs
Tim Peters400cbc32006-02-28 18:44:41 +0000561 if t.kwarg:
562 if first:first = False
563 else: self.write(", ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000564 self.write("**"+t.kwarg)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000565 if t.kwargannotation:
566 self.write(": ")
567 self.dispatch(t.kwargannotation)
Tim Peters400cbc32006-02-28 18:44:41 +0000568
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000569 def _keyword(self, t):
570 self.write(t.arg)
571 self.write("=")
572 self.dispatch(t.value)
573
574 def _Lambda(self, t):
Mark Dickinson8042e282010-06-29 10:01:48 +0000575 self.write("(")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000576 self.write("lambda ")
577 self.dispatch(t.args)
578 self.write(": ")
579 self.dispatch(t.body)
Mark Dickinson8042e282010-06-29 10:01:48 +0000580 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000581
Guido van Rossumd8faa362007-04-27 19:54:29 +0000582 def _alias(self, t):
583 self.write(t.name)
584 if t.asname:
585 self.write(" as "+t.asname)
586
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000587def roundtrip(filename, output=sys.stdout):
Mark Dickinson82c8d932010-06-29 07:48:23 +0000588 with open(filename, "rb") as pyfile:
589 encoding = tokenize.detect_encoding(pyfile.readline)[0]
590 with open(filename, "r", encoding=encoding) as pyfile:
591 source = pyfile.read()
Mark Dickinson3d1bfbf2010-06-28 21:39:51 +0000592 tree = compile(source, filename, "exec", ast.PyCF_ONLY_AST)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000593 Unparser(tree, output)
594
595
596
597def testdir(a):
598 try:
599 names = [n for n in os.listdir(a) if n.endswith('.py')]
600 except OSError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000601 print("Directory not readable: %s" % a, file=sys.stderr)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000602 else:
603 for n in names:
604 fullname = os.path.join(a, n)
605 if os.path.isfile(fullname):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000606 output = io.StringIO()
607 print('Testing %s' % fullname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000608 try:
609 roundtrip(fullname, output)
Guido van Rossumb940e112007-01-10 16:19:56 +0000610 except Exception as e:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000611 print(' Failed to compile, exception is %s' % repr(e))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000612 elif os.path.isdir(fullname):
613 testdir(fullname)
614
615def main(args):
616 if args[0] == '--testdir':
617 for a in args[1:]:
618 testdir(a)
619 else:
620 for a in args:
621 roundtrip(a)
Tim Peters400cbc32006-02-28 18:44:41 +0000622
623if __name__=='__main__':
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000624 main(sys.argv[1:])