From 67fa8d4d542dcb2f1e85dbab045da5ac0f7c80da Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sat, 29 Jul 2023 16:45:55 -0400 Subject: [PATCH 1/6] Avoid removing whitespace for walrus operators within subscripts --- CHANGES.md | 1 + src/black/nodes.py | 3 +++ tests/data/py_310/pep_572_py310.py | 6 +++--- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 709c767b329..9e535e37033 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -66,6 +66,7 @@ (#3740) - Fix error in AST validation when _Black_ removes trailing whitespace in a type comment (#3773) +- Fix a bug whereby spaces were removed from walrus operators within subscript (#3823) ### Preview style diff --git a/src/black/nodes.py b/src/black/nodes.py index 45423b2596b..87d13020a16 100644 --- a/src/black/nodes.py +++ b/src/black/nodes.py @@ -345,6 +345,9 @@ def whitespace(leaf: Leaf, *, complex_subscript: bool) -> str: # noqa: C901 return NO + elif t == token.COLONEQUAL or prev.type == token.COLONEQUAL: + return SPACE + elif not complex_subscript: return NO diff --git a/tests/data/py_310/pep_572_py310.py b/tests/data/py_310/pep_572_py310.py index cb82b2d23f8..3487ac8536a 100644 --- a/tests/data/py_310/pep_572_py310.py +++ b/tests/data/py_310/pep_572_py310.py @@ -1,7 +1,7 @@ # Unparenthesized walruses are now allowed in indices since Python 3.10. -x[a:=0] -x[a:=0, b:=1] -x[5, b:=0] +x[a := 0] +x[a := 0, b := 1] +x[5, b := 0] # Walruses are allowed inside generator expressions on function calls since 3.10. if any(match := pattern_error.match(s) for s in buffer): From 1d0b8e5321ecde09cbf8a1d06d0f42d43d6958e3 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sun, 30 Jul 2023 19:47:28 -0400 Subject: [PATCH 2/6] Only apply in preview --- src/black/lines.py | 2 +- src/black/nodes.py | 5 +++-- tests/data/preview/pep_572.py | 3 +++ tests/data/py_310/pep_572_py310.py | 6 +++--- 4 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 tests/data/preview/pep_572.py diff --git a/src/black/lines.py b/src/black/lines.py index 016a489310d..7ccd401142a 100644 --- a/src/black/lines.py +++ b/src/black/lines.py @@ -81,7 +81,7 @@ def append( # Note: at this point leaf.prefix should be empty except for # imports, for which we only preserve newlines. leaf.prefix += whitespace( - leaf, complex_subscript=self.is_complex_subscript(leaf) + leaf, complex_subscript=self.is_complex_subscript(leaf), mode=self.mode, ) if self.inside_brackets or not preformatted or track_bracket: self.bracket_tracker.mark(leaf) diff --git a/src/black/nodes.py b/src/black/nodes.py index 87d13020a16..abd5b8e60bf 100644 --- a/src/black/nodes.py +++ b/src/black/nodes.py @@ -13,6 +13,7 @@ from mypy_extensions import mypyc_attr from black.cache import CACHE_DIR +from black.mode import Mode from black.strings import has_triple_quotes from blib2to3 import pygram from blib2to3.pgen2 import token @@ -171,7 +172,7 @@ def visit_default(self, node: LN) -> Iterator[T]: yield from self.visit(child) -def whitespace(leaf: Leaf, *, complex_subscript: bool) -> str: # noqa: C901 +def whitespace(leaf: Leaf, *, complex_subscript: bool, mode: Mode) -> str: # noqa: C901 """Return whitespace prefix if needed for the given `leaf`. `complex_subscript` signals whether the given leaf is part of a subscription @@ -345,7 +346,7 @@ def whitespace(leaf: Leaf, *, complex_subscript: bool) -> str: # noqa: C901 return NO - elif t == token.COLONEQUAL or prev.type == token.COLONEQUAL: + elif mode.preview and (t == token.COLONEQUAL or prev.type == token.COLONEQUAL): return SPACE elif not complex_subscript: diff --git a/tests/data/preview/pep_572.py b/tests/data/preview/pep_572.py new file mode 100644 index 00000000000..f0a3a27d188 --- /dev/null +++ b/tests/data/preview/pep_572.py @@ -0,0 +1,3 @@ +x[a := 0] +x[a := 0, b := 1] +x[5, b := 0] diff --git a/tests/data/py_310/pep_572_py310.py b/tests/data/py_310/pep_572_py310.py index 3487ac8536a..cb82b2d23f8 100644 --- a/tests/data/py_310/pep_572_py310.py +++ b/tests/data/py_310/pep_572_py310.py @@ -1,7 +1,7 @@ # Unparenthesized walruses are now allowed in indices since Python 3.10. -x[a := 0] -x[a := 0, b := 1] -x[5, b := 0] +x[a:=0] +x[a:=0, b:=1] +x[5, b:=0] # Walruses are allowed inside generator expressions on function calls since 3.10. if any(match := pattern_error.match(s) for s in buffer): From ad59efb6be0ef47703b3ee9bd269199172c14306 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Thu, 3 Aug 2023 19:27:44 -0700 Subject: [PATCH 3/6] format --- src/black/lines.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/black/lines.py b/src/black/lines.py index 7ccd401142a..4fee631bc26 100644 --- a/src/black/lines.py +++ b/src/black/lines.py @@ -81,7 +81,9 @@ def append( # Note: at this point leaf.prefix should be empty except for # imports, for which we only preserve newlines. leaf.prefix += whitespace( - leaf, complex_subscript=self.is_complex_subscript(leaf), mode=self.mode, + leaf, + complex_subscript=self.is_complex_subscript(leaf), + mode=self.mode, ) if self.inside_brackets or not preformatted or track_bracket: self.bracket_tracker.mark(leaf) From cfb2438a1c9c943852ab0b28a530953e60bb51d8 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Thu, 3 Aug 2023 19:30:42 -0700 Subject: [PATCH 4/6] preview --- src/black/mode.py | 1 + src/black/nodes.py | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/black/mode.py b/src/black/mode.py index 282c1669da7..06d20b7a7d6 100644 --- a/src/black/mode.py +++ b/src/black/mode.py @@ -183,6 +183,7 @@ class Preview(Enum): wrap_long_dict_values_in_parens = auto() wrap_multiple_context_managers_in_parens = auto() dummy_implementations = auto() + walrus_subscript = auto() class Deprecated(UserWarning): diff --git a/src/black/nodes.py b/src/black/nodes.py index abd5b8e60bf..edd201a21e9 100644 --- a/src/black/nodes.py +++ b/src/black/nodes.py @@ -13,7 +13,7 @@ from mypy_extensions import mypyc_attr from black.cache import CACHE_DIR -from black.mode import Mode +from black.mode import Mode, Preview from black.strings import has_triple_quotes from blib2to3 import pygram from blib2to3.pgen2 import token @@ -346,7 +346,9 @@ def whitespace(leaf: Leaf, *, complex_subscript: bool, mode: Mode) -> str: # no return NO - elif mode.preview and (t == token.COLONEQUAL or prev.type == token.COLONEQUAL): + elif Preview.walrus_subscript in mode and ( + t == token.COLONEQUAL or prev.type == token.COLONEQUAL + ): return SPACE elif not complex_subscript: From 22dfe4f926b20c0cbbc26b6d69f347d0069487eb Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Thu, 3 Aug 2023 19:33:56 -0700 Subject: [PATCH 5/6] more test --- tests/data/preview/pep_572.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/data/preview/pep_572.py b/tests/data/preview/pep_572.py index f0a3a27d188..3583a07b3f2 100644 --- a/tests/data/preview/pep_572.py +++ b/tests/data/preview/pep_572.py @@ -1,3 +1,14 @@ +x[a:=0] x[a := 0] x[a := 0, b := 1] x[5, b := 0] +x[(a:=0):] +x[:(a:=0)] + +# output +x[a := 0] +x[a := 0] +x[a := 0, b := 1] +x[5, b := 0] +x[(a := 0):] +x[:(a := 0)] From 4aca4b3a1964af63c1415b9819d2e906e16c528d Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Fri, 8 Sep 2023 07:06:47 -0700 Subject: [PATCH 6/6] Fix tests --- tests/data/preview/pep_572.py | 8 -------- tests/data/preview_py_310/pep_572.py | 12 ++++++++++++ tests/test_format.py | 7 +++++++ 3 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 tests/data/preview_py_310/pep_572.py diff --git a/tests/data/preview/pep_572.py b/tests/data/preview/pep_572.py index 3583a07b3f2..a50e130ad9c 100644 --- a/tests/data/preview/pep_572.py +++ b/tests/data/preview/pep_572.py @@ -1,14 +1,6 @@ -x[a:=0] -x[a := 0] -x[a := 0, b := 1] -x[5, b := 0] x[(a:=0):] x[:(a:=0)] # output -x[a := 0] -x[a := 0] -x[a := 0, b := 1] -x[5, b := 0] x[(a := 0):] x[:(a := 0)] diff --git a/tests/data/preview_py_310/pep_572.py b/tests/data/preview_py_310/pep_572.py new file mode 100644 index 00000000000..78d4e9e4506 --- /dev/null +++ b/tests/data/preview_py_310/pep_572.py @@ -0,0 +1,12 @@ +x[a:=0] +x[a := 0] +x[a := 0, b := 1] +x[5, b := 0] +x[a:=0,b:=1] + +# output +x[a := 0] +x[a := 0] +x[a := 0, b := 1] +x[5, b := 0] +x[a := 0, b := 1] diff --git a/tests/test_format.py b/tests/test_format.py index fb4d8eb4346..0650a2d6e53 100644 --- a/tests/test_format.py +++ b/tests/test_format.py @@ -56,6 +56,13 @@ def test_preview_context_managers_targeting_py39() -> None: assert_format(source, expected, mode, minimum_version=(3, 9)) +@pytest.mark.parametrize("filename", all_data_cases("preview_py_310")) +def test_preview_python_310(filename: str) -> None: + source, expected = read_data("preview_py_310", filename) + mode = black.Mode(target_versions={black.TargetVersion.PY310}, preview=True) + assert_format(source, expected, mode, minimum_version=(3, 10)) + + @pytest.mark.parametrize( "filename", all_data_cases("preview_context_managers/auto_detect") )