More fstring bugs -- nested fstring grammar rules

This commit is contained in:
rocky
2020-01-13 08:04:53 -05:00
parent de282af05d
commit 54f4806021
5 changed files with 35 additions and 21 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -69,17 +69,8 @@ fields = ['a', 'b', 'c']
assert _repr_fn(fields) == ['return xx + f"(a={self.a!r}, b={self.b!r}, c={self.c!r})"']
# From Python 3.7 test_fstring. Why this kind of thing matter seems a bit
# academic, but decompile an equivalent thing. For compatiblity with older
# Python we'll use "%" instead of a format string
def f():
f'''Not a docstring'''
def g():
'''Not a docstring''' \
f''
assert f.__doc__ is None
assert g.__doc__ is None
#################################
# From Python 3.7 test_fstring.py
x = 5
assert f'{(lambda y:x*y)("8")!r}' == "'88888'"
@@ -92,3 +83,19 @@ except SyntaxError:
pass
else:
assert False, "f'{lambda x:x}' should be a syntax error"
(x, y, width) = ("foo", 2, 10)
assert f'x={x*y:{width}}' == 'x=foofoo '
# Why the fact that the distinction of docstring versus stmt is a
# string expression is important academic, but we will decompile an
# equivalent thing. For compatiblity with older Python we'll use "%"
# instead of a format string
def f():
f'''Not a docstring'''
def g():
'''Not a docstring''' \
f''
assert f.__doc__ is None
assert g.__doc__ is None

View File

@@ -450,11 +450,18 @@ def customize_for_version36(self, version):
def n_formatted_value1(node):
expr = node[0]
assert expr == "expr"
self.in_format_string = True
value = self.traverse(expr, indent="")
self.in_format_string = False
conversion = f_conversion(node)
f_str = "f%s" % escape_string("{%s%s}" % (value, conversion))
if (self.in_format_string):
value = self.traverse(expr, indent="")
es = escape_string("{%s%s}" % (value, conversion))
f_str = "%s" % es
else:
self.in_format_string = True
value = self.traverse(expr, indent="")
self.in_format_string = False
es = escape_string("{%s%s}" % (value, conversion))
f_str = "f%s" % es
self.write(f_str)
self.prune()
@@ -468,7 +475,6 @@ def customize_for_version36(self, version):
assert expr == "expr"
self.in_format_string = True
value = self.traverse(expr, indent="")
self.in_format_string = False
format_value_attr = node[-1]
assert format_value_attr == "FORMAT_VALUE_ATTR"
attr = format_value_attr.attr
@@ -483,6 +489,7 @@ def customize_for_version36(self, version):
else:
conversion = FSTRING_CONVERSION_MAP.get(attr, "")
self.in_format_string = False
f_str = "f%s" % escape_string("{%s%s}" % (value, conversion))
self.write(f_str)
@@ -495,14 +502,14 @@ def customize_for_version36(self, version):
p = self.prec
self.prec = 100
result = ''
result = ""
for expr in node[:-1]:
assert expr == 'expr'
value = self.traverse(expr, indent='')
assert expr == "expr"
value = self.traverse(expr, indent="")
if expr[0].kind.startswith('formatted_value'):
# remove leading 'f'
assert value.startswith('f')
value = value[1:]
if value.startswith("f"):
value = value[1:]
pass
else:
# {{ and }} in Python source-code format strings mean