Skip to content

Commit e2adcd7

Browse files
authored
Fix a crash on dicts with paren-wrapped long string keys (#3262)
Fix a crash when formatting some dicts with parenthesis-wrapped long string keys. When LL[0] is an atom string, we need to check the atom node's siblings instead of LL[0] itself, e.g.: dictsetmaker atom STRING '"This is a really long string that can\'t be expected to fit in one line and is used as a nested dict\'s key"' /atom COLON ':' atom LSQB ' ' '[' listmaker STRING '"value"' COMMA ',' STRING ' ' '"value"' /listmaker RSQB ']' /atom COMMA ',' /dictsetmaker
1 parent 72a2559 commit e2adcd7

3 files changed

Lines changed: 34 additions & 0 deletions

File tree

CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
<!-- Changes that affect Black's preview style -->
1616

17+
- Fix a crash when formatting some dicts with parenthesis-wrapped long string keys
18+
(#3262)
19+
1720
### Configuration
1821

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

src/black/trans.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,16 @@ def _prefer_paren_wrap_match(LL: List[Leaf]) -> Optional[int]:
10711071
# And the string is surrounded by commas (or is the first/last child)...
10721072
prev_sibling = LL[0].prev_sibling
10731073
next_sibling = LL[0].next_sibling
1074+
if (
1075+
not prev_sibling
1076+
and not next_sibling
1077+
and parent_type(LL[0]) == syms.atom
1078+
):
1079+
# If it's an atom string, we need to check the parent atom's siblings.
1080+
parent = LL[0].parent
1081+
assert parent is not None # For type checkers.
1082+
prev_sibling = parent.prev_sibling
1083+
next_sibling = parent.next_sibling
10741084
if (not prev_sibling or prev_sibling.type == token.COMMA) and (
10751085
not next_sibling or next_sibling.type == token.COMMA
10761086
):

tests/data/preview/long_strings.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@
1818

1919
D4 = {"A long and ridiculous {}".format(string_key): "This is a really really really long string that has to go i,side of a dictionary. It is soooo bad.", some_func("calling", "some", "stuff"): "This is a really really really long string that has to go inside of a dictionary. It is {soooo} bad (#{x}).".format(sooo="soooo", x=2), "A %s %s" % ("formatted", "string"): "This is a really really really long string that has to go inside of a dictionary. It is %s bad (#%d)." % ("soooo", 2)}
2020

21+
D5 = { # Test for https://github.com/psf/black/issues/3261
22+
("This is a really long string that can't be expected to fit in one line and is used as a nested dict's key"): {"inner": "value"},
23+
}
24+
25+
D6 = { # Test for https://github.com/psf/black/issues/3261
26+
("This is a really long string that can't be expected to fit in one line and is used as a dict's key"): ["value1", "value2"],
27+
}
28+
2129
L1 = ["The is a short string", "This is a really long string that can't possibly be expected to fit all together on one line. Also it is inside a list literal, so it's expected to be wrapped in parens when spliting to avoid implicit str concatenation.", short_call("arg", {"key": "value"}), "This is another really really (not really) long string that also can't be expected to fit on one line and is, like the other string, inside a list literal.", ("parens should be stripped for short string in list")]
2230

2331
L2 = ["This is a really long string that can't be expected to fit in one line and is the only child of a list literal."]
@@ -357,6 +365,19 @@ def foo():
357365
% ("soooo", 2),
358366
}
359367

368+
D5 = { # Test for https://github.com/psf/black/issues/3261
369+
"This is a really long string that can't be expected to fit in one line and is used as a nested dict's key": {
370+
"inner": "value"
371+
},
372+
}
373+
374+
D6 = { # Test for https://github.com/psf/black/issues/3261
375+
"This is a really long string that can't be expected to fit in one line and is used as a dict's key": [
376+
"value1",
377+
"value2",
378+
],
379+
}
380+
360381
L1 = [
361382
"The is a short string",
362383
(

0 commit comments

Comments
 (0)