From b55ea63ff4858109fe4606a6caafb03fda946743 Mon Sep 17 00:00:00 2001 From: Richard Si <63936253+ichard26@users.noreply.github.com> Date: Mon, 26 Apr 2021 16:26:43 -0400 Subject: [PATCH] Stop stripping parens in even more illegal spots (#2148) We're only fixing them so fuzzers don't yell at us when we break "valid" code. I mean "valid" because some of the examples aren't even accepted by Python. --- src/black/__init__.py | 3 +++ tests/data/pep_572_do_not_remove_parens.py | 21 +++++++++++++++++++++ tests/data/pep_572_remove_parens.py | 15 +++++++++++++++ tests/test_black.py | 8 ++++++++ 4 files changed, 47 insertions(+) create mode 100644 tests/data/pep_572_do_not_remove_parens.py diff --git a/src/black/__init__.py b/src/black/__init__.py index 051de5d..015ca41 100644 --- a/src/black/__init__.py +++ b/src/black/__init__.py @@ -5624,6 +5624,9 @@ def maybe_make_parens_invisible_in_atom(node: LN, parent: LN) -> bool: syms.expr_stmt, syms.assert_stmt, syms.return_stmt, + # these ones aren't useful to end users, but they do please fuzzers + syms.for_stmt, + syms.del_stmt, ]: return False diff --git a/tests/data/pep_572_do_not_remove_parens.py b/tests/data/pep_572_do_not_remove_parens.py new file mode 100644 index 0000000..20e80a6 --- /dev/null +++ b/tests/data/pep_572_do_not_remove_parens.py @@ -0,0 +1,21 @@ +# Most of the following examples are really dumb, some of them aren't even accepted by Python, +# we're fixing them only so fuzzers (which follow the grammar which actually allows these +# examples matter of fact!) don't yell at us :p + +del (a := [1]) + +try: + pass +except (a := 1) as (b := why_does_this_exist): + pass + +for (z := 124) in (x := -124): + pass + +with (y := [3, 2, 1]) as (funfunfun := indeed): + pass + + +@(please := stop) +def sigh(): + pass diff --git a/tests/data/pep_572_remove_parens.py b/tests/data/pep_572_remove_parens.py index 9a80485..9718d95 100644 --- a/tests/data/pep_572_remove_parens.py +++ b/tests/data/pep_572_remove_parens.py @@ -33,6 +33,9 @@ def foo2(answer: (p := 42) = 5): lambda: (x := 1) +a[(x := 12)] +a[:(x := 13)] + # we don't touch expressions in f-strings but if we do one day, don't break 'em f'{(x:=10)}' @@ -43,6 +46,10 @@ def a(): yield (a := 2) raise (c := 3) +def this_is_so_dumb() -> (please := no): + pass + + # output if foo := 0: pass @@ -79,6 +86,9 @@ def foo2(answer: (p := 42) = 5): lambda: (x := 1) +a[(x := 12)] +a[:(x := 13)] + # we don't touch expressions in f-strings but if we do one day, don't break 'em f"{(x:=10)}" @@ -88,3 +98,8 @@ def a(): await (b := 1) yield (a := 2) raise (c := 3) + + +def this_is_so_dumb() -> (please := no): + pass + diff --git a/tests/test_black.py b/tests/test_black.py index 88ea317..c643f27 100644 --- a/tests/test_black.py +++ b/tests/test_black.py @@ -290,6 +290,14 @@ class BlackTestCase(BlackBaseTestCase): if sys.version_info >= (3, 8): black.assert_equivalent(source, actual) + @patch("black.dump_to_file", dump_to_stderr) + def test_pep_572_do_not_remove_parens(self) -> None: + source, expected = read_data("pep_572_do_not_remove_parens") + # the AST safety checks will fail, but that's expected, just make sure no + # parentheses are touched + actual = black.format_str(source, mode=DEFAULT_MODE) + self.assertFormatEqual(expected, actual) + def test_pep_572_version_detection(self) -> None: source, _ = read_data("pep_572") root = black.lib2to3_parse(source) -- 2.39.5