blob: 0642b84dcfc8288741df547a249d36ecdc69ea47 [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
Victor Stinner1396d8f2019-01-25 01:49:53 +010082 def _NamedExpr(self, tree):
83 self.write("(")
84 self.dispatch(tree.target)
85 self.write(" := ")
86 self.dispatch(tree.value)
87 self.write(")")
88
Tim Peters400cbc32006-02-28 18:44:41 +000089 def _Import(self, t):
90 self.fill("import ")
Guido van Rossumd8faa362007-04-27 19:54:29 +000091 interleave(lambda: self.write(", "), self.dispatch, t.names)
Tim Peters400cbc32006-02-28 18:44:41 +000092
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000093 def _ImportFrom(self, t):
94 self.fill("from ")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +000095 self.write("." * t.level)
96 if t.module:
97 self.write(t.module)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000098 self.write(" import ")
Guido van Rossumd8faa362007-04-27 19:54:29 +000099 interleave(lambda: self.write(", "), self.dispatch, t.names)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000100
Tim Peters400cbc32006-02-28 18:44:41 +0000101 def _Assign(self, t):
102 self.fill()
103 for target in t.targets:
104 self.dispatch(target)
105 self.write(" = ")
106 self.dispatch(t.value)
107
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000108 def _AugAssign(self, t):
109 self.fill()
110 self.dispatch(t.target)
111 self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
112 self.dispatch(t.value)
113
Yury Selivanovf8cb8a12016-09-08 20:50:03 -0700114 def _AnnAssign(self, t):
115 self.fill()
116 if not t.simple and isinstance(t.target, ast.Name):
117 self.write('(')
118 self.dispatch(t.target)
119 if not t.simple and isinstance(t.target, ast.Name):
120 self.write(')')
121 self.write(": ")
122 self.dispatch(t.annotation)
123 if t.value:
124 self.write(" = ")
125 self.dispatch(t.value)
126
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000127 def _Return(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000128 self.fill("return")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000129 if t.value:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000130 self.write(" ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000131 self.dispatch(t.value)
132
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000133 def _Pass(self, t):
134 self.fill("pass")
135
136 def _Break(self, t):
137 self.fill("break")
138
139 def _Continue(self, t):
140 self.fill("continue")
141
142 def _Delete(self, t):
143 self.fill("del ")
Mark Dickinsonae100052010-06-28 19:44:20 +0000144 interleave(lambda: self.write(", "), self.dispatch, t.targets)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000145
146 def _Assert(self, t):
147 self.fill("assert ")
148 self.dispatch(t.test)
149 if t.msg:
150 self.write(", ")
151 self.dispatch(t.msg)
152
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000153 def _Global(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000154 self.fill("global ")
155 interleave(lambda: self.write(", "), self.write, t.names)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000156
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000157 def _Nonlocal(self, t):
158 self.fill("nonlocal ")
159 interleave(lambda: self.write(", "), self.write, t.names)
160
Yury Selivanov75445082015-05-11 22:57:16 -0400161 def _Await(self, t):
162 self.write("(")
163 self.write("await")
164 if t.value:
165 self.write(" ")
166 self.dispatch(t.value)
167 self.write(")")
168
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000169 def _Yield(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000170 self.write("(")
171 self.write("yield")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000172 if t.value:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000173 self.write(" ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000174 self.dispatch(t.value)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000175 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000176
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100177 def _YieldFrom(self, t):
178 self.write("(")
179 self.write("yield from")
180 if t.value:
181 self.write(" ")
182 self.dispatch(t.value)
183 self.write(")")
184
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000185 def _Raise(self, t):
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000186 self.fill("raise")
187 if not t.exc:
188 assert not t.cause
189 return
190 self.write(" ")
191 self.dispatch(t.exc)
192 if t.cause:
193 self.write(" from ")
194 self.dispatch(t.cause)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000195
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100196 def _Try(self, t):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000197 self.fill("try")
198 self.enter()
199 self.dispatch(t.body)
200 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000201 for ex in t.handlers:
202 self.dispatch(ex)
203 if t.orelse:
204 self.fill("else")
205 self.enter()
206 self.dispatch(t.orelse)
207 self.leave()
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100208 if t.finalbody:
209 self.fill("finally")
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000210 self.enter()
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100211 self.dispatch(t.finalbody)
Mark Dickinson81ad8cc2010-06-30 08:46:53 +0000212 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000213
Benjamin Petersonc4fe6f32008-08-19 18:57:56 +0000214 def _ExceptHandler(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000215 self.fill("except")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000216 if t.type:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000217 self.write(" ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000218 self.dispatch(t.type)
219 if t.name:
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000220 self.write(" as ")
221 self.write(t.name)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000222 self.enter()
223 self.dispatch(t.body)
224 self.leave()
225
Tim Peters400cbc32006-02-28 18:44:41 +0000226 def _ClassDef(self, t):
227 self.write("\n")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000228 for deco in t.decorator_list:
229 self.fill("@")
230 self.dispatch(deco)
Tim Peters400cbc32006-02-28 18:44:41 +0000231 self.fill("class "+t.name)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000232 self.write("(")
233 comma = False
234 for e in t.bases:
235 if comma: self.write(", ")
236 else: comma = True
237 self.dispatch(e)
238 for e in t.keywords:
239 if comma: self.write(", ")
240 else: comma = True
241 self.dispatch(e)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000242 self.write(")")
243
Tim Peters400cbc32006-02-28 18:44:41 +0000244 self.enter()
245 self.dispatch(t.body)
246 self.leave()
247
248 def _FunctionDef(self, t):
Yury Selivanov75445082015-05-11 22:57:16 -0400249 self.__FunctionDef_helper(t, "def")
250
251 def _AsyncFunctionDef(self, t):
252 self.__FunctionDef_helper(t, "async def")
253
254 def __FunctionDef_helper(self, t, fill_suffix):
Tim Peters400cbc32006-02-28 18:44:41 +0000255 self.write("\n")
Benjamin Petersonc4fe6f32008-08-19 18:57:56 +0000256 for deco in t.decorator_list:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000257 self.fill("@")
258 self.dispatch(deco)
Yury Selivanov75445082015-05-11 22:57:16 -0400259 def_str = fill_suffix+" "+t.name + "("
260 self.fill(def_str)
Tim Peters400cbc32006-02-28 18:44:41 +0000261 self.dispatch(t.args)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000262 self.write(")")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000263 if t.returns:
264 self.write(" -> ")
265 self.dispatch(t.returns)
Tim Peters400cbc32006-02-28 18:44:41 +0000266 self.enter()
267 self.dispatch(t.body)
268 self.leave()
269
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000270 def _For(self, t):
Yury Selivanov75445082015-05-11 22:57:16 -0400271 self.__For_helper("for ", t)
272
273 def _AsyncFor(self, t):
274 self.__For_helper("async for ", t)
275
276 def __For_helper(self, fill, t):
277 self.fill(fill)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000278 self.dispatch(t.target)
279 self.write(" in ")
280 self.dispatch(t.iter)
281 self.enter()
282 self.dispatch(t.body)
283 self.leave()
284 if t.orelse:
285 self.fill("else")
286 self.enter()
287 self.dispatch(t.orelse)
Mark Dickinsonae100052010-06-28 19:44:20 +0000288 self.leave()
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000289
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000290 def _If(self, t):
291 self.fill("if ")
292 self.dispatch(t.test)
293 self.enter()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000294 self.dispatch(t.body)
295 self.leave()
Mark Dickinson8d6d7602010-06-30 08:32:11 +0000296 # collapse nested ifs into equivalent elifs.
297 while (t.orelse and len(t.orelse) == 1 and
298 isinstance(t.orelse[0], ast.If)):
299 t = t.orelse[0]
300 self.fill("elif ")
301 self.dispatch(t.test)
302 self.enter()
303 self.dispatch(t.body)
304 self.leave()
305 # final else
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000306 if t.orelse:
307 self.fill("else")
308 self.enter()
309 self.dispatch(t.orelse)
310 self.leave()
311
312 def _While(self, t):
313 self.fill("while ")
314 self.dispatch(t.test)
315 self.enter()
316 self.dispatch(t.body)
317 self.leave()
318 if t.orelse:
319 self.fill("else")
320 self.enter()
321 self.dispatch(t.orelse)
Mark Dickinsonae100052010-06-28 19:44:20 +0000322 self.leave()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000323
324 def _With(self, t):
325 self.fill("with ")
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100326 interleave(lambda: self.write(", "), self.dispatch, t.items)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000327 self.enter()
328 self.dispatch(t.body)
329 self.leave()
330
Yury Selivanov75445082015-05-11 22:57:16 -0400331 def _AsyncWith(self, t):
332 self.fill("async with ")
333 interleave(lambda: self.write(", "), self.dispatch, t.items)
334 self.enter()
335 self.dispatch(t.body)
336 self.leave()
337
Tim Peters400cbc32006-02-28 18:44:41 +0000338 # expr
Eric V. Smith608adf92015-09-20 15:09:15 -0400339 def _JoinedStr(self, t):
340 self.write("f")
341 string = io.StringIO()
342 self._fstring_JoinedStr(t, string.write)
343 self.write(repr(string.getvalue()))
344
345 def _FormattedValue(self, t):
346 self.write("f")
347 string = io.StringIO()
348 self._fstring_FormattedValue(t, string.write)
349 self.write(repr(string.getvalue()))
350
351 def _fstring_JoinedStr(self, t, write):
352 for value in t.values:
353 meth = getattr(self, "_fstring_" + type(value).__name__)
354 meth(value, write)
355
Victor Stinnerf2c1aa12016-01-26 00:40:57 +0100356 def _fstring_Constant(self, t, write):
357 assert isinstance(t.value, str)
358 value = t.value.replace("{", "{{").replace("}", "}}")
359 write(value)
360
Eric V. Smith608adf92015-09-20 15:09:15 -0400361 def _fstring_FormattedValue(self, t, write):
362 write("{")
363 expr = io.StringIO()
364 Unparser(t.value, expr)
365 expr = expr.getvalue().rstrip("\n")
366 if expr.startswith("{"):
367 write(" ") # Separate pair of opening brackets as "{ {"
368 write(expr)
369 if t.conversion != -1:
370 conversion = chr(t.conversion)
371 assert conversion in "sra"
372 write(f"!{conversion}")
373 if t.format_spec:
374 write(":")
375 meth = getattr(self, "_fstring_" + type(t.format_spec).__name__)
376 meth(t.format_spec, write)
377 write("}")
378
Tim Peters400cbc32006-02-28 18:44:41 +0000379 def _Name(self, t):
380 self.write(t.id)
381
Victor Stinnerf2c1aa12016-01-26 00:40:57 +0100382 def _write_constant(self, value):
383 if isinstance(value, (float, complex)):
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300384 # Substitute overflowing decimal literal for AST infinities.
Victor Stinnerf2c1aa12016-01-26 00:40:57 +0100385 self.write(repr(value).replace("inf", INFSTR))
386 else:
387 self.write(repr(value))
388
389 def _Constant(self, t):
390 value = t.value
391 if isinstance(value, tuple):
392 self.write("(")
393 if len(value) == 1:
394 self._write_constant(value[0])
395 self.write(",")
396 else:
397 interleave(lambda: self.write(", "), self._write_constant, value)
398 self.write(")")
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300399 elif value is ...:
400 self.write("...")
Victor Stinnerf2c1aa12016-01-26 00:40:57 +0100401 else:
Chih-Hsuan Yenaaf47ca2019-05-27 01:08:20 +0800402 if t.kind == "u":
403 self.write("u")
Victor Stinnerf2c1aa12016-01-26 00:40:57 +0100404 self._write_constant(t.value)
405
Tim Peters400cbc32006-02-28 18:44:41 +0000406 def _List(self, t):
407 self.write("[")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000408 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Tim Peters400cbc32006-02-28 18:44:41 +0000409 self.write("]")
410
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000411 def _ListComp(self, t):
412 self.write("[")
413 self.dispatch(t.elt)
414 for gen in t.generators:
415 self.dispatch(gen)
416 self.write("]")
417
418 def _GeneratorExp(self, t):
419 self.write("(")
420 self.dispatch(t.elt)
421 for gen in t.generators:
422 self.dispatch(gen)
423 self.write(")")
424
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000425 def _SetComp(self, t):
426 self.write("{")
427 self.dispatch(t.elt)
428 for gen in t.generators:
429 self.dispatch(gen)
430 self.write("}")
431
432 def _DictComp(self, t):
433 self.write("{")
434 self.dispatch(t.key)
435 self.write(": ")
436 self.dispatch(t.value)
437 for gen in t.generators:
438 self.dispatch(gen)
439 self.write("}")
440
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000441 def _comprehension(self, t):
Yury Selivanovbf04b062016-09-09 11:48:39 -0700442 if t.is_async:
443 self.write(" async for ")
444 else:
445 self.write(" for ")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000446 self.dispatch(t.target)
447 self.write(" in ")
448 self.dispatch(t.iter)
449 for if_clause in t.ifs:
450 self.write(" if ")
451 self.dispatch(if_clause)
452
453 def _IfExp(self, t):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000454 self.write("(")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000455 self.dispatch(t.body)
456 self.write(" if ")
457 self.dispatch(t.test)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000458 self.write(" else ")
459 self.dispatch(t.orelse)
460 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000461
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000462 def _Set(self, t):
463 assert(t.elts) # should be at least one element
464 self.write("{")
465 interleave(lambda: self.write(", "), self.dispatch, t.elts)
466 self.write("}")
467
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000468 def _Dict(self, t):
469 self.write("{")
Berker Peksagd66dd5c2016-03-06 16:50:15 +0200470 def write_key_value_pair(k, v):
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000471 self.dispatch(k)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000472 self.write(": ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000473 self.dispatch(v)
Berker Peksagd66dd5c2016-03-06 16:50:15 +0200474
475 def write_item(item):
476 k, v = item
477 if k is None:
478 # for dictionary unpacking operator in dicts {**{'y': 2}}
479 # see PEP 448 for details
480 self.write("**")
481 self.dispatch(v)
482 else:
483 write_key_value_pair(k, v)
484 interleave(lambda: self.write(", "), write_item, zip(t.keys, t.values))
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000485 self.write("}")
486
487 def _Tuple(self, t):
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000488 self.write("(")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000489 if len(t.elts) == 1:
Victor Stinnerf2c1aa12016-01-26 00:40:57 +0100490 elt = t.elts[0]
Guido van Rossumd8faa362007-04-27 19:54:29 +0000491 self.dispatch(elt)
492 self.write(",")
493 else:
494 interleave(lambda: self.write(", "), self.dispatch, t.elts)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000495 self.write(")")
496
Tim Peters400cbc32006-02-28 18:44:41 +0000497 unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}
498 def _UnaryOp(self, t):
Tim Peters400cbc32006-02-28 18:44:41 +0000499 self.write("(")
Mark Dickinsonae100052010-06-28 19:44:20 +0000500 self.write(self.unop[t.op.__class__.__name__])
501 self.write(" ")
Tim Peters400cbc32006-02-28 18:44:41 +0000502 self.dispatch(t.operand)
503 self.write(")")
504
Benjamin Peterson63c46b22014-04-10 00:17:48 -0400505 binop = { "Add":"+", "Sub":"-", "Mult":"*", "MatMult":"@", "Div":"/", "Mod":"%",
Mark Dickinsonae100052010-06-28 19:44:20 +0000506 "LShift":"<<", "RShift":">>", "BitOr":"|", "BitXor":"^", "BitAnd":"&",
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000507 "FloorDiv":"//", "Pow": "**"}
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000508 def _BinOp(self, t):
509 self.write("(")
510 self.dispatch(t.left)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000511 self.write(" " + self.binop[t.op.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000512 self.dispatch(t.right)
513 self.write(")")
514
515 cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=",
516 "Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"}
517 def _Compare(self, t):
518 self.write("(")
519 self.dispatch(t.left)
520 for o, e in zip(t.ops, t.comparators):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000521 self.write(" " + self.cmpops[o.__class__.__name__] + " ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000522 self.dispatch(e)
Mark Dickinsonf5451e52010-06-28 20:09:18 +0000523 self.write(")")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000524
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000525 boolops = {ast.And: 'and', ast.Or: 'or'}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000526 def _BoolOp(self, t):
527 self.write("(")
Guido van Rossumd8faa362007-04-27 19:54:29 +0000528 s = " %s " % self.boolops[t.op.__class__]
529 interleave(lambda: self.write(s), self.dispatch, t.values)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000530 self.write(")")
531
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000532 def _Attribute(self,t):
533 self.dispatch(t.value)
Mark Dickinsonb67e15c2010-06-30 09:05:47 +0000534 # Special case: 3.__abs__() is a syntax error, so if t.value
535 # is an integer literal then we need to either parenthesize
536 # it or add an extra space to get 3 .__abs__().
Serhiy Storchaka3f228112018-09-27 17:42:37 +0300537 if isinstance(t.value, ast.Constant) and isinstance(t.value.value, int):
Mark Dickinsonb67e15c2010-06-30 09:05:47 +0000538 self.write(" ")
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000539 self.write(".")
540 self.write(t.attr)
541
542 def _Call(self, t):
543 self.dispatch(t.func)
544 self.write("(")
545 comma = False
546 for e in t.args:
547 if comma: self.write(", ")
548 else: comma = True
549 self.dispatch(e)
550 for e in t.keywords:
551 if comma: self.write(", ")
552 else: comma = True
553 self.dispatch(e)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000554 self.write(")")
555
556 def _Subscript(self, t):
557 self.dispatch(t.value)
558 self.write("[")
Serhiy Storchaka92b72782020-03-07 18:55:32 +0200559 if (isinstance(t.slice, ast.Index)
560 and isinstance(t.slice.value, ast.Tuple)
561 and t.slice.value.elts):
562 if len(t.slice.value.elts) == 1:
563 elt = t.slice.value.elts[0]
564 self.dispatch(elt)
565 self.write(",")
566 else:
567 interleave(lambda: self.write(", "), self.dispatch, t.slice.value.elts)
568 else:
569 self.dispatch(t.slice)
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000570 self.write("]")
571
Mark Dickinson1b2e9442012-05-06 17:27:39 +0100572 def _Starred(self, t):
573 self.write("*")
574 self.dispatch(t.value)
575
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000576 # slice
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000577 def _Ellipsis(self, t):
578 self.write("...")
579
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000580 def _Index(self, t):
581 self.dispatch(t.value)
582
583 def _Slice(self, t):
584 if t.lower:
585 self.dispatch(t.lower)
586 self.write(":")
587 if t.upper:
588 self.dispatch(t.upper)
589 if t.step:
590 self.write(":")
591 self.dispatch(t.step)
592
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000593 def _ExtSlice(self, t):
Serhiy Storchaka92b72782020-03-07 18:55:32 +0200594 if len(t.dims) == 1:
595 elt = t.dims[0]
596 self.dispatch(elt)
597 self.write(",")
598 else:
599 interleave(lambda: self.write(', '), self.dispatch, t.dims)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000600
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000601 # argument
602 def _arg(self, t):
603 self.write(t.arg)
604 if t.annotation:
605 self.write(": ")
606 self.dispatch(t.annotation)
607
Tim Peters400cbc32006-02-28 18:44:41 +0000608 # others
609 def _arguments(self, t):
610 first = True
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000611 # normal arguments
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100612 all_args = t.posonlyargs + t.args
613 defaults = [None] * (len(all_args) - len(t.defaults)) + t.defaults
614 for index, elements in enumerate(zip(all_args, defaults), 1):
615 a, d = elements
Tim Peters400cbc32006-02-28 18:44:41 +0000616 if first:first = False
617 else: self.write(", ")
618 self.dispatch(a)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000619 if d:
620 self.write("=")
621 self.dispatch(d)
Pablo Galindo8c77b8c2019-04-29 13:36:57 +0100622 if index == len(t.posonlyargs):
623 self.write(", /")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000624
625 # varargs, or bare '*' if no varargs but keyword-only arguments present
626 if t.vararg or t.kwonlyargs:
Martin v. Löwis87a8b4f2006-02-28 21:41:30 +0000627 if first:first = False
628 else: self.write(", ")
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000629 self.write("*")
630 if t.vararg:
Benjamin Petersoncda75be2013-03-18 10:48:58 -0700631 self.write(t.vararg.arg)
632 if t.vararg.annotation:
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000633 self.write(": ")
Benjamin Petersoncda75be2013-03-18 10:48:58 -0700634 self.dispatch(t.vararg.annotation)
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000635
636 # keyword-only arguments
637 if t.kwonlyargs:
638 for a, d in zip(t.kwonlyargs, t.kw_defaults):
639 if first:first = False
640 else: self.write(", ")
641 self.dispatch(a),
642 if d:
643 self.write("=")
644 self.dispatch(d)
645
646 # kwargs
Tim Peters400cbc32006-02-28 18:44:41 +0000647 if t.kwarg:
648 if first:first = False
649 else: self.write(", ")
Benjamin Petersoncda75be2013-03-18 10:48:58 -0700650 self.write("**"+t.kwarg.arg)
651 if t.kwarg.annotation:
Mark Dickinsonfa2e4e92010-06-28 21:14:17 +0000652 self.write(": ")
Benjamin Petersoncda75be2013-03-18 10:48:58 -0700653 self.dispatch(t.kwarg.annotation)
Tim Peters400cbc32006-02-28 18:44:41 +0000654
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000655 def _keyword(self, t):
Benjamin Peterson025e9eb2015-05-05 20:16:41 -0400656 if t.arg is None:
657 self.write("**")
658 else:
659 self.write(t.arg)
660 self.write("=")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000661 self.dispatch(t.value)
662
663 def _Lambda(self, t):
Mark Dickinson8042e282010-06-29 10:01:48 +0000664 self.write("(")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000665 self.write("lambda ")
666 self.dispatch(t.args)
667 self.write(": ")
668 self.dispatch(t.body)
Mark Dickinson8042e282010-06-29 10:01:48 +0000669 self.write(")")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000670
Guido van Rossumd8faa362007-04-27 19:54:29 +0000671 def _alias(self, t):
672 self.write(t.name)
673 if t.asname:
674 self.write(" as "+t.asname)
675
Mark Dickinsonfe8440a2012-05-06 17:35:19 +0100676 def _withitem(self, t):
677 self.dispatch(t.context_expr)
678 if t.optional_vars:
679 self.write(" as ")
680 self.dispatch(t.optional_vars)
681
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000682def roundtrip(filename, output=sys.stdout):
Mark Dickinson82c8d932010-06-29 07:48:23 +0000683 with open(filename, "rb") as pyfile:
684 encoding = tokenize.detect_encoding(pyfile.readline)[0]
685 with open(filename, "r", encoding=encoding) as pyfile:
686 source = pyfile.read()
Mark Dickinson3d1bfbf2010-06-28 21:39:51 +0000687 tree = compile(source, filename, "exec", ast.PyCF_ONLY_AST)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000688 Unparser(tree, output)
689
690
691
692def testdir(a):
693 try:
694 names = [n for n in os.listdir(a) if n.endswith('.py')]
695 except OSError:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000696 print("Directory not readable: %s" % a, file=sys.stderr)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000697 else:
698 for n in names:
699 fullname = os.path.join(a, n)
700 if os.path.isfile(fullname):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000701 output = io.StringIO()
702 print('Testing %s' % fullname)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000703 try:
704 roundtrip(fullname, output)
Guido van Rossumb940e112007-01-10 16:19:56 +0000705 except Exception as e:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000706 print(' Failed to compile, exception is %s' % repr(e))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000707 elif os.path.isdir(fullname):
708 testdir(fullname)
709
710def main(args):
711 if args[0] == '--testdir':
712 for a in args[1:]:
713 testdir(a)
714 else:
715 for a in args:
716 roundtrip(a)
Tim Peters400cbc32006-02-28 18:44:41 +0000717
718if __name__=='__main__':
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000719 main(sys.argv[1:])