From b6308d5d34e4db072a6c62ef64c3f202ff637b04 Mon Sep 17 00:00:00 2001 From: Kelvin Li <13176405+rdrll@users.noreply.github.com> Date: Sat, 4 Nov 2023 14:14:43 -0700 Subject: [PATCH 01/12] fix for line too long case block (w/ changes to unit test) --- src/black/linegen.py | 7 ++++ tests/data/cases/pattern_matching_extras.py | 20 +--------- tests/data/cases/pattern_matching_generic.py | 4 +- tests/data/cases/pattern_matching_long.py | 38 +++++++++++++++++++ .../cases/pattern_matching_trailing_comma.py | 38 +++++++++++++++++++ 5 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 tests/data/cases/pattern_matching_long.py create mode 100644 tests/data/cases/pattern_matching_trailing_comma.py diff --git a/src/black/linegen.py b/src/black/linegen.py index b13b95d9b31..7fba7199772 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -1260,6 +1260,13 @@ def normalize_invisible_parens( child, parens_after=parens_after, mode=mode, features=features ) + # Fixes a bug where invisible parens are not properly wrapped around + # case blocks. + if isinstance(child, Node) and child.type == syms.case_block: + normalize_invisible_parens( + child, parens_after={"case"}, mode=mode, features=features + ) + # Add parentheses around long tuple unpacking in assignments. if ( index == 0 diff --git a/tests/data/cases/pattern_matching_extras.py b/tests/data/cases/pattern_matching_extras.py index 1e1481d7bbe..6c3f84dbe82 100644 --- a/tests/data/cases/pattern_matching_extras.py +++ b/tests/data/cases/pattern_matching_extras.py @@ -30,22 +30,6 @@ def func(match: case, case: match) -> case: ... -match maybe, multiple: - case perhaps, 5: - pass - case perhaps, 6,: - pass - - -match more := (than, one), indeed,: - case _, (5, 6): - pass - case [[5], (6)], [7],: - pass - case _: - pass - - match a, *b, c: case [*_]: assert "seq" == _ @@ -71,12 +55,12 @@ def func(match: case, case: match) -> case: case [a as match]: pass - case case: + case anything: pass match match: - case case: + case something: pass diff --git a/tests/data/cases/pattern_matching_generic.py b/tests/data/cases/pattern_matching_generic.py index 4b4d45f0bff..1d100f80ce3 100644 --- a/tests/data/cases/pattern_matching_generic.py +++ b/tests/data/cases/pattern_matching_generic.py @@ -25,9 +25,9 @@ def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]: ] match match: - case case: + case something: match match: - case case: + case something: pass if all(version.is_python2() for version in target_versions): diff --git a/tests/data/cases/pattern_matching_long.py b/tests/data/cases/pattern_matching_long.py new file mode 100644 index 00000000000..cede2bf81a2 --- /dev/null +++ b/tests/data/cases/pattern_matching_long.py @@ -0,0 +1,38 @@ +match x: + case "abcd" | "abcd" | "abcd" : + pass + case "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd" | "abcd": + pass + case xxxxxxxxxxxxxxxxxxxxxxx: + pass + case case: + pass + +# output + +match x: + case "abcd" | "abcd" | "abcd": + pass + case ( + "abcd" + | "abcd" + | "abcd" + | "abcd" + | "abcd" + | "abcd" + | "abcd" + | "abcd" + | "abcd" + | "abcd" + | "abcd" + | "abcd" + | "abcd" + | "abcd" + | "abcd" + ): + pass + case xxxxxxxxxxxxxxxxxxxxxxx: + pass + case case : + pass + diff --git a/tests/data/cases/pattern_matching_trailing_comma.py b/tests/data/cases/pattern_matching_trailing_comma.py new file mode 100644 index 00000000000..11b6c76ac6b --- /dev/null +++ b/tests/data/cases/pattern_matching_trailing_comma.py @@ -0,0 +1,38 @@ +match maybe, multiple: + case perhaps, 5: + pass + case perhaps, 6,: + pass + + +match more := (than, one), indeed,: + case _, (5, 6): + pass + case [[5], (6)], [7],: + pass + case _: + pass + + +# output + +match maybe, multiple: + case perhaps, 5: + pass + case ( + perhaps, + 6, + ): + pass + + +match more := (than, one), indeed,: + case _, (5, 6): + pass + case ( + [[5], (6)], + [7], + ): + pass + case _: + pass \ No newline at end of file From 8fa0ad0f40b6129d16cc896feb73d3612fa41e53 Mon Sep 17 00:00:00 2001 From: Kelvin Li <13176405+rdrll@users.noreply.github.com> Date: Sat, 4 Nov 2023 14:23:32 -0700 Subject: [PATCH 02/12] modify minimum version for new unit tests --- tests/data/cases/pattern_matching_long.py | 1 + tests/data/cases/pattern_matching_trailing_comma.py | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/data/cases/pattern_matching_long.py b/tests/data/cases/pattern_matching_long.py index cede2bf81a2..0ef69e92dbc 100644 --- a/tests/data/cases/pattern_matching_long.py +++ b/tests/data/cases/pattern_matching_long.py @@ -1,3 +1,4 @@ +# flags: --minimum-version=3.10 match x: case "abcd" | "abcd" | "abcd" : pass diff --git a/tests/data/cases/pattern_matching_trailing_comma.py b/tests/data/cases/pattern_matching_trailing_comma.py index 11b6c76ac6b..5660b0f6a14 100644 --- a/tests/data/cases/pattern_matching_trailing_comma.py +++ b/tests/data/cases/pattern_matching_trailing_comma.py @@ -1,3 +1,4 @@ +# flags: --minimum-version=3.10 match maybe, multiple: case perhaps, 5: pass From 07be862e12f6fe736ad09b74945d05141998bdcf Mon Sep 17 00:00:00 2001 From: Kelvin Li <13176405+rdrll@users.noreply.github.com> Date: Sat, 4 Nov 2023 14:46:32 -0700 Subject: [PATCH 03/12] Add changes.md --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 5ce37943693..739550cd453 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,8 @@ - Fix crash when whitespace followed a backslash before newline in a docstring (#4008) - Fix crash on formatting code like `await (a ** b)` (#3994) +- Fix a bug that long `case` blocks will not be split into multiple lines, also enabled + general trailing comma rules on `case` blocks (#4024) ### Preview style From 8cf81da7a62ded99fee1c448fab25695fe6a1b2f Mon Sep 17 00:00:00 2001 From: Kelvin Li <13176405+rdrll@users.noreply.github.com> Date: Sun, 5 Nov 2023 12:03:15 -0800 Subject: [PATCH 04/12] Adding a fix for "case case:" scenario, modified unit tests --- src/black/linegen.py | 12 +++++++++++- tests/data/cases/pattern_matching_extras.py | 7 +++++-- tests/data/cases/pattern_matching_generic.py | 4 ++-- tests/data/cases/pattern_matching_long.py | 5 ----- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/black/linegen.py b/src/black/linegen.py index 7fba7199772..6781a241f07 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -1229,7 +1229,7 @@ def normalize_prefix(leaf: Leaf, *, inside_brackets: bool) -> None: leaf.prefix = "" -def normalize_invisible_parens( +def normalize_invisible_parens( # noqa: C901 node: Node, parens_after: Set[str], *, mode: Mode, features: Collection[Feature] ) -> None: """Make existing optional parentheses invisible or create new ones. @@ -1312,6 +1312,16 @@ def normalize_invisible_parens( # invisible parentheses to work more precisely. continue + elif ( + isinstance(child, Leaf) + and child.next_sibling is not None + and child.next_sibling.type == token.COLON + and child.value == "case" + ): + # A special patch for "case case:" scenario, the second occurrence + # of case will be not parsed as an actual keyword + break + elif not (isinstance(child, Leaf) and is_multiline_string(child)): wrap_in_parentheses(node, child, visible=False) diff --git a/tests/data/cases/pattern_matching_extras.py b/tests/data/cases/pattern_matching_extras.py index 6c3f84dbe82..d8d64a477fc 100644 --- a/tests/data/cases/pattern_matching_extras.py +++ b/tests/data/cases/pattern_matching_extras.py @@ -55,12 +55,15 @@ def func(match: case, case: match) -> case: case [a as match]: pass - case anything: + case case: + pass + + case something: pass match match: - case something: + case case: pass diff --git a/tests/data/cases/pattern_matching_generic.py b/tests/data/cases/pattern_matching_generic.py index 1d100f80ce3..4b4d45f0bff 100644 --- a/tests/data/cases/pattern_matching_generic.py +++ b/tests/data/cases/pattern_matching_generic.py @@ -25,9 +25,9 @@ def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]: ] match match: - case something: + case case: match match: - case something: + case case: pass if all(version.is_python2() for version in target_versions): diff --git a/tests/data/cases/pattern_matching_long.py b/tests/data/cases/pattern_matching_long.py index 0ef69e92dbc..9a944c9d0c9 100644 --- a/tests/data/cases/pattern_matching_long.py +++ b/tests/data/cases/pattern_matching_long.py @@ -6,8 +6,6 @@ pass case xxxxxxxxxxxxxxxxxxxxxxx: pass - case case: - pass # output @@ -34,6 +32,3 @@ pass case xxxxxxxxxxxxxxxxxxxxxxx: pass - case case : - pass - From fbb9300569a3f3081bff602f963fa19b56f45e97 Mon Sep 17 00:00:00 2001 From: Kelvin Li <13176405+rdrll@users.noreply.github.com> Date: Sun, 5 Nov 2023 13:13:27 -0800 Subject: [PATCH 05/12] trigger for another GitHub Action run Co-Authored-By: Jelle Zijlstra --- src/black/linegen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/black/linegen.py b/src/black/linegen.py index 6781a241f07..833560e864d 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -1319,7 +1319,7 @@ def normalize_invisible_parens( # noqa: C901 and child.value == "case" ): # A special patch for "case case:" scenario, the second occurrence - # of case will be not parsed as an actual keyword + # of case will be not parsed as a Python keyword break elif not (isinstance(child, Leaf) and is_multiline_string(child)): From 9ba3e74a476a3bcf875ebaf354090e1aa0190e2c Mon Sep 17 00:00:00 2001 From: Kelvin Li <13176405+rdrll@users.noreply.github.com> Date: Sun, 5 Nov 2023 14:30:33 -0800 Subject: [PATCH 06/12] Another try on CI --- src/black/linegen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/black/linegen.py b/src/black/linegen.py index 833560e864d..2eb14c26f64 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -1319,7 +1319,7 @@ def normalize_invisible_parens( # noqa: C901 and child.value == "case" ): # A special patch for "case case:" scenario, the second occurrence - # of case will be not parsed as a Python keyword + # of case will be not parsed as a Python keyword. break elif not (isinstance(child, Leaf) and is_multiline_string(child)): From 46ba06bd0a98130482e184e2dc224f435afe01b5 Mon Sep 17 00:00:00 2001 From: Kelvin Li <13176405+rdrll@users.noreply.github.com> Date: Sun, 5 Nov 2023 16:11:17 -0800 Subject: [PATCH 07/12] Update CHANGES.md --- CHANGES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 739550cd453..468ef3a5d36 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,8 +12,6 @@ - Fix crash when whitespace followed a backslash before newline in a docstring (#4008) - Fix crash on formatting code like `await (a ** b)` (#3994) -- Fix a bug that long `case` blocks will not be split into multiple lines, also enabled - general trailing comma rules on `case` blocks (#4024) ### Preview style @@ -21,6 +19,8 @@ indented less (#3964) - Multiline list and dict unpacking as the sole argument to a function is now also indented less (#3992) +- Fix a bug that long `case` blocks will not be split into multiple lines, while now + also enabled general trailing comma rules on `case` blocks (#4024) ### Configuration From c28c5c0df364f5f961db1f08c5d6c282bf6d0c63 Mon Sep 17 00:00:00 2001 From: Kelvin Li <13176405+rdrll@users.noreply.github.com> Date: Sun, 5 Nov 2023 20:03:47 -0800 Subject: [PATCH 08/12] channel modifications to preview mode, unit test also modified --- src/black/linegen.py | 7 ++++++- src/black/mode.py | 1 + tests/data/cases/pattern_matching_extras.py | 5 ----- ...n_matching_long.py => preview_pattern_matching_long.py} | 2 +- ...comma.py => preview_pattern_matching_trailing_comma.py} | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) rename tests/data/cases/{pattern_matching_long.py => preview_pattern_matching_long.py} (94%) rename tests/data/cases/{pattern_matching_trailing_comma.py => preview_pattern_matching_trailing_comma.py} (90%) diff --git a/src/black/linegen.py b/src/black/linegen.py index 2eb14c26f64..30cfff3e846 100644 --- a/src/black/linegen.py +++ b/src/black/linegen.py @@ -1262,7 +1262,11 @@ def normalize_invisible_parens( # noqa: C901 # Fixes a bug where invisible parens are not properly wrapped around # case blocks. - if isinstance(child, Node) and child.type == syms.case_block: + if ( + isinstance(child, Node) + and child.type == syms.case_block + and Preview.long_case_block_line_splitting in mode + ): normalize_invisible_parens( child, parens_after={"case"}, mode=mode, features=features ) @@ -1317,6 +1321,7 @@ def normalize_invisible_parens( # noqa: C901 and child.next_sibling is not None and child.next_sibling.type == token.COLON and child.value == "case" + and Preview.long_case_block_line_splitting in mode ): # A special patch for "case case:" scenario, the second occurrence # of case will be not parsed as a Python keyword. diff --git a/src/black/mode.py b/src/black/mode.py index 4e4effffb86..1aa5cbecc86 100644 --- a/src/black/mode.py +++ b/src/black/mode.py @@ -193,6 +193,7 @@ class Preview(Enum): hug_parens_with_braces_and_square_brackets = auto() allow_empty_first_line_before_new_block_or_comment = auto() single_line_format_skip_with_multiple_comments = auto() + long_case_block_line_splitting = auto() class Deprecated(UserWarning): diff --git a/tests/data/cases/pattern_matching_extras.py b/tests/data/cases/pattern_matching_extras.py index d8d64a477fc..1aef8f16b5a 100644 --- a/tests/data/cases/pattern_matching_extras.py +++ b/tests/data/cases/pattern_matching_extras.py @@ -51,13 +51,10 @@ def func(match: case, case: match) -> case: ), ): pass - case [a as match]: pass - case case: pass - case something: pass @@ -85,10 +82,8 @@ def func(match: case, case: match) -> case: match something: case 1 as a: pass - case 2 as b, 3 as c: pass - case 4 as d, (5 as e), (6 | 7 as g), *h: pass diff --git a/tests/data/cases/pattern_matching_long.py b/tests/data/cases/preview_pattern_matching_long.py similarity index 94% rename from tests/data/cases/pattern_matching_long.py rename to tests/data/cases/preview_pattern_matching_long.py index 9a944c9d0c9..df849fdc4f2 100644 --- a/tests/data/cases/pattern_matching_long.py +++ b/tests/data/cases/preview_pattern_matching_long.py @@ -1,4 +1,4 @@ -# flags: --minimum-version=3.10 +# flags: --preview --minimum-version=3.10 match x: case "abcd" | "abcd" | "abcd" : pass diff --git a/tests/data/cases/pattern_matching_trailing_comma.py b/tests/data/cases/preview_pattern_matching_trailing_comma.py similarity index 90% rename from tests/data/cases/pattern_matching_trailing_comma.py rename to tests/data/cases/preview_pattern_matching_trailing_comma.py index 5660b0f6a14..e6c0d88bb80 100644 --- a/tests/data/cases/pattern_matching_trailing_comma.py +++ b/tests/data/cases/preview_pattern_matching_trailing_comma.py @@ -1,4 +1,4 @@ -# flags: --minimum-version=3.10 +# flags: --preview --minimum-version=3.10 match maybe, multiple: case perhaps, 5: pass From caf963eff0c95b2e53799b3e760724769a163a0f Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Mon, 6 Nov 2023 17:56:06 -0800 Subject: [PATCH 09/12] Update CHANGES.md --- CHANGES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5046cd4c23e..b5ee0893cb4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -22,8 +22,8 @@ indented less (#3964) - Multiline list and dict unpacking as the sole argument to a function is now also indented less (#3992) -- Fix a bug that long `case` blocks will not be split into multiple lines, while now - also enabled general trailing comma rules on `case` blocks (#4024) +- Fix a bug where long `case` blocks were not split into multiple lines. Also + enable general trailing comma rules on `case` blocks (#4024) - Keep requiring two empty lines between module-level docstring and first function or class definition. (#4028) From 9c88568947c728ea3476cd877f881d552f47f9e4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 7 Nov 2023 01:56:24 +0000 Subject: [PATCH 10/12] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- CHANGES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b5ee0893cb4..a847d737518 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -22,8 +22,8 @@ indented less (#3964) - Multiline list and dict unpacking as the sole argument to a function is now also indented less (#3992) -- Fix a bug where long `case` blocks were not split into multiple lines. Also - enable general trailing comma rules on `case` blocks (#4024) +- Fix a bug where long `case` blocks were not split into multiple lines. Also enable + general trailing comma rules on `case` blocks (#4024) - Keep requiring two empty lines between module-level docstring and first function or class definition. (#4028) From f2b2a322e12417fde189c6a94b66314a779592c2 Mon Sep 17 00:00:00 2001 From: Kelvin Li <13176405+rdrll@users.noreply.github.com> Date: Mon, 6 Nov 2023 23:18:29 -0800 Subject: [PATCH 11/12] Update CHANGES.md --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index a847d737518..0c88e4299d2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -23,7 +23,7 @@ - Multiline list and dict unpacking as the sole argument to a function is now also indented less (#3992) - Fix a bug where long `case` blocks were not split into multiple lines. Also enable - general trailing comma rules on `case` blocks (#4024) + general trailing comma rules on `case` blocks. (#4024) - Keep requiring two empty lines between module-level docstring and first function or class definition. (#4028) From da296f35e7731fadc3e03d8f439015a96adf25b9 Mon Sep 17 00:00:00 2001 From: Kelvin Li <13176405+rdrll@users.noreply.github.com> Date: Tue, 7 Nov 2023 00:13:12 -0800 Subject: [PATCH 12/12] Update CHANGES.md --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 0c88e4299d2..a847d737518 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -23,7 +23,7 @@ - Multiline list and dict unpacking as the sole argument to a function is now also indented less (#3992) - Fix a bug where long `case` blocks were not split into multiple lines. Also enable - general trailing comma rules on `case` blocks. (#4024) + general trailing comma rules on `case` blocks (#4024) - Keep requiring two empty lines between module-level docstring and first function or class definition. (#4028)