unparser: refactor delimiting with context managers in ast.unparse
Backport of 4b3b1226e8
This commit is contained in:
parent
5847eb1e65
commit
afb358313a
1 changed files with 177 additions and 190 deletions
107
lib/spack/external/spack_astunparse/unparser.py
vendored
107
lib/spack/external/spack_astunparse/unparser.py
vendored
|
@ -13,6 +13,7 @@
|
|||
|
||||
|
||||
# TODO: if we require Python 3.7, use its `nullcontext()`
|
||||
@contextmanager
|
||||
def nullcontext():
|
||||
yield
|
||||
|
||||
|
@ -101,6 +102,21 @@ def __exit__(self, exc_type, exc_value, traceback):
|
|||
def block(self):
|
||||
return self._Block(self)
|
||||
|
||||
@contextmanager
|
||||
def delimit(self, start, end):
|
||||
"""A context manager for preparing the source for expressions. It adds
|
||||
*start* to the buffer and enters, after exit it adds *end*."""
|
||||
|
||||
self.write(start)
|
||||
yield
|
||||
self.write(end)
|
||||
|
||||
def delimit_if(self, start, end, condition):
|
||||
if condition:
|
||||
return self.delimit(start, end)
|
||||
else:
|
||||
return nullcontext()
|
||||
|
||||
def dispatch(self, tree):
|
||||
"Dispatcher function, dispatching tree type T to method _T."
|
||||
if isinstance(tree, list):
|
||||
|
@ -135,11 +151,10 @@ def _Expr(self, tree):
|
|||
self.dispatch(tree.value)
|
||||
|
||||
def _NamedExpr(self, tree):
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
self.dispatch(tree.target)
|
||||
self.write(" := ")
|
||||
self.dispatch(tree.value)
|
||||
self.write(")")
|
||||
|
||||
def _Import(self, t):
|
||||
self.fill("import ")
|
||||
|
@ -172,11 +187,9 @@ def _AugAssign(self, t):
|
|||
|
||||
def _AnnAssign(self, t):
|
||||
self.fill()
|
||||
if not t.simple and isinstance(t.target, ast.Name):
|
||||
self.write('(')
|
||||
with self.delimit_if(
|
||||
"(", ")", not node.simple and isinstance(t.target, ast.Name)):
|
||||
self.dispatch(t.target)
|
||||
if not t.simple and isinstance(t.target, ast.Name):
|
||||
self.write(')')
|
||||
self.write(": ")
|
||||
self.dispatch(t.annotation)
|
||||
if t.value:
|
||||
|
@ -250,28 +263,25 @@ def _Nonlocal(self, t):
|
|||
interleave(lambda: self.write(", "), self.write, t.names)
|
||||
|
||||
def _Await(self, t):
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
self.write("await")
|
||||
if t.value:
|
||||
self.write(" ")
|
||||
self.dispatch(t.value)
|
||||
self.write(")")
|
||||
|
||||
def _Yield(self, t):
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
self.write("yield")
|
||||
if t.value:
|
||||
self.write(" ")
|
||||
self.dispatch(t.value)
|
||||
self.write(")")
|
||||
|
||||
def _YieldFrom(self, t):
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
self.write("yield from")
|
||||
if t.value:
|
||||
self.write(" ")
|
||||
self.dispatch(t.value)
|
||||
self.write(")")
|
||||
|
||||
def _Raise(self, t):
|
||||
self.fill("raise")
|
||||
|
@ -356,7 +366,7 @@ def _ClassDef(self, t):
|
|||
self.dispatch(deco)
|
||||
self.fill("class "+t.name)
|
||||
if six.PY3:
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
comma = False
|
||||
for e in t.bases:
|
||||
if comma: self.write(", ")
|
||||
|
@ -377,14 +387,12 @@ def _ClassDef(self, t):
|
|||
else: comma = True
|
||||
self.write("**")
|
||||
self.dispatch(t.kwargs)
|
||||
self.write(")")
|
||||
elif t.bases:
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
for a in t.bases[:-1]:
|
||||
self.dispatch(a)
|
||||
self.write(", ")
|
||||
self.dispatch(t.bases[-1])
|
||||
self.write(")")
|
||||
with self.block():
|
||||
self.dispatch(t.body)
|
||||
|
||||
|
@ -399,10 +407,10 @@ def __FunctionDef_helper(self, t, fill_suffix):
|
|||
for deco in t.decorator_list:
|
||||
self.fill("@")
|
||||
self.dispatch(deco)
|
||||
def_str = fill_suffix+" "+t.name + "("
|
||||
def_str = fill_suffix + " " + t.name
|
||||
self.fill(def_str)
|
||||
with self.delimit("(", ")"):
|
||||
self.dispatch(t.args)
|
||||
self.write(")")
|
||||
if getattr(t, "returns", False):
|
||||
self.write(" -> ")
|
||||
self.dispatch(t.returns)
|
||||
|
@ -574,13 +582,12 @@ def _write_constant(self, value):
|
|||
def _Constant(self, t):
|
||||
value = t.value
|
||||
if isinstance(value, tuple):
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
if len(value) == 1:
|
||||
self._write_constant(value[0])
|
||||
self.write(",")
|
||||
else:
|
||||
interleave(lambda: self.write(", "), self._write_constant, value)
|
||||
self.write(")")
|
||||
elif value is Ellipsis: # instead of `...` for Py2 compatibility
|
||||
self.write("...")
|
||||
else:
|
||||
|
@ -594,49 +601,41 @@ def _Num(self, t):
|
|||
self.write(repr_n.replace("inf", INFSTR))
|
||||
else:
|
||||
# Parenthesize negative numbers, to avoid turning (-1)**2 into -1**2.
|
||||
if repr_n.startswith("-"):
|
||||
self.write("(")
|
||||
with self.delimit_if("(", ")", repr_n.startswith("-")):
|
||||
if "inf" in repr_n and repr_n.endswith("*j"):
|
||||
repr_n = repr_n.replace("*j", "j")
|
||||
# Substitute overflowing decimal literal for AST infinities.
|
||||
self.write(repr_n.replace("inf", INFSTR))
|
||||
if repr_n.startswith("-"):
|
||||
self.write(")")
|
||||
|
||||
def _List(self, t):
|
||||
self.write("[")
|
||||
with self.delimit("[", "]"):
|
||||
interleave(lambda: self.write(", "), self.dispatch, t.elts)
|
||||
self.write("]")
|
||||
|
||||
def _ListComp(self, t):
|
||||
self.write("[")
|
||||
with self.delimit("[", "]"):
|
||||
self.dispatch(t.elt)
|
||||
for gen in t.generators:
|
||||
self.dispatch(gen)
|
||||
self.write("]")
|
||||
|
||||
def _GeneratorExp(self, t):
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
self.dispatch(t.elt)
|
||||
for gen in t.generators:
|
||||
self.dispatch(gen)
|
||||
self.write(")")
|
||||
|
||||
def _SetComp(self, t):
|
||||
self.write("{")
|
||||
with self.delimit("{", "}"):
|
||||
self.dispatch(t.elt)
|
||||
for gen in t.generators:
|
||||
self.dispatch(gen)
|
||||
self.write("}")
|
||||
|
||||
def _DictComp(self, t):
|
||||
self.write("{")
|
||||
with self.delimit("{", "}"):
|
||||
self.dispatch(t.key)
|
||||
self.write(": ")
|
||||
self.dispatch(t.value)
|
||||
for gen in t.generators:
|
||||
self.dispatch(gen)
|
||||
self.write("}")
|
||||
|
||||
def _comprehension(self, t):
|
||||
if getattr(t, 'is_async', False):
|
||||
|
@ -651,22 +650,19 @@ def _comprehension(self, t):
|
|||
self.dispatch(if_clause)
|
||||
|
||||
def _IfExp(self, t):
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
self.dispatch(t.body)
|
||||
self.write(" if ")
|
||||
self.dispatch(t.test)
|
||||
self.write(" else ")
|
||||
self.dispatch(t.orelse)
|
||||
self.write(")")
|
||||
|
||||
def _Set(self, t):
|
||||
assert(t.elts) # should be at least one element
|
||||
self.write("{")
|
||||
with self.delimit("{", "}"):
|
||||
interleave(lambda: self.write(", "), self.dispatch, t.elts)
|
||||
self.write("}")
|
||||
|
||||
def _Dict(self, t):
|
||||
self.write("{")
|
||||
def write_key_value_pair(k, v):
|
||||
self.dispatch(k)
|
||||
self.write(": ")
|
||||
|
@ -681,22 +677,22 @@ def write_item(item):
|
|||
self.dispatch(v)
|
||||
else:
|
||||
write_key_value_pair(k, v)
|
||||
|
||||
with self.delimit("{", "}"):
|
||||
interleave(lambda: self.write(", "), write_item, zip(t.keys, t.values))
|
||||
self.write("}")
|
||||
|
||||
def _Tuple(self, t):
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
if len(t.elts) == 1:
|
||||
elt = t.elts[0]
|
||||
self.dispatch(elt)
|
||||
self.write(",")
|
||||
else:
|
||||
interleave(lambda: self.write(", "), self.dispatch, t.elts)
|
||||
self.write(")")
|
||||
|
||||
unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}
|
||||
def _UnaryOp(self, t):
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
self.write(self.unop[t.op.__class__.__name__])
|
||||
if not self._py_ver_consistent:
|
||||
self.write(" ")
|
||||
|
@ -706,39 +702,34 @@ def _UnaryOp(self, t):
|
|||
# a 32-bit machine (the first is an int, the second a long), and
|
||||
# -7j is different from -(7j). (The first has real part 0.0, the second
|
||||
# has real part -0.0.)
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
self.dispatch(t.operand)
|
||||
self.write(")")
|
||||
else:
|
||||
self.dispatch(t.operand)
|
||||
self.write(")")
|
||||
|
||||
binop = { "Add":"+", "Sub":"-", "Mult":"*", "MatMult":"@", "Div":"/", "Mod":"%",
|
||||
"LShift":"<<", "RShift":">>", "BitOr":"|", "BitXor":"^", "BitAnd":"&",
|
||||
"FloorDiv":"//", "Pow": "**"}
|
||||
def _BinOp(self, t):
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
self.dispatch(t.left)
|
||||
self.write(" " + self.binop[t.op.__class__.__name__] + " ")
|
||||
self.dispatch(t.right)
|
||||
self.write(")")
|
||||
|
||||
cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=",
|
||||
"Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"}
|
||||
def _Compare(self, t):
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
self.dispatch(t.left)
|
||||
for o, e in zip(t.ops, t.comparators):
|
||||
self.write(" " + self.cmpops[o.__class__.__name__] + " ")
|
||||
self.dispatch(e)
|
||||
self.write(")")
|
||||
|
||||
boolops = {ast.And: 'and', ast.Or: 'or'}
|
||||
def _BoolOp(self, t):
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
s = " %s " % self.boolops[t.op.__class__]
|
||||
interleave(lambda: self.write(s), self.dispatch, t.values)
|
||||
self.write(")")
|
||||
|
||||
def _Attribute(self,t):
|
||||
self.dispatch(t.value)
|
||||
|
@ -752,10 +743,10 @@ def _Attribute(self,t):
|
|||
|
||||
def _Call(self, t):
|
||||
self.dispatch(t.func)
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
comma = False
|
||||
|
||||
# move starred arguments last in Python 3.5+, for consistency w/earlier versions
|
||||
# starred arguments last in Python 3.5+, for consistency w/earlier versions
|
||||
star_and_kwargs = []
|
||||
move_stars_last = sys.version_info[:2] >= (3, 5)
|
||||
|
||||
|
@ -794,13 +785,10 @@ def _Call(self, t):
|
|||
self.write("**")
|
||||
self.dispatch(t.kwargs)
|
||||
|
||||
self.write(")")
|
||||
|
||||
def _Subscript(self, t):
|
||||
self.dispatch(t.value)
|
||||
self.write("[")
|
||||
with self.delimit("[", "]"):
|
||||
self.dispatch(t.slice)
|
||||
self.write("]")
|
||||
|
||||
def _Starred(self, t):
|
||||
self.write("*")
|
||||
|
@ -902,12 +890,11 @@ def _keyword(self, t):
|
|||
self.dispatch(t.value)
|
||||
|
||||
def _Lambda(self, t):
|
||||
self.write("(")
|
||||
with self.delimit("(", ")"):
|
||||
self.write("lambda ")
|
||||
self.dispatch(t.args)
|
||||
self.write(": ")
|
||||
self.dispatch(t.body)
|
||||
self.write(")")
|
||||
|
||||
def _alias(self, t):
|
||||
self.write(t.name)
|
||||
|
|
Loading…
Reference in a new issue