Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/astunparse/unparser.py: 15%
718 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
1"Usage: unparse.py <path to source file>"
2from __future__ import print_function, unicode_literals
3import six
4import sys
5import ast
6import os
7import tokenize
8from six import StringIO
10# Large float and imaginary literals get turned into infinities in the AST.
11# We unparse those infinities to INFSTR.
12INFSTR = "1e" + repr(sys.float_info.max_10_exp + 1)
14def interleave(inter, f, seq):
15 """Call f on each item in seq, calling inter() in between.
16 """
17 seq = iter(seq)
18 try:
19 f(next(seq))
20 except StopIteration:
21 pass
22 else:
23 for x in seq:
24 inter()
25 f(x)
27class Unparser:
28 """Methods in this class recursively traverse an AST and
29 output source code for the abstract syntax; original formatting
30 is disregarded. """
32 def __init__(self, tree, file = sys.stdout):
33 """Unparser(tree, file=sys.stdout) -> None.
34 Print the source for tree to file."""
35 self.f = file
36 self.future_imports = []
37 self._indent = 0
38 self.dispatch(tree)
39 print("", file=self.f)
40 self.f.flush()
42 def fill(self, text = ""):
43 "Indent a piece of text, according to the current indentation level"
44 self.f.write("\n"+" "*self._indent + text)
46 def write(self, text):
47 "Append a piece of text to the current line."
48 self.f.write(six.text_type(text))
50 def enter(self):
51 "Print ':', and increase the indentation."
52 self.write(":")
53 self._indent += 1
55 def leave(self):
56 "Decrease the indentation level."
57 self._indent -= 1
59 def dispatch(self, tree):
60 "Dispatcher function, dispatching tree type T to method _T."
61 if isinstance(tree, list):
62 for t in tree:
63 self.dispatch(t)
64 return
65 meth = getattr(self, "_"+tree.__class__.__name__)
66 meth(tree)
69 ############### Unparsing methods ######################
70 # There should be one method per concrete grammar type #
71 # Constructors should be grouped by sum type. Ideally, #
72 # this would follow the order in the grammar, but #
73 # currently doesn't. #
74 ########################################################
76 def _Module(self, tree):
77 for stmt in tree.body:
78 self.dispatch(stmt)
80 def _Interactive(self, tree):
81 for stmt in tree.body:
82 self.dispatch(stmt)
84 def _Expression(self, tree):
85 self.dispatch(tree.body)
87 # stmt
88 def _Expr(self, tree):
89 self.fill()
90 self.dispatch(tree.value)
92 def _NamedExpr(self, tree):
93 self.write("(")
94 self.dispatch(tree.target)
95 self.write(" := ")
96 self.dispatch(tree.value)
97 self.write(")")
99 def _Import(self, t):
100 self.fill("import ")
101 interleave(lambda: self.write(", "), self.dispatch, t.names)
103 def _ImportFrom(self, t):
104 # A from __future__ import may affect unparsing, so record it.
105 if t.module and t.module == '__future__':
106 self.future_imports.extend(n.name for n in t.names)
108 self.fill("from ")
109 self.write("." * t.level)
110 if t.module:
111 self.write(t.module)
112 self.write(" import ")
113 interleave(lambda: self.write(", "), self.dispatch, t.names)
115 def _Assign(self, t):
116 self.fill()
117 for target in t.targets:
118 self.dispatch(target)
119 self.write(" = ")
120 self.dispatch(t.value)
122 def _AugAssign(self, t):
123 self.fill()
124 self.dispatch(t.target)
125 self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
126 self.dispatch(t.value)
128 def _AnnAssign(self, t):
129 self.fill()
130 if not t.simple and isinstance(t.target, ast.Name):
131 self.write('(')
132 self.dispatch(t.target)
133 if not t.simple and isinstance(t.target, ast.Name):
134 self.write(')')
135 self.write(": ")
136 self.dispatch(t.annotation)
137 if t.value:
138 self.write(" = ")
139 self.dispatch(t.value)
141 def _Return(self, t):
142 self.fill("return")
143 if t.value:
144 self.write(" ")
145 self.dispatch(t.value)
147 def _Pass(self, t):
148 self.fill("pass")
150 def _Break(self, t):
151 self.fill("break")
153 def _Continue(self, t):
154 self.fill("continue")
156 def _Delete(self, t):
157 self.fill("del ")
158 interleave(lambda: self.write(", "), self.dispatch, t.targets)
160 def _Assert(self, t):
161 self.fill("assert ")
162 self.dispatch(t.test)
163 if t.msg:
164 self.write(", ")
165 self.dispatch(t.msg)
167 def _Exec(self, t):
168 self.fill("exec ")
169 self.dispatch(t.body)
170 if t.globals:
171 self.write(" in ")
172 self.dispatch(t.globals)
173 if t.locals:
174 self.write(", ")
175 self.dispatch(t.locals)
177 def _Print(self, t):
178 self.fill("print ")
179 do_comma = False
180 if t.dest:
181 self.write(">>")
182 self.dispatch(t.dest)
183 do_comma = True
184 for e in t.values:
185 if do_comma:self.write(", ")
186 else:do_comma=True
187 self.dispatch(e)
188 if not t.nl:
189 self.write(",")
191 def _Global(self, t):
192 self.fill("global ")
193 interleave(lambda: self.write(", "), self.write, t.names)
195 def _Nonlocal(self, t):
196 self.fill("nonlocal ")
197 interleave(lambda: self.write(", "), self.write, t.names)
199 def _Await(self, t):
200 self.write("(")
201 self.write("await")
202 if t.value:
203 self.write(" ")
204 self.dispatch(t.value)
205 self.write(")")
207 def _Yield(self, t):
208 self.write("(")
209 self.write("yield")
210 if t.value:
211 self.write(" ")
212 self.dispatch(t.value)
213 self.write(")")
215 def _YieldFrom(self, t):
216 self.write("(")
217 self.write("yield from")
218 if t.value:
219 self.write(" ")
220 self.dispatch(t.value)
221 self.write(")")
223 def _Raise(self, t):
224 self.fill("raise")
225 if six.PY3:
226 if not t.exc:
227 assert not t.cause
228 return
229 self.write(" ")
230 self.dispatch(t.exc)
231 if t.cause:
232 self.write(" from ")
233 self.dispatch(t.cause)
234 else:
235 self.write(" ")
236 if t.type:
237 self.dispatch(t.type)
238 if t.inst:
239 self.write(", ")
240 self.dispatch(t.inst)
241 if t.tback:
242 self.write(", ")
243 self.dispatch(t.tback)
245 def _Try(self, t):
246 self.fill("try")
247 self.enter()
248 self.dispatch(t.body)
249 self.leave()
250 for ex in t.handlers:
251 self.dispatch(ex)
252 if t.orelse:
253 self.fill("else")
254 self.enter()
255 self.dispatch(t.orelse)
256 self.leave()
257 if t.finalbody:
258 self.fill("finally")
259 self.enter()
260 self.dispatch(t.finalbody)
261 self.leave()
263 def _TryExcept(self, t):
264 self.fill("try")
265 self.enter()
266 self.dispatch(t.body)
267 self.leave()
269 for ex in t.handlers:
270 self.dispatch(ex)
271 if t.orelse:
272 self.fill("else")
273 self.enter()
274 self.dispatch(t.orelse)
275 self.leave()
277 def _TryFinally(self, t):
278 if len(t.body) == 1 and isinstance(t.body[0], ast.TryExcept):
279 # try-except-finally
280 self.dispatch(t.body)
281 else:
282 self.fill("try")
283 self.enter()
284 self.dispatch(t.body)
285 self.leave()
287 self.fill("finally")
288 self.enter()
289 self.dispatch(t.finalbody)
290 self.leave()
292 def _ExceptHandler(self, t):
293 self.fill("except")
294 if t.type:
295 self.write(" ")
296 self.dispatch(t.type)
297 if t.name:
298 self.write(" as ")
299 if six.PY3:
300 self.write(t.name)
301 else:
302 self.dispatch(t.name)
303 self.enter()
304 self.dispatch(t.body)
305 self.leave()
307 def _ClassDef(self, t):
308 self.write("\n")
309 for deco in t.decorator_list:
310 self.fill("@")
311 self.dispatch(deco)
312 self.fill("class "+t.name)
313 if six.PY3:
314 self.write("(")
315 comma = False
316 for e in t.bases:
317 if comma: self.write(", ")
318 else: comma = True
319 self.dispatch(e)
320 for e in t.keywords:
321 if comma: self.write(", ")
322 else: comma = True
323 self.dispatch(e)
324 if sys.version_info[:2] < (3, 5):
325 if t.starargs:
326 if comma: self.write(", ")
327 else: comma = True
328 self.write("*")
329 self.dispatch(t.starargs)
330 if t.kwargs:
331 if comma: self.write(", ")
332 else: comma = True
333 self.write("**")
334 self.dispatch(t.kwargs)
335 self.write(")")
336 elif t.bases:
337 self.write("(")
338 for a in t.bases:
339 self.dispatch(a)
340 self.write(", ")
341 self.write(")")
342 self.enter()
343 self.dispatch(t.body)
344 self.leave()
346 def _FunctionDef(self, t):
347 self.__FunctionDef_helper(t, "def")
349 def _AsyncFunctionDef(self, t):
350 self.__FunctionDef_helper(t, "async def")
352 def __FunctionDef_helper(self, t, fill_suffix):
353 self.write("\n")
354 for deco in t.decorator_list:
355 self.fill("@")
356 self.dispatch(deco)
357 def_str = fill_suffix+" "+t.name + "("
358 self.fill(def_str)
359 self.dispatch(t.args)
360 self.write(")")
361 if getattr(t, "returns", False):
362 self.write(" -> ")
363 self.dispatch(t.returns)
364 self.enter()
365 self.dispatch(t.body)
366 self.leave()
368 def _For(self, t):
369 self.__For_helper("for ", t)
371 def _AsyncFor(self, t):
372 self.__For_helper("async for ", t)
374 def __For_helper(self, fill, t):
375 self.fill(fill)
376 self.dispatch(t.target)
377 self.write(" in ")
378 self.dispatch(t.iter)
379 self.enter()
380 self.dispatch(t.body)
381 self.leave()
382 if t.orelse:
383 self.fill("else")
384 self.enter()
385 self.dispatch(t.orelse)
386 self.leave()
388 def _If(self, t):
389 self.fill("if ")
390 self.dispatch(t.test)
391 self.enter()
392 self.dispatch(t.body)
393 self.leave()
394 # collapse nested ifs into equivalent elifs.
395 while (t.orelse and len(t.orelse) == 1 and
396 isinstance(t.orelse[0], ast.If)):
397 t = t.orelse[0]
398 self.fill("elif ")
399 self.dispatch(t.test)
400 self.enter()
401 self.dispatch(t.body)
402 self.leave()
403 # final else
404 if t.orelse:
405 self.fill("else")
406 self.enter()
407 self.dispatch(t.orelse)
408 self.leave()
410 def _While(self, t):
411 self.fill("while ")
412 self.dispatch(t.test)
413 self.enter()
414 self.dispatch(t.body)
415 self.leave()
416 if t.orelse:
417 self.fill("else")
418 self.enter()
419 self.dispatch(t.orelse)
420 self.leave()
422 def _generic_With(self, t, async_=False):
423 self.fill("async with " if async_ else "with ")
424 if hasattr(t, 'items'):
425 interleave(lambda: self.write(", "), self.dispatch, t.items)
426 else:
427 self.dispatch(t.context_expr)
428 if t.optional_vars:
429 self.write(" as ")
430 self.dispatch(t.optional_vars)
431 self.enter()
432 self.dispatch(t.body)
433 self.leave()
435 def _With(self, t):
436 self._generic_With(t)
438 def _AsyncWith(self, t):
439 self._generic_With(t, async_=True)
441 # expr
442 def _Bytes(self, t):
443 self.write(repr(t.s))
445 def _Str(self, tree):
446 if six.PY3:
447 self.write(repr(tree.s))
448 else:
449 # if from __future__ import unicode_literals is in effect,
450 # then we want to output string literals using a 'b' prefix
451 # and unicode literals with no prefix.
452 if "unicode_literals" not in self.future_imports:
453 self.write(repr(tree.s))
454 elif isinstance(tree.s, str):
455 self.write("b" + repr(tree.s))
456 elif isinstance(tree.s, unicode):
457 self.write(repr(tree.s).lstrip("u"))
458 else:
459 assert False, "shouldn't get here"
461 def _JoinedStr(self, t):
462 # JoinedStr(expr* values)
463 self.write("f")
464 string = StringIO()
465 self._fstring_JoinedStr(t, string.write)
466 # Deviation from `unparse.py`: Try to find an unused quote.
467 # This change is made to handle _very_ complex f-strings.
468 v = string.getvalue()
469 if '\n' in v or '\r' in v:
470 quote_types = ["'''", '"""']
471 else:
472 quote_types = ["'", '"', '"""', "'''"]
473 for quote_type in quote_types:
474 if quote_type not in v:
475 v = "{quote_type}{v}{quote_type}".format(quote_type=quote_type, v=v)
476 break
477 else:
478 v = repr(v)
479 self.write(v)
481 def _FormattedValue(self, t):
482 # FormattedValue(expr value, int? conversion, expr? format_spec)
483 self.write("f")
484 string = StringIO()
485 self._fstring_JoinedStr(t, string.write)
486 self.write(repr(string.getvalue()))
488 def _fstring_JoinedStr(self, t, write):
489 for value in t.values:
490 meth = getattr(self, "_fstring_" + type(value).__name__)
491 meth(value, write)
493 def _fstring_Str(self, t, write):
494 value = t.s.replace("{", "{{").replace("}", "}}")
495 write(value)
497 def _fstring_Constant(self, t, write):
498 assert isinstance(t.value, str)
499 value = t.value.replace("{", "{{").replace("}", "}}")
500 write(value)
502 def _fstring_FormattedValue(self, t, write):
503 write("{")
504 expr = StringIO()
505 Unparser(t.value, expr)
506 expr = expr.getvalue().rstrip("\n")
507 if expr.startswith("{"):
508 write(" ") # Separate pair of opening brackets as "{ {"
509 write(expr)
510 if t.conversion != -1:
511 conversion = chr(t.conversion)
512 assert conversion in "sra"
513 write("!{conversion}".format(conversion=conversion))
514 if t.format_spec:
515 write(":")
516 meth = getattr(self, "_fstring_" + type(t.format_spec).__name__)
517 meth(t.format_spec, write)
518 write("}")
520 def _Name(self, t):
521 self.write(t.id)
523 def _NameConstant(self, t):
524 self.write(repr(t.value))
526 def _Repr(self, t):
527 self.write("`")
528 self.dispatch(t.value)
529 self.write("`")
531 def _write_constant(self, value):
532 if isinstance(value, (float, complex)):
533 # Substitute overflowing decimal literal for AST infinities.
534 self.write(repr(value).replace("inf", INFSTR))
535 else:
536 self.write(repr(value))
538 def _Constant(self, t):
539 value = t.value
540 if isinstance(value, tuple):
541 self.write("(")
542 if len(value) == 1:
543 self._write_constant(value[0])
544 self.write(",")
545 else:
546 interleave(lambda: self.write(", "), self._write_constant, value)
547 self.write(")")
548 elif value is Ellipsis: # instead of `...` for Py2 compatibility
549 self.write("...")
550 else:
551 if t.kind == "u":
552 self.write("u")
553 self._write_constant(t.value)
555 def _Num(self, t):
556 repr_n = repr(t.n)
557 if six.PY3:
558 self.write(repr_n.replace("inf", INFSTR))
559 else:
560 # Parenthesize negative numbers, to avoid turning (-1)**2 into -1**2.
561 if repr_n.startswith("-"):
562 self.write("(")
563 if "inf" in repr_n and repr_n.endswith("*j"):
564 repr_n = repr_n.replace("*j", "j")
565 # Substitute overflowing decimal literal for AST infinities.
566 self.write(repr_n.replace("inf", INFSTR))
567 if repr_n.startswith("-"):
568 self.write(")")
570 def _List(self, t):
571 self.write("[")
572 interleave(lambda: self.write(", "), self.dispatch, t.elts)
573 self.write("]")
575 def _ListComp(self, t):
576 self.write("[")
577 self.dispatch(t.elt)
578 for gen in t.generators:
579 self.dispatch(gen)
580 self.write("]")
582 def _GeneratorExp(self, t):
583 self.write("(")
584 self.dispatch(t.elt)
585 for gen in t.generators:
586 self.dispatch(gen)
587 self.write(")")
589 def _SetComp(self, t):
590 self.write("{")
591 self.dispatch(t.elt)
592 for gen in t.generators:
593 self.dispatch(gen)
594 self.write("}")
596 def _DictComp(self, t):
597 self.write("{")
598 self.dispatch(t.key)
599 self.write(": ")
600 self.dispatch(t.value)
601 for gen in t.generators:
602 self.dispatch(gen)
603 self.write("}")
605 def _comprehension(self, t):
606 if getattr(t, 'is_async', False):
607 self.write(" async for ")
608 else:
609 self.write(" for ")
610 self.dispatch(t.target)
611 self.write(" in ")
612 self.dispatch(t.iter)
613 for if_clause in t.ifs:
614 self.write(" if ")
615 self.dispatch(if_clause)
617 def _IfExp(self, t):
618 self.write("(")
619 self.dispatch(t.body)
620 self.write(" if ")
621 self.dispatch(t.test)
622 self.write(" else ")
623 self.dispatch(t.orelse)
624 self.write(")")
626 def _Set(self, t):
627 assert(t.elts) # should be at least one element
628 self.write("{")
629 interleave(lambda: self.write(", "), self.dispatch, t.elts)
630 self.write("}")
632 def _Dict(self, t):
633 self.write("{")
634 def write_key_value_pair(k, v):
635 self.dispatch(k)
636 self.write(": ")
637 self.dispatch(v)
639 def write_item(item):
640 k, v = item
641 if k is None:
642 # for dictionary unpacking operator in dicts {**{'y': 2}}
643 # see PEP 448 for details
644 self.write("**")
645 self.dispatch(v)
646 else:
647 write_key_value_pair(k, v)
648 interleave(lambda: self.write(", "), write_item, zip(t.keys, t.values))
649 self.write("}")
651 def _Tuple(self, t):
652 self.write("(")
653 if len(t.elts) == 1:
654 elt = t.elts[0]
655 self.dispatch(elt)
656 self.write(",")
657 else:
658 interleave(lambda: self.write(", "), self.dispatch, t.elts)
659 self.write(")")
661 unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}
662 def _UnaryOp(self, t):
663 self.write("(")
664 self.write(self.unop[t.op.__class__.__name__])
665 self.write(" ")
666 if six.PY2 and isinstance(t.op, ast.USub) and isinstance(t.operand, ast.Num):
667 # If we're applying unary minus to a number, parenthesize the number.
668 # This is necessary: -2147483648 is different from -(2147483648) on
669 # a 32-bit machine (the first is an int, the second a long), and
670 # -7j is different from -(7j). (The first has real part 0.0, the second
671 # has real part -0.0.)
672 self.write("(")
673 self.dispatch(t.operand)
674 self.write(")")
675 else:
676 self.dispatch(t.operand)
677 self.write(")")
679 binop = { "Add":"+", "Sub":"-", "Mult":"*", "MatMult":"@", "Div":"/", "Mod":"%",
680 "LShift":"<<", "RShift":">>", "BitOr":"|", "BitXor":"^", "BitAnd":"&",
681 "FloorDiv":"//", "Pow": "**"}
682 def _BinOp(self, t):
683 self.write("(")
684 self.dispatch(t.left)
685 self.write(" " + self.binop[t.op.__class__.__name__] + " ")
686 self.dispatch(t.right)
687 self.write(")")
689 cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=",
690 "Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"}
691 def _Compare(self, t):
692 self.write("(")
693 self.dispatch(t.left)
694 for o, e in zip(t.ops, t.comparators):
695 self.write(" " + self.cmpops[o.__class__.__name__] + " ")
696 self.dispatch(e)
697 self.write(")")
699 boolops = {ast.And: 'and', ast.Or: 'or'}
700 def _BoolOp(self, t):
701 self.write("(")
702 s = " %s " % self.boolops[t.op.__class__]
703 interleave(lambda: self.write(s), self.dispatch, t.values)
704 self.write(")")
706 def _Attribute(self,t):
707 self.dispatch(t.value)
708 # Special case: 3.__abs__() is a syntax error, so if t.value
709 # is an integer literal then we need to either parenthesize
710 # it or add an extra space to get 3 .__abs__().
711 if isinstance(t.value, getattr(ast, 'Constant', getattr(ast, 'Num', None))) and isinstance(t.value.n, int):
712 self.write(" ")
713 self.write(".")
714 self.write(t.attr)
716 def _Call(self, t):
717 self.dispatch(t.func)
718 self.write("(")
719 comma = False
720 for e in t.args:
721 if comma: self.write(", ")
722 else: comma = True
723 self.dispatch(e)
724 for e in t.keywords:
725 if comma: self.write(", ")
726 else: comma = True
727 self.dispatch(e)
728 if sys.version_info[:2] < (3, 5):
729 if t.starargs:
730 if comma: self.write(", ")
731 else: comma = True
732 self.write("*")
733 self.dispatch(t.starargs)
734 if t.kwargs:
735 if comma: self.write(", ")
736 else: comma = True
737 self.write("**")
738 self.dispatch(t.kwargs)
739 self.write(")")
741 def _Subscript(self, t):
742 self.dispatch(t.value)
743 self.write("[")
744 self.dispatch(t.slice)
745 self.write("]")
747 def _Starred(self, t):
748 self.write("*")
749 self.dispatch(t.value)
751 # slice
752 def _Ellipsis(self, t):
753 self.write("...")
755 def _Index(self, t):
756 self.dispatch(t.value)
758 def _Slice(self, t):
759 if t.lower:
760 self.dispatch(t.lower)
761 self.write(":")
762 if t.upper:
763 self.dispatch(t.upper)
764 if t.step:
765 self.write(":")
766 self.dispatch(t.step)
768 def _ExtSlice(self, t):
769 interleave(lambda: self.write(', '), self.dispatch, t.dims)
771 # argument
772 def _arg(self, t):
773 self.write(t.arg)
774 if t.annotation:
775 self.write(": ")
776 self.dispatch(t.annotation)
778 # others
779 def _arguments(self, t):
780 first = True
781 # normal arguments
782 all_args = getattr(t, 'posonlyargs', []) + t.args
783 defaults = [None] * (len(all_args) - len(t.defaults)) + t.defaults
784 for index, elements in enumerate(zip(all_args, defaults), 1):
785 a, d = elements
786 if first:first = False
787 else: self.write(", ")
788 self.dispatch(a)
789 if d:
790 self.write("=")
791 self.dispatch(d)
792 if index == len(getattr(t, 'posonlyargs', ())):
793 self.write(", /")
795 # varargs, or bare '*' if no varargs but keyword-only arguments present
796 if t.vararg or getattr(t, "kwonlyargs", False):
797 if first:first = False
798 else: self.write(", ")
799 self.write("*")
800 if t.vararg:
801 if hasattr(t.vararg, 'arg'):
802 self.write(t.vararg.arg)
803 if t.vararg.annotation:
804 self.write(": ")
805 self.dispatch(t.vararg.annotation)
806 else:
807 self.write(t.vararg)
808 if getattr(t, 'varargannotation', None):
809 self.write(": ")
810 self.dispatch(t.varargannotation)
812 # keyword-only arguments
813 if getattr(t, "kwonlyargs", False):
814 for a, d in zip(t.kwonlyargs, t.kw_defaults):
815 if first:first = False
816 else: self.write(", ")
817 self.dispatch(a),
818 if d:
819 self.write("=")
820 self.dispatch(d)
822 # kwargs
823 if t.kwarg:
824 if first:first = False
825 else: self.write(", ")
826 if hasattr(t.kwarg, 'arg'):
827 self.write("**"+t.kwarg.arg)
828 if t.kwarg.annotation:
829 self.write(": ")
830 self.dispatch(t.kwarg.annotation)
831 else:
832 self.write("**"+t.kwarg)
833 if getattr(t, 'kwargannotation', None):
834 self.write(": ")
835 self.dispatch(t.kwargannotation)
837 def _keyword(self, t):
838 if t.arg is None:
839 # starting from Python 3.5 this denotes a kwargs part of the invocation
840 self.write("**")
841 else:
842 self.write(t.arg)
843 self.write("=")
844 self.dispatch(t.value)
846 def _Lambda(self, t):
847 self.write("(")
848 self.write("lambda ")
849 self.dispatch(t.args)
850 self.write(": ")
851 self.dispatch(t.body)
852 self.write(")")
854 def _alias(self, t):
855 self.write(t.name)
856 if t.asname:
857 self.write(" as "+t.asname)
859 def _withitem(self, t):
860 self.dispatch(t.context_expr)
861 if t.optional_vars:
862 self.write(" as ")
863 self.dispatch(t.optional_vars)
865def roundtrip(filename, output=sys.stdout):
866 if six.PY3:
867 with open(filename, "rb") as pyfile:
868 encoding = tokenize.detect_encoding(pyfile.readline)[0]
869 with open(filename, "r", encoding=encoding) as pyfile:
870 source = pyfile.read()
871 else:
872 with open(filename, "r") as pyfile:
873 source = pyfile.read()
874 tree = compile(source, filename, "exec", ast.PyCF_ONLY_AST, dont_inherit=True)
875 Unparser(tree, output)
879def testdir(a):
880 try:
881 names = [n for n in os.listdir(a) if n.endswith('.py')]
882 except OSError:
883 print("Directory not readable: %s" % a, file=sys.stderr)
884 else:
885 for n in names:
886 fullname = os.path.join(a, n)
887 if os.path.isfile(fullname):
888 output = StringIO()
889 print('Testing %s' % fullname)
890 try:
891 roundtrip(fullname, output)
892 except Exception as e:
893 print(' Failed to compile, exception is %s' % repr(e))
894 elif os.path.isdir(fullname):
895 testdir(fullname)
897def main(args):
898 if args[0] == '--testdir':
899 for a in args[1:]:
900 testdir(a)
901 else:
902 for a in args:
903 roundtrip(a)
905if __name__=='__main__':
906 main(sys.argv[1:])