From 485c078f4f37d5737ea624021acd8937a7145d09 Mon Sep 17 00:00:00 2001 From: David Bieber Date: Thu, 6 Sep 2018 00:10:10 -0700 Subject: [PATCH] Allow user to specify version_info rather than assuming AST version matches the current Python version. This is useful if the user is using e.g. gast to get a different AST version from the Python version they are using. --- lib/astunparse/unparser.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/astunparse/unparser.py b/lib/astunparse/unparser.py index 767412c..e4df04b 100644 --- a/lib/astunparse/unparser.py +++ b/lib/astunparse/unparser.py @@ -24,14 +24,15 @@ def interleave(inter, f, seq): inter() f(x) -class Unparser: +class Unparser(object): """Methods in this class recursively traverse an AST and output source code for the abstract syntax; original formatting is disregarded. """ - def __init__(self, tree, file=sys.stdout): + def __init__(self, tree, file=sys.stdout, version_info=None): """Unparser(tree, file=sys.stdout) -> None. Print the source for tree to file.""" + self.version_info = version_info or sys.version_info self.f = file self.future_imports = [] self._indent = 0 @@ -207,7 +208,7 @@ def _YieldFrom(self, t): def _Raise(self, t): self.fill("raise") - if six.PY3: + if self.version_info[0] == 3: if not t.exc: assert not t.cause return @@ -281,7 +282,7 @@ def _ExceptHandler(self, t): self.dispatch(t.type) if t.name: self.write(" as ") - if six.PY3: + if isinstance(t.name, six.string_types): self.write(t.name) else: self.dispatch(t.name) @@ -295,7 +296,7 @@ def _ClassDef(self, t): self.fill("@") self.dispatch(deco) self.fill("class "+t.name) - if six.PY3: + if self.version_info[0] == 3: self.write("(") comma = False for e in t.bases: @@ -306,7 +307,7 @@ def _ClassDef(self, t): if comma: self.write(", ") else: comma = True self.dispatch(e) - if sys.version_info[:2] < (3, 5): + if self.version_info[:2] < (3, 5): if t.starargs: if comma: self.write(", ") else: comma = True @@ -427,7 +428,7 @@ def _Bytes(self, t): self.write(repr(t.s)) def _Str(self, tree): - if six.PY3: + if self.version_info[0] == 3: self.write(repr(tree.s)) else: # if from __future__ import unicode_literals is in effect, @@ -501,7 +502,7 @@ def _Repr(self, t): def _Num(self, t): repr_n = repr(t.n) - if six.PY3: + if self.version_info[0] == 3: self.write(repr_n.replace("inf", INFSTR)) else: # Parenthesize negative numbers, to avoid turning (-1)**2 into -1**2. @@ -608,7 +609,7 @@ def _UnaryOp(self, t): self.write("(") self.write(self.unop[t.op.__class__.__name__]) self.write(" ") - if six.PY2 and isinstance(t.op, ast.USub) and isinstance(t.operand, ast.Num): + if self.version_info[0] == 2 and isinstance(t.op, ast.USub) and isinstance(t.operand, ast.Num): # If we're applying unary minus to a number, parenthesize the number. # This is necessary: -2147483648 is different from -(2147483648) on # a 32-bit machine (the first is an int, the second a long), and @@ -671,7 +672,7 @@ def _Call(self, t): if comma: self.write(", ") else: comma = True self.dispatch(e) - if sys.version_info[:2] < (3, 5): + if self.version_info[:2] < (3, 5): if t.starargs: if comma: self.write(", ") else: comma = True @@ -770,6 +771,11 @@ def _arguments(self, t): if t.kwarg.annotation: self.write(": ") self.dispatch(t.kwarg.annotation) + elif hasattr(t.kwarg, 'id'): + self.write("**"+t.kwarg.id) + if t.kwarg.annotation: + self.write(": ") + self.dispatch(t.kwarg.annotation) else: self.write("**"+t.kwarg) if getattr(t, 'kwargannotation', None):