diff options
author | Shantanu <12621235+hauntsaninja@users.noreply.github.com> | 2020-11-20 21:16:42 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-20 21:16:42 (GMT) |
commit | a993e901ebe60c38d46ecb31f771d0b4a206828c (patch) | |
tree | 949001849d989d051d9b2d0e5feb361bb7f51c55 /Lib/test/test_unparse.py | |
parent | 9fc319dc033fa32d298fe1c3f171b3d011ac04f0 (diff) | |
download | cpython-a993e901ebe60c38d46ecb31f771d0b4a206828c.zip cpython-a993e901ebe60c38d46ecb31f771d0b4a206828c.tar.gz cpython-a993e901ebe60c38d46ecb31f771d0b4a206828c.tar.bz2 |
bpo-28002: Roundtrip f-strings with ast.unparse better (#19612)
By attempting to avoid backslashes in f-string expressions.
We also now proactively raise errors for some backslashes we can't
avoid while unparsing FormattedValues
Co-authored-by: hauntsaninja <>
Co-authored-by: Shantanu <hauntsaninja@users.noreply.github.com>
Co-authored-by: Batuhan Taskaya <isidentical@gmail.com>
Diffstat (limited to 'Lib/test/test_unparse.py')
-rw-r--r-- | Lib/test/test_unparse.py | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/Lib/test/test_unparse.py b/Lib/test/test_unparse.py index 532aa3a..c7c8613 100644 --- a/Lib/test/test_unparse.py +++ b/Lib/test/test_unparse.py @@ -152,6 +152,18 @@ class UnparseTestCase(ASTTestCase): # See issue 25180 self.check_ast_roundtrip(r"""f'{f"{0}"*3}'""") self.check_ast_roundtrip(r"""f'{f"{y}"*3}'""") + self.check_ast_roundtrip("""f''""") + self.check_ast_roundtrip('''f"""'end' "quote\\""""''') + + def test_fstrings_complicated(self): + # See issue 28002 + self.check_ast_roundtrip("""f'''{"'"}'''""") + self.check_ast_roundtrip('''f\'\'\'-{f"""*{f"+{f'.{x}.'}+"}*"""}-\'\'\'''') + self.check_ast_roundtrip('''f\'\'\'-{f"""*{f"+{f'.{x}.'}+"}*"""}-'single quote\\'\'\'\'''') + self.check_ast_roundtrip('f"""{\'\'\'\n\'\'\'}"""') + self.check_ast_roundtrip('f"""{g(\'\'\'\n\'\'\')}"""') + self.check_ast_roundtrip('''f"a\\r\\nb"''') + self.check_ast_roundtrip('''f"\\u2028{'x'}"''') def test_strings(self): self.check_ast_roundtrip("u'foo'") @@ -311,6 +323,9 @@ class UnparseTestCase(ASTTestCase): ) ) + def test_invalid_fstring_backslash(self): + self.check_invalid(ast.FormattedValue(value=ast.Constant(value="\\\\"))) + def test_invalid_set(self): self.check_invalid(ast.Set(elts=[])) @@ -330,8 +345,8 @@ class UnparseTestCase(ASTTestCase): '\r\\r\t\\t\n\\n', '""">>> content = \"\"\"blabla\"\"\" <<<"""', r'foo\n\x00', - '🐍⛎𩸽üéş^\N{LONG RIGHTWARDS SQUIGGLE ARROW}' - + "' \\'\\'\\'\"\"\" \"\"\\'\\' \\'", + '🐍⛎𩸽üéş^\\\\X\\\\BB\N{LONG RIGHTWARDS SQUIGGLE ARROW}' ) for docstring in docstrings: # check as Module docstrings for easy testing @@ -416,7 +431,6 @@ class CosmeticTestCase(ASTTestCase): self.check_src_roundtrip("call((yield x))") self.check_src_roundtrip("return x + (yield x)") - def test_class_bases_and_keywords(self): self.check_src_roundtrip("class X:\n pass") self.check_src_roundtrip("class X(A):\n pass") @@ -429,6 +443,13 @@ class CosmeticTestCase(ASTTestCase): self.check_src_roundtrip("class X(*args):\n pass") self.check_src_roundtrip("class X(*args, **kwargs):\n pass") + def test_fstrings(self): + self.check_src_roundtrip('''f\'\'\'-{f"""*{f"+{f'.{x}.'}+"}*"""}-\'\'\'''') + self.check_src_roundtrip('''f"\\u2028{'x'}"''') + self.check_src_roundtrip(r"f'{x}\n'") + self.check_src_roundtrip('''f''\'{"""\n"""}\\n''\'''') + self.check_src_roundtrip('''f''\'{f"""{x}\n"""}\\n''\'''') + def test_docstrings(self): docstrings = ( '"""simple doc string"""', @@ -443,6 +464,10 @@ class CosmeticTestCase(ASTTestCase): '""""""', '"""\'\'\'"""', '"""\'\'\'\'\'\'"""', + '"""🐍⛎𩸽üéş^\\\\X\\\\BB⟿"""', + '"""end in single \'quote\'"""', + "'''end in double \"quote\"'''", + '"""almost end in double "quote"."""', ) for prefix in docstring_prefixes: @@ -483,9 +508,8 @@ class DirectoryTestCase(ASTTestCase): lib_dir = pathlib.Path(__file__).parent / ".." test_directories = (lib_dir, lib_dir / "test") - skip_files = {"test_fstring.py"} run_always_files = {"test_grammar.py", "test_syntax.py", "test_compile.py", - "test_ast.py", "test_asdl_parser.py"} + "test_ast.py", "test_asdl_parser.py", "test_fstring.py"} _files_to_test = None @@ -525,14 +549,6 @@ class DirectoryTestCase(ASTTestCase): if test.support.verbose: print(f"Testing {item.absolute()}") - # Some f-strings are not correctly round-tripped by - # Tools/parser/unparse.py. See issue 28002 for details. - # We need to skip files that contain such f-strings. - if item.name in self.skip_files: - if test.support.verbose: - print(f"Skipping {item.absolute()}: see issue 28002") - continue - with self.subTest(filename=item): source = read_pyfile(item) self.check_ast_roundtrip(source) |