Skip to content

Commit 4b4db75

Browse files
committed
1 parent 650aaf2 commit 4b4db75

File tree

2 files changed

+40
-6
lines changed

2 files changed

+40
-6
lines changed

lib/astunparse/unparser.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ def dispatch(self, tree, from_statement=False):
6464
for t in tree:
6565
self.dispatch(t)
6666
return
67-
tree.from_statement = from_statement
67+
if tree is not None:
68+
tree.from_statement = from_statement
6869
meth = getattr(self, "_" + tree.__class__.__name__)
6970
meth(tree)
7071

@@ -460,7 +461,7 @@ def _Str(self, tree):
460461

461462
format_conversions = {97: 'a', 114: 'r', 115: 's'}
462463

463-
def _FormattedValue(self, t):
464+
def _generic_FormattedValue(self, t):
464465
# FormattedValue(expr value, int? conversion, expr? format_spec)
465466
self.write("{")
466467
self.dispatch(t.value)
@@ -472,16 +473,30 @@ def _FormattedValue(self, t):
472473
self.write(":")
473474
if isinstance(t.format_spec, ast.Str):
474475
self.write(t.format_spec.s)
476+
elif isinstance(t.format_spec, ast.JoinedStr):
477+
# 3.6.1+ joined string
478+
for value in t.format_spec.values:
479+
if isinstance(value, ast.Str):
480+
self.write(value.s)
481+
else:
482+
self.dispatch(value)
475483
else:
476484
self.dispatch(t.format_spec)
477485
self.write("}")
478486

487+
def _FormattedValue(self, t):
488+
self.write("f'''")
489+
self._generic_FormattedValue(t)
490+
self.write("'''")
491+
479492
def _JoinedStr(self, t):
480493
# JoinedStr(expr* values)
481494
self.write("f'''")
482495
for value in t.values:
483496
if isinstance(value, ast.Str):
484497
self.write(value.s)
498+
elif isinstance(value, ast.FormattedValue):
499+
self._generic_FormattedValue(value)
485500
else:
486501
self.dispatch(value)
487502
self.write("'''")
@@ -578,9 +593,13 @@ def _Dict(self, t):
578593

579594
def write_pair(pair):
580595
(k, v) = pair
581-
self.dispatch(k)
582-
self.write(": ")
583-
self.dispatch(v)
596+
if k is None:
597+
self.write("**")
598+
self.dispatch(v)
599+
else:
600+
self.dispatch(k)
601+
self.write(": ")
602+
self.dispatch(v)
584603
self.write(",")
585604
self._indent += 1
586605
self.fill("")

tests/common.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
else:
1313
from lib2to3.pgen2 import tokenize
1414

15+
1516
def read_pyfile(filename):
1617
"""Read and return the contents of a Python source file (as a
1718
string), taking into account the file encoding."""
@@ -25,6 +26,7 @@ def read_pyfile(filename):
2526
source = pyfile.read()
2627
return source
2728

29+
2830
code_parseable_in_all_parser_modes = """\
2931
(a + b + c) * (d + e + f)
3032
"""
@@ -162,6 +164,7 @@ async def f():
162164
suite1
163165
"""
164166

167+
165168
class AstunparseCommonTestCase:
166169
# Tests for specific bugs found in earlier versions of unparse
167170

@@ -222,7 +225,7 @@ def test_huge_float(self):
222225

223226
@unittest.skipUnless(six.PY2, "Only works for Python 2")
224227
def test_min_int27(self):
225-
self.check_roundtrip(str(-sys.maxint-1))
228+
self.check_roundtrip(str(-sys.maxint - 1))
226229
self.check_roundtrip("-(%s)" % (sys.maxint + 1))
227230

228231
@unittest.skipUnless(six.PY3, "Only works for Python 3")
@@ -288,6 +291,18 @@ def test_raise_from(self):
288291
def test_bytes(self):
289292
self.check_roundtrip("b'123'")
290293

294+
@unittest.skipIf(sys.version_info < (3, 6), "Not supported < 3.6")
295+
def test_formatted_value(self):
296+
self.check_roundtrip('f"{value}"')
297+
self.check_roundtrip('f"{value!s}"')
298+
self.check_roundtrip('f"{value:4}"')
299+
self.check_roundtrip('f"{value!s:4}"')
300+
301+
@unittest.skipIf(sys.version_info < (3, 6), "Not supported < 3.6")
302+
def test_dict_with_unpacking(self):
303+
self.check_roundtrip("{**x}")
304+
self.check_roundtrip("{a: b, **x}")
305+
291306
@unittest.skipIf(sys.version_info < (3, 6), "Not supported < 3.6")
292307
def test_joined_str(self):
293308
self.check_roundtrip('f"{key}={value!s}"')

0 commit comments

Comments
 (0)