@@ -1094,6 +1094,13 @@ def contains_standalone_comments(self, depth_limit: int = sys.maxsize) -> bool:
1094
1094
1095
1095
return False
1096
1096
1097
+ def contains_multiline_strings (self ) -> bool :
1098
+ for leaf in self .leaves :
1099
+ if is_multiline_string (leaf ):
1100
+ return True
1101
+
1102
+ return False
1103
+
1097
1104
def maybe_remove_trailing_comma (self , closing : Leaf ) -> bool :
1098
1105
"""Remove trailing comma if there is one and it's safe."""
1099
1106
if not (
@@ -2225,24 +2232,35 @@ def right_hand_split(
2225
2232
# the closing bracket is an optional paren
2226
2233
and closing_bracket .type == token .RPAR
2227
2234
and not closing_bracket .value
2228
- # there are no standalone comments in the body
2229
- and not line .contains_standalone_comments (0 )
2230
- # and it's not an import (optional parens are the only thing we can split
2231
- # on in this case; attempting a split without them is a waste of time)
2235
+ # it's not an import (optional parens are the only thing we can split on
2236
+ # in this case; attempting a split without them is a waste of time)
2232
2237
and not line .is_import
2238
+ # there are no standalone comments in the body
2239
+ and not body .contains_standalone_comments (0 )
2240
+ # and we can actually remove the parens
2241
+ and can_omit_invisible_parens (body , line_length )
2233
2242
):
2234
2243
omit = {id (closing_bracket ), * omit }
2235
- if can_omit_invisible_parens (body , line_length ):
2236
- try :
2237
- yield from right_hand_split (line , line_length , py36 = py36 , omit = omit )
2238
- return
2239
- except CannotSplit :
2240
- if len (body .leaves ) == 1 and not is_line_short_enough (
2241
- body , line_length = line_length
2242
- ):
2243
- raise CannotSplit (
2244
- "Splitting failed, body is still too long and can't be split."
2245
- )
2244
+ try :
2245
+ yield from right_hand_split (line , line_length , py36 = py36 , omit = omit )
2246
+ return
2247
+
2248
+ except CannotSplit :
2249
+ if not (
2250
+ can_be_split (body )
2251
+ or is_line_short_enough (body , line_length = line_length )
2252
+ ):
2253
+ raise CannotSplit (
2254
+ "Splitting failed, body is still too long and can't be split."
2255
+ )
2256
+
2257
+ elif head .contains_multiline_strings () or tail .contains_multiline_strings ():
2258
+ raise CannotSplit (
2259
+ "The current optional pair of parentheses is bound to fail to "
2260
+ "satisfy the splitting algorithm becase the head or the tail "
2261
+ "contains multiline strings which by definition never fit one "
2262
+ "line."
2263
+ )
2246
2264
2247
2265
ensure_visible (opening_bracket )
2248
2266
ensure_visible (closing_bracket )
@@ -3190,6 +3208,42 @@ def is_line_short_enough(line: Line, *, line_length: int, line_str: str = "") ->
3190
3208
)
3191
3209
3192
3210
3211
+ def can_be_split (line : Line ) -> bool :
3212
+ """Return False if the line cannot be split *for sure*.
3213
+
3214
+ This is not an exhaustive search but a cheap heuristic that we can use to
3215
+ avoid some unfortunate formattings (mostly around wrapping unsplittable code
3216
+ in unnecessary parentheses).
3217
+ """
3218
+ leaves = line .leaves
3219
+ if len (leaves ) < 2 :
3220
+ return False
3221
+
3222
+ if leaves [0 ].type == token .STRING and leaves [1 ].type == token .DOT :
3223
+ call_count = 0
3224
+ dot_count = 0
3225
+ next = leaves [- 1 ]
3226
+ for leaf in leaves [- 2 ::- 1 ]:
3227
+ if leaf .type in OPENING_BRACKETS :
3228
+ if next .type not in CLOSING_BRACKETS :
3229
+ return False
3230
+
3231
+ call_count += 1
3232
+ elif leaf .type == token .DOT :
3233
+ dot_count += 1
3234
+ elif leaf .type == token .NAME :
3235
+ if not (next .type == token .DOT or next .type in OPENING_BRACKETS ):
3236
+ return False
3237
+
3238
+ elif leaf .type not in CLOSING_BRACKETS :
3239
+ return False
3240
+
3241
+ if dot_count > 1 and call_count > 1 :
3242
+ return False
3243
+
3244
+ return True
3245
+
3246
+
3193
3247
def can_omit_invisible_parens (line : Line , line_length : int ) -> bool :
3194
3248
"""Does `line` have a shape safe to reformat without optional parens around it?
3195
3249
0 commit comments