You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

906 lines
27 KiB

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