You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-04 01:09:52 +08:00
More fstring bugs -- nested fstring grammar rules
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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})"']
|
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
|
# From Python 3.7 test_fstring.py
|
||||||
# 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
|
|
||||||
|
|
||||||
x = 5
|
x = 5
|
||||||
assert f'{(lambda y:x*y)("8")!r}' == "'88888'"
|
assert f'{(lambda y:x*y)("8")!r}' == "'88888'"
|
||||||
@@ -92,3 +83,19 @@ except SyntaxError:
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
assert False, "f'{lambda x:x}' should be a syntax error"
|
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
|
||||||
|
@@ -450,11 +450,18 @@ def customize_for_version36(self, version):
|
|||||||
def n_formatted_value1(node):
|
def n_formatted_value1(node):
|
||||||
expr = node[0]
|
expr = node[0]
|
||||||
assert expr == "expr"
|
assert expr == "expr"
|
||||||
self.in_format_string = True
|
|
||||||
value = self.traverse(expr, indent="")
|
|
||||||
self.in_format_string = False
|
|
||||||
conversion = f_conversion(node)
|
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.write(f_str)
|
||||||
self.prune()
|
self.prune()
|
||||||
|
|
||||||
@@ -468,7 +475,6 @@ def customize_for_version36(self, version):
|
|||||||
assert expr == "expr"
|
assert expr == "expr"
|
||||||
self.in_format_string = True
|
self.in_format_string = True
|
||||||
value = self.traverse(expr, indent="")
|
value = self.traverse(expr, indent="")
|
||||||
self.in_format_string = False
|
|
||||||
format_value_attr = node[-1]
|
format_value_attr = node[-1]
|
||||||
assert format_value_attr == "FORMAT_VALUE_ATTR"
|
assert format_value_attr == "FORMAT_VALUE_ATTR"
|
||||||
attr = format_value_attr.attr
|
attr = format_value_attr.attr
|
||||||
@@ -483,6 +489,7 @@ def customize_for_version36(self, version):
|
|||||||
else:
|
else:
|
||||||
conversion = FSTRING_CONVERSION_MAP.get(attr, "")
|
conversion = FSTRING_CONVERSION_MAP.get(attr, "")
|
||||||
|
|
||||||
|
self.in_format_string = False
|
||||||
f_str = "f%s" % escape_string("{%s%s}" % (value, conversion))
|
f_str = "f%s" % escape_string("{%s%s}" % (value, conversion))
|
||||||
self.write(f_str)
|
self.write(f_str)
|
||||||
|
|
||||||
@@ -495,14 +502,14 @@ def customize_for_version36(self, version):
|
|||||||
p = self.prec
|
p = self.prec
|
||||||
self.prec = 100
|
self.prec = 100
|
||||||
|
|
||||||
result = ''
|
result = ""
|
||||||
for expr in node[:-1]:
|
for expr in node[:-1]:
|
||||||
assert expr == 'expr'
|
assert expr == "expr"
|
||||||
value = self.traverse(expr, indent='')
|
value = self.traverse(expr, indent="")
|
||||||
if expr[0].kind.startswith('formatted_value'):
|
if expr[0].kind.startswith('formatted_value'):
|
||||||
# remove leading 'f'
|
# remove leading 'f'
|
||||||
assert value.startswith('f')
|
if value.startswith("f"):
|
||||||
value = value[1:]
|
value = value[1:]
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
# {{ and }} in Python source-code format strings mean
|
# {{ and }} in Python source-code format strings mean
|
||||||
|
Reference in New Issue
Block a user