blob: 72030576d019335867b7084c97231f28247a9d1d [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
Yury Selivanov75445082015-05-11 22:57:16 -0400141 def _Await(self, t):
142 self.write("(")
143 self.write("await")
144 if t.value:
145 self.write(" ")
146 self.dispatch(t.value)
147 self.write(")")
148
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000149 def _Yield(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000150 self.write("(")
151 self.write("yield")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000152 if t.value:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000153 self.write(" ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000154 self.dispatch(t.value)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000155 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000156
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100157 def _YieldFrom(self, t):
158 self.write("(")
159 self.write("yield from")
160 if t.value:
161 self.write(" ")
162 self.dispatch(t.value)
163 self.write(")")
164
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000165 def _Raise(self, t):
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000166 self.fill("raise")
167 if not t.exc:
168 assert not t.cause
169 return
170 self.write(" ")
171 self.dispatch(t.exc)
172 if t.cause:
173 self.write(" from ")
174 self.dispatch(t.cause)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000175
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100176 def _Try(self, t):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000177 self.fill("try")
178 self.enter()
179 self.dispatch(t.body)
180 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000181 for ex in t.handlers:
182 self.dispatch(ex)
183 if t.orelse:
184 self.fill("else")
185 self.enter()
186 self.dispatch(t.orelse)
187 self.leave()
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100188 if t.finalbody:
189 self.fill("finally")
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000190 self.enter()
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100191 self.dispatch(t.finalbody)
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000192 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000193
Benjamin Petersonc4fe6f32008-08-19 18:57:56 +0000194 def _ExceptHandler(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000195 self.fill("except")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000196 if t.type:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000197 self.write(" ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000198 self.dispatch(t.type)
199 if t.name:
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000200 self.write(" as ")
201 self.write(t.name)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000202 self.enter()
203 self.dispatch(t.body)
204 self.leave()
205
Tim Peters400cbc32006-02-28 18:44:41 +0000206 def _ClassDef(self, t):
207 self.write("\n")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000208 for deco in t.decorator_list:
209 self.fill("@")
210 self.dispatch(deco)
Tim Peters400cbc32006-02-28 18:44:41 +0000211 self.fill("class "+t.name)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000212 self.write("(")
213 comma = False
214 for e in t.bases:
215 if comma: self.write(", ")
216 else: comma = True
217 self.dispatch(e)
218 for e in t.keywords:
219 if comma: self.write(", ")
220 else: comma = True
221 self.dispatch(e)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000222 self.write(")")
223
Tim Peters400cbc32006-02-28 18:44:41 +0000224 self.enter()
225 self.dispatch(t.body)
226 self.leave()
227
228 def _FunctionDef(self, t):
Yury Selivanov75445082015-05-11 22:57:16 -0400229 self.__FunctionDef_helper(t, "def")
230
231 def _AsyncFunctionDef(self, t):
232 self.__FunctionDef_helper(t, "async def")
233
234 def __FunctionDef_helper(self, t, fill_suffix):
Tim Peters400cbc32006-02-28 18:44:41 +0000235 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)
Yury Selivanov75445082015-05-11 22:57:16 -0400239 def_str = fill_suffix+" "+t.name + "("
240 self.fill(def_str)
Tim Peters400cbc32006-02-28 18:44:41 +0000241 self.dispatch(t.args)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000242 self.write(")")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000243 if t.returns:
244 self.write(" -> ")
245 self.dispatch(t.returns)
Tim Peters400cbc32006-02-28 18:44:41 +0000246 self.enter()
247 self.dispatch(t.body)
248 self.leave()
249
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000250 def _For(self, t):
Yury Selivanov75445082015-05-11 22:57:16 -0400251 self.__For_helper("for ", t)
252
253 def _AsyncFor(self, t):
254 self.__For_helper("async for ", t)
255
256 def __For_helper(self, fill, t):
257 self.fill(fill)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000258 self.dispatch(t.target)
259 self.write(" in ")
260 self.dispatch(t.iter)
261 self.enter()
262 self.dispatch(t.body)
263 self.leave()
264 if t.orelse:
265 self.fill("else")
266 self.enter()
267 self.dispatch(t.orelse)
Mark Dickinsonae100052010-06-28 19:44:20 +0000268 self.leave()
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000269
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000270 def _If(self, t):
271 self.fill("if ")
272 self.dispatch(t.test)
273 self.enter()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000274 self.dispatch(t.body)
275 self.leave()
Mark Dickinson8d6d7602010-06-30 08:32:11 +0000276 # collapse nested ifs into equivalent elifs.
277 while (t.orelse and len(t.orelse) == 1 and
278 isinstance(t.orelse[0], ast.If)):
279 t = t.orelse[0]
280 self.fill("elif ")
281 self.dispatch(t.test)
282 self.enter()
283 self.dispatch(t.body)
284 self.leave()
285 # final else
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000286 if t.orelse:
287 self.fill("else")
288 self.enter()
289 self.dispatch(t.orelse)
290 self.leave()
291
292 def _While(self, t):
293 self.fill("while ")
294 self.dispatch(t.test)
295 self.enter()
296 self.dispatch(t.body)
297 self.leave()
298 if t.orelse:
299 self.fill("else")
300 self.enter()
301 self.dispatch(t.orelse)
Mark Dickinsonae100052010-06-28 19:44:20 +0000302 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000303
304 def _With(self, t):
305 self.fill("with ")
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100306 interleave(lambda: self.write(", "), self.dispatch, t.items)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000307 self.enter()
308 self.dispatch(t.body)
309 self.leave()
310
Yury Selivanov75445082015-05-11 22:57:16 -0400311 def _AsyncWith(self, t):
312 self.fill("async with ")
313 interleave(lambda: self.write(", "), self.dispatch, t.items)
314 self.enter()
315 self.dispatch(t.body)
316 self.leave()
317
Tim Peters400cbc32006-02-28 18:44:41 +0000318 # expr
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000319 def _Bytes(self, t):
320 self.write(repr(t.s))
321
Tim Peters400cbc32006-02-28 18:44:41 +0000322 def _Str(self, tree):
323 self.write(repr(tree.s))
324
Eric V. Smith608adf92015-09-20 15:09:15 -0400325 def _JoinedStr(self, t):
326 self.write("f")
327 string = io.StringIO()
328 self._fstring_JoinedStr(t, string.write)
329 self.write(repr(string.getvalue()))
330
331 def _FormattedValue(self, t):
332 self.write("f")
333 string = io.StringIO()
334 self._fstring_FormattedValue(t, string.write)
335 self.write(repr(string.getvalue()))
336
337 def _fstring_JoinedStr(self, t, write):
338 for value in t.values:
339 meth = getattr(self, "_fstring_" + type(value).__name__)
340 meth(value, write)
341
342 def _fstring_Str(self, t, write):
343 value = t.s.replace("{", "{{").replace("}", "}}")
344 write(value)
345
Victor Stinnerf2c1aa12016-01-26 00:40:57 +0100346 def _fstring_Constant(self, t, write):
347 assert isinstance(t.value, str)
348 value = t.value.replace("{", "{{").replace("}", "}}")
349 write(value)
350
Eric V. Smith608adf92015-09-20 15:09:15 -0400351 def _fstring_FormattedValue(self, t, write):
352 write("{")
353 expr = io.StringIO()
354 Unparser(t.value, expr)
355 expr = expr.getvalue().rstrip("\n")
356 if expr.startswith("{"):
357 write(" ") # Separate pair of opening brackets as "{ {"
358 write(expr)
359 if t.conversion != -1:
360 conversion = chr(t.conversion)
361 assert conversion in "sra"
362 write(f"!{conversion}")
363 if t.format_spec:
364 write(":")
365 meth = getattr(self, "_fstring_" + type(t.format_spec).__name__)
366 meth(t.format_spec, write)
367 write("}")
368
Tim Peters400cbc32006-02-28 18:44:41 +0000369 def _Name(self, t):
370 self.write(t.id)
371
Victor Stinnerf2c1aa12016-01-26 00:40:57 +0100372 def _write_constant(self, value):
373 if isinstance(value, (float, complex)):
374 self.write(repr(value).replace("inf", INFSTR))
375 else:
376 self.write(repr(value))
377
378 def _Constant(self, t):
379 value = t.value
380 if isinstance(value, tuple):
381 self.write("(")
382 if len(value) == 1:
383 self._write_constant(value[0])
384 self.write(",")
385 else:
386 interleave(lambda: self.write(", "), self._write_constant, value)
387 self.write(")")
388 else:
389 self._write_constant(t.value)
390
Benjamin Peterson442f2092012-12-06 17:41:04 -0500391 def _NameConstant(self, t):
392 self.write(repr(t.value))
393
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000394 def _Num(self, t):
Mark Dickinsoncba8c102010-06-30 11:45:53 +0000395 # Substitute overflowing decimal literal for AST infinities.
396 self.write(repr(t.n).replace("inf", INFSTR))
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000397
Tim Peters400cbc32006-02-28 18:44:41 +0000398 def _List(self, t):
399 self.write("[")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000400 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Tim Peters400cbc32006-02-28 18:44:41 +0000401 self.write("]")
402
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000403 def _ListComp(self, t):
404 self.write("[")
405 self.dispatch(t.elt)
406 for gen in t.generators:
407 self.dispatch(gen)
408 self.write("]")
409
410 def _GeneratorExp(self, t):
411 self.write("(")
412 self.dispatch(t.elt)
413 for gen in t.generators:
414 self.dispatch(gen)
415 self.write(")")
416
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000417 def _SetComp(self, t):
418 self.write("{")
419 self.dispatch(t.elt)
420 for gen in t.generators:
421 self.dispatch(gen)
422 self.write("}")
423
424 def _DictComp(self, t):
425 self.write("{")
426 self.dispatch(t.key)
427 self.write(": ")
428 self.dispatch(t.value)
429 for gen in t.generators:
430 self.dispatch(gen)
431 self.write("}")
432
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000433 def _comprehension(self, t):
434 self.write(" for ")
435 self.dispatch(t.target)
436 self.write(" in ")
437 self.dispatch(t.iter)
438 for if_clause in t.ifs:
439 self.write(" if ")
440 self.dispatch(if_clause)
441
442 def _IfExp(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000443 self.write("(")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000444 self.dispatch(t.body)
445 self.write(" if ")
446 self.dispatch(t.test)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000447 self.write(" else ")
448 self.dispatch(t.orelse)
449 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000450
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000451 def _Set(self, t):
452 assert(t.elts) # should be at least one element
453 self.write("{")
454 interleave(lambda: self.write(", "), self.dispatch, t.elts)
455 self.write("}")
456
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000457 def _Dict(self, t):
458 self.write("{")
Berker Peksagd66dd5c2016-03-06 16:50:15 +0200459 def write_key_value_pair(k, v):
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000460 self.dispatch(k)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000461 self.write(": ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000462 self.dispatch(v)
Berker Peksagd66dd5c2016-03-06 16:50:15 +0200463
464 def write_item(item):
465 k, v = item
466 if k is None:
467 # for dictionary unpacking operator in dicts {**{'y': 2}}
468 # see PEP 448 for details
469 self.write("**")
470 self.dispatch(v)
471 else:
472 write_key_value_pair(k, v)
473 interleave(lambda: self.write(", "), write_item, zip(t.keys, t.values))
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000474 self.write("}")
475
476 def _Tuple(self, t):
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000477 self.write("(")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000478 if len(t.elts) == 1:
Victor Stinnerf2c1aa12016-01-26 00:40:57 +0100479 elt = t.elts[0]
Guido van Rossumd8faa362007-04-27 19:54:29 +0000480 self.dispatch(elt)
481 self.write(",")
482 else:
483 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000484 self.write(")")
485
Tim Peters400cbc32006-02-28 18:44:41 +0000486 unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}
487 def _UnaryOp(self, t):
Tim Peters400cbc32006-02-28 18:44:41 +0000488 self.write("(")
Mark Dickinsonae100052010-06-28 19:44:20 +0000489 self.write(self.unop[t.op.__class__.__name__])
490 self.write(" ")
Tim Peters400cbc32006-02-28 18:44:41 +0000491 self.dispatch(t.operand)
492 self.write(")")
493
Benjamin Peterson63c46b22014-04-10 00:17:48 -0400494 binop = { "Add":"+", "Sub":"-", "Mult":"*", "MatMult":"@", "Div":"/", "Mod":"%",
Mark Dickinsonae100052010-06-28 19:44:20 +0000495 "LShift":"<<", "RShift":">>", "BitOr":"|", "BitXor":"^", "BitAnd":"&",
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000496 "FloorDiv":"//", "Pow": "**"}
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000497 def _BinOp(self, t):
498 self.write("(")
499 self.dispatch(t.left)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000500 self.write(" " + self.binop[t.op.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000501 self.dispatch(t.right)
502 self.write(")")
503
504 cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=",
505 "Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"}
506 def _Compare(self, t):
507 self.write("(")
508 self.dispatch(t.left)
509 for o, e in zip(t.ops, t.comparators):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000510 self.write(" " + self.cmpops[o.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000511 self.dispatch(e)
Mark Dickinsonf5451e52010-06-28 20:09:18 +0000512 self.write(")")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000513
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000514 boolops = {ast.And: 'and', ast.Or: 'or'}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000515 def _BoolOp(self, t):
516 self.write("(")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000517 s = " %s " % self.boolops[t.op.__class__]
518 interleave(lambda: self.write(s), self.dispatch, t.values)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000519 self.write(")")
520
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000521 def _Attribute(self,t):
522 self.dispatch(t.value)
Mark Dickinsonb67e15c2010-06-30 09:05:47 +0000523 # Special case: 3.__abs__() is a syntax error, so if t.value
524 # is an integer literal then we need to either parenthesize
525 # it or add an extra space to get 3 .__abs__().
Victor Stinnerf2c1aa12016-01-26 00:40:57 +0100526 if ((isinstance(t.value, ast.Num) and isinstance(t.value.n, int))
527 or (isinstance(t.value, ast.Constant) and isinstance(t.value.value, int))):
Mark Dickinsonb67e15c2010-06-30 09:05:47 +0000528 self.write(" ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000529 self.write(".")
530 self.write(t.attr)
531
532 def _Call(self, t):
533 self.dispatch(t.func)
534 self.write("(")
535 comma = False
536 for e in t.args:
537 if comma: self.write(", ")
538 else: comma = True
539 self.dispatch(e)
540 for e in t.keywords:
541 if comma: self.write(", ")
542 else: comma = True
543 self.dispatch(e)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000544 self.write(")")
545
546 def _Subscript(self, t):
547 self.dispatch(t.value)
548 self.write("[")
549 self.dispatch(t.slice)
550 self.write("]")
551
Mark Dickinson1b2e9442012-05-06 17:27:39 +0100552 def _Starred(self, t):
553 self.write("*")
554 self.dispatch(t.value)
555
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000556 # slice
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000557 def _Ellipsis(self, t):
558 self.write("...")
559
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000560 def _Index(self, t):
561 self.dispatch(t.value)
562
563 def _Slice(self, t):
564 if t.lower:
565 self.dispatch(t.lower)
566 self.write(":")
567 if t.upper:
568 self.dispatch(t.upper)
569 if t.step:
570 self.write(":")
571 self.dispatch(t.step)
572
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000573 def _ExtSlice(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000574 interleave(lambda: self.write(', '), self.dispatch, t.dims)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000575
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000576 # argument
577 def _arg(self, t):
578 self.write(t.arg)
579 if t.annotation:
580 self.write(": ")
581 self.dispatch(t.annotation)
582
Tim Peters400cbc32006-02-28 18:44:41 +0000583 # others
584 def _arguments(self, t):
585 first = True
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000586 # normal arguments
587 defaults = [None] * (len(t.args) - len(t.defaults)) + t.defaults
588 for a, d in zip(t.args, defaults):
Tim Peters400cbc32006-02-28 18:44:41 +0000589 if first:first = False
590 else: self.write(", ")
591 self.dispatch(a)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000592 if d:
593 self.write("=")
594 self.dispatch(d)
595
596 # varargs, or bare '*' if no varargs but keyword-only arguments present
597 if t.vararg or t.kwonlyargs:
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000598 if first:first = False
599 else: self.write(", ")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000600 self.write("*")
601 if t.vararg:
Benjamin Petersoncda75be2013-03-18 10:48:58 -0700602 self.write(t.vararg.arg)
603 if t.vararg.annotation:
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000604 self.write(": ")
Benjamin Petersoncda75be2013-03-18 10:48:58 -0700605 self.dispatch(t.vararg.annotation)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000606
607 # keyword-only arguments
608 if t.kwonlyargs:
609 for a, d in zip(t.kwonlyargs, t.kw_defaults):
610 if first:first = False
611 else: self.write(", ")
612 self.dispatch(a),
613 if d:
614 self.write("=")
615 self.dispatch(d)
616
617 # kwargs
Tim Peters400cbc32006-02-28 18:44:41 +0000618 if t.kwarg:
619 if first:first = False
620 else: self.write(", ")
Benjamin Petersoncda75be2013-03-18 10:48:58 -0700621 self.write("**"+t.kwarg.arg)
622 if t.kwarg.annotation:
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000623 self.write(": ")
Benjamin Petersoncda75be2013-03-18 10:48:58 -0700624 self.dispatch(t.kwarg.annotation)
Tim Peters400cbc32006-02-28 18:44:41 +0000625
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000626 def _keyword(self, t):
Benjamin Peterson025e9eb2015-05-05 20:16:41 -0400627 if t.arg is None:
628 self.write("**")
629 else:
630 self.write(t.arg)
631 self.write("=")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000632 self.dispatch(t.value)
633
634 def _Lambda(self, t):
Mark Dickinson8042e282010-06-29 10:01:48 +0000635 self.write("(")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000636 self.write("lambda ")
637 self.dispatch(t.args)
638 self.write(": ")
639 self.dispatch(t.body)
Mark Dickinson8042e282010-06-29 10:01:48 +0000640 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000641
Guido van Rossumd8faa362007-04-27 19:54:29 +0000642 def _alias(self, t):
643 self.write(t.name)
644 if t.asname:
645 self.write(" as "+t.asname)
646
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100647 def _withitem(self, t):
648 self.dispatch(t.context_expr)
649 if t.optional_vars:
650 self.write(" as ")
651 self.dispatch(t.optional_vars)
652
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000653def roundtrip(filename, output=sys.stdout):
Mark Dickinson82c8d932010-06-29 07:48:23 +0000654 with open(filename, "rb") as pyfile:
655 encoding = tokenize.detect_encoding(pyfile.readline)[0]
656 with open(filename, "r", encoding=encoding) as pyfile:
657 source = pyfile.read()
Mark Dickinson3d1bfbf2010-06-28 21:39:51 +0000658 tree = compile(source, filename, "exec", ast.PyCF_ONLY_AST)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000659 Unparser(tree, output)
660
661
662
663def testdir(a):
664 try:
665 names = [n for n in os.listdir(a) if n.endswith('.py')]
666 except OSError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000667 print("Directory not readable: %s" % a, file=sys.stderr)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000668 else:
669 for n in names:
670 fullname = os.path.join(a, n)
671 if os.path.isfile(fullname):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000672 output = io.StringIO()
673 print('Testing %s' % fullname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000674 try:
675 roundtrip(fullname, output)
Guido van Rossumb940e112007-01-10 16:19:56 +0000676 except Exception as e:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000677 print(' Failed to compile, exception is %s' % repr(e))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000678 elif os.path.isdir(fullname):
679 testdir(fullname)
680
681def main(args):
682 if args[0] == '--testdir':
683 for a in args[1:]:
684 testdir(a)
685 else:
686 for a in args:
687 roundtrip(a)
Tim Peters400cbc32006-02-28 18:44:41 +0000688
689if __name__=='__main__':
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000690 main(sys.argv[1:])