Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 96ca1b6

Browse files
authored
fix: Remove parenthesis around sole list items (psf#4312)
1 parent 17efac4 commit 96ca1b6

7 files changed

Lines changed: 436 additions & 3 deletions

File tree

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
<!-- Changes that affect Black's preview style -->
1919

20+
- Remove parentheses around sole list items (#4312)
21+
2022
### Configuration
2123

2224
<!-- Changes to how Black can be configured -->

docs/the_black_code_style/future_style.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ Currently, the following features are included in the preview style:
3838
blocks when the line is too long
3939
- `pep646_typed_star_arg_type_var_tuple`: fix type annotation spacing between * and more
4040
complex type variable tuple (i.e. `def fn(*args: *tuple[*Ts, T]) -> None: pass`)
41+
- `remove_lone_list_item_parens`: remove redundant parentheses around lone list items
42+
(depends on unstable `hug_parens_with_braces_and_square_brackets` feature in some
43+
cases)
4144

4245
(labels/unstable-features)=
4346

src/black/linegen.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,22 @@ def visit_NUMBER(self, leaf: Leaf) -> Iterator[Line]:
507507
normalize_numeric_literal(leaf)
508508
yield from self.visit_default(leaf)
509509

510+
def visit_atom(self, node: Node) -> Iterator[Line]:
511+
"""Visit any atom"""
512+
if (
513+
Preview.remove_lone_list_item_parens in self.mode
514+
and len(node.children) == 3
515+
):
516+
first = node.children[0]
517+
last = node.children[-1]
518+
if (first.type == token.LSQB and last.type == token.RSQB) or (
519+
first.type == token.LBRACE and last.type == token.RBRACE
520+
):
521+
# Lists or sets of one item
522+
maybe_make_parens_invisible_in_atom(node.children[1], parent=node)
523+
524+
yield from self.visit_default(node)
525+
510526
def visit_fstring(self, node: Node) -> Iterator[Line]:
511527
# currently we don't want to format and split f-strings at all.
512528
string_leaf = fstring_to_string(node)
@@ -1643,9 +1659,6 @@ def maybe_make_parens_invisible_in_atom(
16431659
not is_type_ignore_comment_string(middle.prefix.strip())
16441660
):
16451661
first.value = ""
1646-
if first.prefix.strip():
1647-
# Preserve comments before first paren
1648-
middle.prefix = first.prefix + middle.prefix
16491662
last.value = ""
16501663
maybe_make_parens_invisible_in_atom(
16511664
middle,
@@ -1657,6 +1670,13 @@ def maybe_make_parens_invisible_in_atom(
16571670
# Strip the invisible parens from `middle` by replacing
16581671
# it with the child in-between the invisible parens
16591672
middle.replace(middle.children[1])
1673+
1674+
if middle.children[0].prefix.strip():
1675+
# Preserve comments before first paren
1676+
middle.children[1].prefix = (
1677+
middle.children[0].prefix + middle.children[1].prefix
1678+
)
1679+
16601680
if middle.children[-1].prefix.strip():
16611681
# Preserve comments before last paren
16621682
last.prefix = middle.children[-1].prefix + last.prefix

src/black/mode.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ class Preview(Enum):
210210
docstring_check_for_newline = auto()
211211
remove_redundant_guard_parens = auto()
212212
parens_for_long_if_clauses_in_case_block = auto()
213+
# NOTE: remove_lone_list_item_parens requires
214+
# hug_parens_with_braces_and_square_brackets to remove parens in some cases
215+
remove_lone_list_item_parens = auto()
213216
pep646_typed_star_arg_type_var_tuple = auto()
214217

215218

src/black/resources/black.schema.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
"docstring_check_for_newline",
9292
"remove_redundant_guard_parens",
9393
"parens_for_long_if_clauses_in_case_block",
94+
"remove_lone_list_item_parens",
9495
"pep646_typed_star_arg_type_var_tuple"
9596
]
9697
},
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# flags: --preview
2+
items = [(123)]
3+
items = [(True)]
4+
items = [(((((True)))))]
5+
items = [(((((True,)))))]
6+
items = [((((()))))]
7+
items = [(x for x in [1])]
8+
items = {(123)}
9+
items = {(True)}
10+
items = {(((((True)))))}
11+
12+
# Requires `hug_parens_with_braces_and_square_brackets` unstable style to remove parentheses
13+
# around multiline values
14+
items = [
15+
(
16+
{"key1": "val1", "key2": "val2", "key3": "val3"}
17+
if some_var == "long strings"
18+
else {"key": "val"}
19+
)
20+
]
21+
items = [
22+
(
23+
{"key1": "val1", "key2": "val2"}
24+
if some_var == ""
25+
else {"key": "val"}
26+
)
27+
]
28+
29+
# Comments should not cause crashes
30+
items = [
31+
( # comment
32+
{"key1": "val1", "key2": "val2", "key3": "val3"}
33+
if some_var == "long strings"
34+
else {"key": "val"}
35+
)
36+
]
37+
items = [
38+
(
39+
{"key1": "val1", "key2": "val2", "key3": "val3"}
40+
if some_var == "long strings"
41+
else {"key": "val"}
42+
) # comment
43+
]
44+
45+
items = [ # comment
46+
(
47+
{"key1": "val1", "key2": "val2", "key3": "val3"}
48+
if some_var == "long strings"
49+
else {"key": "val"}
50+
)
51+
]
52+
items = [
53+
(
54+
{"key1": "val1", "key2": "val2", "key3": "val3"}
55+
if some_var == "long strings"
56+
else {"key": "val"}
57+
)
58+
] # comment
59+
60+
items = [
61+
(
62+
{"key1": "val1", "key2": "val2", "key3": "val3"} # comment
63+
if some_var == "long strings"
64+
else {"key": "val"}
65+
)
66+
]
67+
68+
items = [ # comment
69+
( # comment
70+
{"key1": "val1", "key2": "val2", "key3": "val3"}
71+
if some_var == "long strings"
72+
else {"key": "val"}
73+
)
74+
]
75+
items = [
76+
(
77+
{"key1": "val1", "key2": "val2", "key3": "val3"}
78+
if some_var == "long strings"
79+
else {"key": "val"}
80+
) # comment
81+
] # comment
82+
83+
84+
# output
85+
items = [123]
86+
items = [True]
87+
items = [True]
88+
items = [(True,)]
89+
items = [()]
90+
items = [(x for x in [1])]
91+
items = {123}
92+
items = {True}
93+
items = {True}
94+
95+
# Requires `hug_parens_with_braces_and_square_brackets` unstable style to remove parentheses
96+
# around multiline values
97+
items = [
98+
(
99+
{"key1": "val1", "key2": "val2", "key3": "val3"}
100+
if some_var == "long strings"
101+
else {"key": "val"}
102+
)
103+
]
104+
items = [{"key1": "val1", "key2": "val2"} if some_var == "" else {"key": "val"}]
105+
106+
# Comments should not cause crashes
107+
items = [
108+
( # comment
109+
{"key1": "val1", "key2": "val2", "key3": "val3"}
110+
if some_var == "long strings"
111+
else {"key": "val"}
112+
)
113+
]
114+
items = [
115+
(
116+
{"key1": "val1", "key2": "val2", "key3": "val3"}
117+
if some_var == "long strings"
118+
else {"key": "val"}
119+
) # comment
120+
]
121+
122+
items = [ # comment
123+
(
124+
{"key1": "val1", "key2": "val2", "key3": "val3"}
125+
if some_var == "long strings"
126+
else {"key": "val"}
127+
)
128+
]
129+
items = [
130+
(
131+
{"key1": "val1", "key2": "val2", "key3": "val3"}
132+
if some_var == "long strings"
133+
else {"key": "val"}
134+
)
135+
] # comment
136+
137+
items = [
138+
(
139+
{"key1": "val1", "key2": "val2", "key3": "val3"} # comment
140+
if some_var == "long strings"
141+
else {"key": "val"}
142+
)
143+
]
144+
145+
items = [ # comment
146+
( # comment
147+
{"key1": "val1", "key2": "val2", "key3": "val3"}
148+
if some_var == "long strings"
149+
else {"key": "val"}
150+
)
151+
]
152+
items = [
153+
(
154+
{"key1": "val1", "key2": "val2", "key3": "val3"}
155+
if some_var == "long strings"
156+
else {"key": "val"}
157+
) # comment
158+
] # comment

0 commit comments

Comments
 (0)