diff --git a/test/bytecode_3.6_run/10_fstring.pyc b/test/bytecode_3.6_run/10_fstring.pyc index 2b936f01..b54bc491 100644 Binary files a/test/bytecode_3.6_run/10_fstring.pyc and b/test/bytecode_3.6_run/10_fstring.pyc differ diff --git a/test/bytecode_3.7_run/10_fstring.pyc b/test/bytecode_3.7_run/10_fstring.pyc index 719730e2..4288b0f6 100644 Binary files a/test/bytecode_3.7_run/10_fstring.pyc and b/test/bytecode_3.7_run/10_fstring.pyc differ diff --git a/test/bytecode_3.8_run/10_fstring.pyc b/test/bytecode_3.8_run/10_fstring.pyc index fcb22f35..8af17ed7 100644 Binary files a/test/bytecode_3.8_run/10_fstring.pyc and b/test/bytecode_3.8_run/10_fstring.pyc differ diff --git a/test/simple_source/bug36/10_fstring.py b/test/simple_source/bug36/10_fstring.py index d06ec562..ef38dabf 100644 --- a/test/simple_source/bug36/10_fstring.py +++ b/test/simple_source/bug36/10_fstring.py @@ -2,13 +2,17 @@ # String interpolation tests # RUNNABLE! -var1 = 'x' -var2 = 'y' -abc = 'def' -assert (f"interpolate {var1} strings {var2!r} {var2!s} 'py36" == - "interpolate x strings 'y' y 'py36") -assert 'def0' == f'{abc}0' -assert 'defdef' == f'{abc}{abc!s}' +"""This program is self-checking!""" + +var1 = "x" +var2 = "y" +abc = "def" +assert ( + f"interpolate {var1} strings {var2!r} {var2!s} 'py36" + == "interpolate x strings 'y' y 'py36" +) +assert "def0" == f"{abc}0" +assert "defdef" == f"{abc}{abc!s}" # From 3.6 functools.py # Bug was handling format operator strings. @@ -21,51 +25,51 @@ assert y == "functools.1=['2'](2)" # From 3.6 http/client.py # Bug is in handling X -chunk = ['a', 'b', 'c'] -chunk2 = 'd' -chunk = f'{len(chunk):X}' + chunk2 -assert chunk == '3d' +chunk = ["a", "b", "c"] +chunk2 = "d" +chunk = f"{len(chunk):X}" + chunk2 +assert chunk == "3d" -chunk = b'abc' -chunk2 = 'd' -chunk = f'{len(chunk):X}\r\n'.encode('ascii') + chunk \ - + b'\r\n' -assert chunk == b'3\r\nabc\r\n' +chunk = b"abc" +chunk2 = "d" +chunk = f"{len(chunk):X}\r\n".encode("ascii") + chunk + b"\r\n" +assert chunk == b"3\r\nabc\r\n" # From 3.6.8 idlelib/pyshell.py # Bug was handling ''' import os -filename = '.' -source = 'foo' -source = (f"__file__ = r'''{os.path.abspath(filename)}'''\n" - + source + "\ndel __file__") + +filename = "." +source = "foo" +source = f"__file__ = r'''{os.path.abspath(filename)}'''\n" + source + "\ndel __file__" # Note how { and } are *not* escaped here -f = 'one' -name = 'two' -assert(f"{f}{'{{name}}'} {f}{'{name}'}") == 'one{{name}} one{name}' +f = "one" +name = "two" +assert (f"{f}{'{{name}}'} {f}{'{name}'}") == "one{{name}} one{name}" # From 3.7.3 dataclasses.py -log_rounds = 5 -assert "05$" == f'{log_rounds:02d}$' +log_rounds = 5 +assert "05$" == f"{log_rounds:02d}$" def testit(a, b, l): # print(l) return l + # The call below shows the need for BUILD_STRING to count expr arguments. # Also note that we use {{ }} to escape braces in contrast to the example # above. def _repr_fn(fields): - return testit('__repr__', - ('self',), - ['return xx + f"(' + - ', '.join([f"{f}={{self.{f}!r}}" - for f in fields]) + - ')"']) + return testit( + "__repr__", + ("self",), + ['return xx + f"(' + ", ".join([f"{f}={{self.{f}!r}}" for f in fields]) + ')"'], + ) -fields = ['a', 'b', 'c'] + +fields = ["a", "b", "c"] assert _repr_fn(fields) == ['return xx + f"(a={self.a!r}, b={self.b!r}, c={self.c!r})"'] @@ -85,28 +89,31 @@ 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 ' +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''' + f"""Not a docstring""" + + def g(): - '''Not a docstring''' \ - f'' + """Not a docstring""" f"" + assert f.__doc__ is None assert g.__doc__ is None import decimal -width, precision, value = (10, 4, decimal.Decimal('12.34567')) + +width, precision, value = (10, 4, decimal.Decimal("12.34567")) # Make sure we don't have additional f'..' inside the format strings below. -assert f'result: {value:{width}.{precision}}' == 'result: 12.35' -assert f'result: {value:{width:0}.{precision:1}}' == 'result: 12.35' -assert f'{2}\t' == '2\t' +assert f"result: {value:{width}.{precision}}" == "result: 12.35" +assert f"result: {value:{width:0}.{precision:1}}" == "result: 12.35" +assert f"{2}\t" == "2\t" # But below we *do* need the additional f".." assert f'{f"{0}"*3}' == "000" @@ -115,4 +122,4 @@ assert f'{f"{0}"*3}' == "000" # ^ # The former, {{ confuses the format strings so dictionary/set comprehensions # don't work. -assert f'expr={ {x: y for x, y in [(1, 2), ]}}' == 'expr={1: 2}' +assert f"expr={ {x: y for x, y in [(1, 2), ]}}" == "expr={1: 2}" diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index d21cc5f8..9ab6f48a 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -2553,7 +2553,16 @@ class SourceWalker(GenericASTTraversal, object): else: self.customize(customize) self.text = self.traverse(ast, is_lambda=is_lambda) - self.println(self.text) + # In a formatted string using "lambda', we should not add "\n". + # For example in: + # f'{(lambda x:x)("8")!r}' + # Adding a "\n" after "lambda x: x" will give an error message: + # SyntaxError: f-string expression part cannot include a backslash + # So avoid that. + printfn = ( + self.write if self.in_format_string and is_lambda else self.println + ) + printfn(self.text) self.name = old_name self.return_none = rn