]> git.madduck.net Git - etc/vim.git/blob - .vim/bundle/black/src/black/lines.py

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Merge commit '882d8795c6ff65c02f2657e596391748d1b6b7f5'
[etc/vim.git] / .vim / bundle / black / src / black / lines.py
1 import itertools
2 import math
3 import sys
4 from dataclasses import dataclass, field
5 from typing import (
6     Callable,
7     Dict,
8     Iterator,
9     List,
10     Optional,
11     Sequence,
12     Tuple,
13     TypeVar,
14     Union,
15     cast,
16 )
17
18 from black.brackets import COMMA_PRIORITY, DOT_PRIORITY, BracketTracker
19 from black.mode import Mode, Preview
20 from black.nodes import (
21     BRACKETS,
22     CLOSING_BRACKETS,
23     OPENING_BRACKETS,
24     STANDALONE_COMMENT,
25     TEST_DESCENDANTS,
26     child_towards,
27     is_import,
28     is_multiline_string,
29     is_one_sequence_between,
30     is_type_comment,
31     is_type_ignore_comment,
32     is_with_or_async_with_stmt,
33     replace_child,
34     syms,
35     whitespace,
36 )
37 from black.strings import str_width
38 from blib2to3.pgen2 import token
39 from blib2to3.pytree import Leaf, Node
40
41 # types
42 T = TypeVar("T")
43 Index = int
44 LeafID = int
45 LN = Union[Leaf, Node]
46
47
48 @dataclass
49 class Line:
50     """Holds leaves and comments. Can be printed with `str(line)`."""
51
52     mode: Mode = field(repr=False)
53     depth: int = 0
54     leaves: List[Leaf] = field(default_factory=list)
55     # keys ordered like `leaves`
56     comments: Dict[LeafID, List[Leaf]] = field(default_factory=dict)
57     bracket_tracker: BracketTracker = field(default_factory=BracketTracker)
58     inside_brackets: bool = False
59     should_split_rhs: bool = False
60     magic_trailing_comma: Optional[Leaf] = None
61
62     def append(
63         self, leaf: Leaf, preformatted: bool = False, track_bracket: bool = False
64     ) -> None:
65         """Add a new `leaf` to the end of the line.
66
67         Unless `preformatted` is True, the `leaf` will receive a new consistent
68         whitespace prefix and metadata applied by :class:`BracketTracker`.
69         Trailing commas are maybe removed, unpacked for loop variables are
70         demoted from being delimiters.
71
72         Inline comments are put aside.
73         """
74         has_value = leaf.type in BRACKETS or bool(leaf.value.strip())
75         if not has_value:
76             return
77
78         if token.COLON == leaf.type and self.is_class_paren_empty:
79             del self.leaves[-2:]
80         if self.leaves and not preformatted:
81             # Note: at this point leaf.prefix should be empty except for
82             # imports, for which we only preserve newlines.
83             leaf.prefix += whitespace(
84                 leaf,
85                 complex_subscript=self.is_complex_subscript(leaf),
86                 mode=self.mode,
87             )
88         if self.inside_brackets or not preformatted or track_bracket:
89             self.bracket_tracker.mark(leaf)
90             if self.mode.magic_trailing_comma:
91                 if self.has_magic_trailing_comma(leaf):
92                     self.magic_trailing_comma = leaf
93             elif self.has_magic_trailing_comma(leaf, ensure_removable=True):
94                 self.remove_trailing_comma()
95         if not self.append_comment(leaf):
96             self.leaves.append(leaf)
97
98     def append_safe(self, leaf: Leaf, preformatted: bool = False) -> None:
99         """Like :func:`append()` but disallow invalid standalone comment structure.
100
101         Raises ValueError when any `leaf` is appended after a standalone comment
102         or when a standalone comment is not the first leaf on the line.
103         """
104         if self.bracket_tracker.depth == 0:
105             if self.is_comment:
106                 raise ValueError("cannot append to standalone comments")
107
108             if self.leaves and leaf.type == STANDALONE_COMMENT:
109                 raise ValueError(
110                     "cannot append standalone comments to a populated line"
111                 )
112
113         self.append(leaf, preformatted=preformatted)
114
115     @property
116     def is_comment(self) -> bool:
117         """Is this line a standalone comment?"""
118         return len(self.leaves) == 1 and self.leaves[0].type == STANDALONE_COMMENT
119
120     @property
121     def is_decorator(self) -> bool:
122         """Is this line a decorator?"""
123         return bool(self) and self.leaves[0].type == token.AT
124
125     @property
126     def is_import(self) -> bool:
127         """Is this an import line?"""
128         return bool(self) and is_import(self.leaves[0])
129
130     @property
131     def is_with_or_async_with_stmt(self) -> bool:
132         """Is this a with_stmt line?"""
133         return bool(self) and is_with_or_async_with_stmt(self.leaves[0])
134
135     @property
136     def is_class(self) -> bool:
137         """Is this line a class definition?"""
138         return (
139             bool(self)
140             and self.leaves[0].type == token.NAME
141             and self.leaves[0].value == "class"
142         )
143
144     @property
145     def is_stub_class(self) -> bool:
146         """Is this line a class definition with a body consisting only of "..."?"""
147         return self.is_class and self.leaves[-3:] == [
148             Leaf(token.DOT, ".") for _ in range(3)
149         ]
150
151     @property
152     def is_def(self) -> bool:
153         """Is this a function definition? (Also returns True for async defs.)"""
154         try:
155             first_leaf = self.leaves[0]
156         except IndexError:
157             return False
158
159         try:
160             second_leaf: Optional[Leaf] = self.leaves[1]
161         except IndexError:
162             second_leaf = None
163         return (first_leaf.type == token.NAME and first_leaf.value == "def") or (
164             first_leaf.type == token.ASYNC
165             and second_leaf is not None
166             and second_leaf.type == token.NAME
167             and second_leaf.value == "def"
168         )
169
170     @property
171     def is_stub_def(self) -> bool:
172         """Is this line a function definition with a body consisting only of "..."?"""
173         return self.is_def and self.leaves[-4:] == [Leaf(token.COLON, ":")] + [
174             Leaf(token.DOT, ".") for _ in range(3)
175         ]
176
177     @property
178     def is_class_paren_empty(self) -> bool:
179         """Is this a class with no base classes but using parentheses?
180
181         Those are unnecessary and should be removed.
182         """
183         return (
184             bool(self)
185             and len(self.leaves) == 4
186             and self.is_class
187             and self.leaves[2].type == token.LPAR
188             and self.leaves[2].value == "("
189             and self.leaves[3].type == token.RPAR
190             and self.leaves[3].value == ")"
191         )
192
193     @property
194     def is_triple_quoted_string(self) -> bool:
195         """Is the line a triple quoted string?"""
196         if not self or self.leaves[0].type != token.STRING:
197             return False
198         value = self.leaves[0].value
199         if value.startswith(('"""', "'''")):
200             return True
201         if Preview.accept_raw_docstrings in self.mode and value.startswith(
202             ("r'''", 'r"""', "R'''", 'R"""')
203         ):
204             return True
205         return False
206
207     @property
208     def opens_block(self) -> bool:
209         """Does this line open a new level of indentation."""
210         if len(self.leaves) == 0:
211             return False
212         return self.leaves[-1].type == token.COLON
213
214     def is_fmt_pass_converted(
215         self, *, first_leaf_matches: Optional[Callable[[Leaf], bool]] = None
216     ) -> bool:
217         """Is this line converted from fmt off/skip code?
218
219         If first_leaf_matches is not None, it only returns True if the first
220         leaf of converted code matches.
221         """
222         if len(self.leaves) != 1:
223             return False
224         leaf = self.leaves[0]
225         if (
226             leaf.type != STANDALONE_COMMENT
227             or leaf.fmt_pass_converted_first_leaf is None
228         ):
229             return False
230         return first_leaf_matches is None or first_leaf_matches(
231             leaf.fmt_pass_converted_first_leaf
232         )
233
234     def contains_standalone_comments(self, depth_limit: int = sys.maxsize) -> bool:
235         """If so, needs to be split before emitting."""
236         for leaf in self.leaves:
237             if leaf.type == STANDALONE_COMMENT and leaf.bracket_depth <= depth_limit:
238                 return True
239
240         return False
241
242     def contains_implicit_multiline_string_with_comments(self) -> bool:
243         """Chck if we have an implicit multiline string with comments on the line"""
244         for leaf_type, leaf_group_iterator in itertools.groupby(
245             self.leaves, lambda leaf: leaf.type
246         ):
247             if leaf_type != token.STRING:
248                 continue
249             leaf_list = list(leaf_group_iterator)
250             if len(leaf_list) == 1:
251                 continue
252             for leaf in leaf_list:
253                 if self.comments_after(leaf):
254                     return True
255         return False
256
257     def contains_uncollapsable_type_comments(self) -> bool:
258         ignored_ids = set()
259         try:
260             last_leaf = self.leaves[-1]
261             ignored_ids.add(id(last_leaf))
262             if last_leaf.type == token.COMMA or (
263                 last_leaf.type == token.RPAR and not last_leaf.value
264             ):
265                 # When trailing commas or optional parens are inserted by Black for
266                 # consistency, comments after the previous last element are not moved
267                 # (they don't have to, rendering will still be correct).  So we ignore
268                 # trailing commas and invisible.
269                 last_leaf = self.leaves[-2]
270                 ignored_ids.add(id(last_leaf))
271         except IndexError:
272             return False
273
274         # A type comment is uncollapsable if it is attached to a leaf
275         # that isn't at the end of the line (since that could cause it
276         # to get associated to a different argument) or if there are
277         # comments before it (since that could cause it to get hidden
278         # behind a comment.
279         comment_seen = False
280         for leaf_id, comments in self.comments.items():
281             for comment in comments:
282                 if is_type_comment(comment):
283                     if comment_seen or (
284                         not is_type_ignore_comment(comment)
285                         and leaf_id not in ignored_ids
286                     ):
287                         return True
288
289                 comment_seen = True
290
291         return False
292
293     def contains_unsplittable_type_ignore(self) -> bool:
294         if not self.leaves:
295             return False
296
297         # If a 'type: ignore' is attached to the end of a line, we
298         # can't split the line, because we can't know which of the
299         # subexpressions the ignore was meant to apply to.
300         #
301         # We only want this to apply to actual physical lines from the
302         # original source, though: we don't want the presence of a
303         # 'type: ignore' at the end of a multiline expression to
304         # justify pushing it all onto one line. Thus we
305         # (unfortunately) need to check the actual source lines and
306         # only report an unsplittable 'type: ignore' if this line was
307         # one line in the original code.
308
309         # Grab the first and last line numbers, skipping generated leaves
310         first_line = next((leaf.lineno for leaf in self.leaves if leaf.lineno != 0), 0)
311         last_line = next(
312             (leaf.lineno for leaf in reversed(self.leaves) if leaf.lineno != 0), 0
313         )
314
315         if first_line == last_line:
316             # We look at the last two leaves since a comma or an
317             # invisible paren could have been added at the end of the
318             # line.
319             for node in self.leaves[-2:]:
320                 for comment in self.comments.get(id(node), []):
321                     if is_type_ignore_comment(comment):
322                         return True
323
324         return False
325
326     def contains_multiline_strings(self) -> bool:
327         return any(is_multiline_string(leaf) for leaf in self.leaves)
328
329     def has_magic_trailing_comma(
330         self, closing: Leaf, ensure_removable: bool = False
331     ) -> bool:
332         """Return True if we have a magic trailing comma, that is when:
333         - there's a trailing comma here
334         - it's not a one-tuple
335         - it's not a single-element subscript
336         Additionally, if ensure_removable:
337         - it's not from square bracket indexing
338         (specifically, single-element square bracket indexing)
339         """
340         if not (
341             closing.type in CLOSING_BRACKETS
342             and self.leaves
343             and self.leaves[-1].type == token.COMMA
344         ):
345             return False
346
347         if closing.type == token.RBRACE:
348             return True
349
350         if closing.type == token.RSQB:
351             if (
352                 closing.parent
353                 and closing.parent.type == syms.trailer
354                 and closing.opening_bracket
355                 and is_one_sequence_between(
356                     closing.opening_bracket,
357                     closing,
358                     self.leaves,
359                     brackets=(token.LSQB, token.RSQB),
360                 )
361             ):
362                 return False
363
364             if not ensure_removable:
365                 return True
366
367             comma = self.leaves[-1]
368             if comma.parent is None:
369                 return False
370             return (
371                 comma.parent.type != syms.subscriptlist
372                 or closing.opening_bracket is None
373                 or not is_one_sequence_between(
374                     closing.opening_bracket,
375                     closing,
376                     self.leaves,
377                     brackets=(token.LSQB, token.RSQB),
378                 )
379             )
380
381         if self.is_import:
382             return True
383
384         if closing.opening_bracket is not None and not is_one_sequence_between(
385             closing.opening_bracket, closing, self.leaves
386         ):
387             return True
388
389         return False
390
391     def append_comment(self, comment: Leaf) -> bool:
392         """Add an inline or standalone comment to the line."""
393         if (
394             comment.type == STANDALONE_COMMENT
395             and self.bracket_tracker.any_open_brackets()
396         ):
397             comment.prefix = ""
398             return False
399
400         if comment.type != token.COMMENT:
401             return False
402
403         if not self.leaves:
404             comment.type = STANDALONE_COMMENT
405             comment.prefix = ""
406             return False
407
408         last_leaf = self.leaves[-1]
409         if (
410             last_leaf.type == token.RPAR
411             and not last_leaf.value
412             and last_leaf.parent
413             and len(list(last_leaf.parent.leaves())) <= 3
414             and not is_type_comment(comment)
415         ):
416             # Comments on an optional parens wrapping a single leaf should belong to
417             # the wrapped node except if it's a type comment. Pinning the comment like
418             # this avoids unstable formatting caused by comment migration.
419             if len(self.leaves) < 2:
420                 comment.type = STANDALONE_COMMENT
421                 comment.prefix = ""
422                 return False
423
424             last_leaf = self.leaves[-2]
425         self.comments.setdefault(id(last_leaf), []).append(comment)
426         return True
427
428     def comments_after(self, leaf: Leaf) -> List[Leaf]:
429         """Generate comments that should appear directly after `leaf`."""
430         return self.comments.get(id(leaf), [])
431
432     def remove_trailing_comma(self) -> None:
433         """Remove the trailing comma and moves the comments attached to it."""
434         trailing_comma = self.leaves.pop()
435         trailing_comma_comments = self.comments.pop(id(trailing_comma), [])
436         self.comments.setdefault(id(self.leaves[-1]), []).extend(
437             trailing_comma_comments
438         )
439
440     def is_complex_subscript(self, leaf: Leaf) -> bool:
441         """Return True iff `leaf` is part of a slice with non-trivial exprs."""
442         open_lsqb = self.bracket_tracker.get_open_lsqb()
443         if open_lsqb is None:
444             return False
445
446         subscript_start = open_lsqb.next_sibling
447
448         if isinstance(subscript_start, Node):
449             if subscript_start.type == syms.listmaker:
450                 return False
451
452             if subscript_start.type == syms.subscriptlist:
453                 subscript_start = child_towards(subscript_start, leaf)
454         return subscript_start is not None and any(
455             n.type in TEST_DESCENDANTS for n in subscript_start.pre_order()
456         )
457
458     def enumerate_with_length(
459         self, reversed: bool = False
460     ) -> Iterator[Tuple[Index, Leaf, int]]:
461         """Return an enumeration of leaves with their length.
462
463         Stops prematurely on multiline strings and standalone comments.
464         """
465         op = cast(
466             Callable[[Sequence[Leaf]], Iterator[Tuple[Index, Leaf]]],
467             enumerate_reversed if reversed else enumerate,
468         )
469         for index, leaf in op(self.leaves):
470             length = len(leaf.prefix) + len(leaf.value)
471             if "\n" in leaf.value:
472                 return  # Multiline strings, we can't continue.
473
474             for comment in self.comments_after(leaf):
475                 length += len(comment.value)
476
477             yield index, leaf, length
478
479     def clone(self) -> "Line":
480         return Line(
481             mode=self.mode,
482             depth=self.depth,
483             inside_brackets=self.inside_brackets,
484             should_split_rhs=self.should_split_rhs,
485             magic_trailing_comma=self.magic_trailing_comma,
486         )
487
488     def __str__(self) -> str:
489         """Render the line."""
490         if not self:
491             return "\n"
492
493         indent = "    " * self.depth
494         leaves = iter(self.leaves)
495         first = next(leaves)
496         res = f"{first.prefix}{indent}{first.value}"
497         for leaf in leaves:
498             res += str(leaf)
499         for comment in itertools.chain.from_iterable(self.comments.values()):
500             res += str(comment)
501
502         return res + "\n"
503
504     def __bool__(self) -> bool:
505         """Return True if the line has leaves or comments."""
506         return bool(self.leaves or self.comments)
507
508
509 @dataclass
510 class RHSResult:
511     """Intermediate split result from a right hand split."""
512
513     head: Line
514     body: Line
515     tail: Line
516     opening_bracket: Leaf
517     closing_bracket: Leaf
518
519
520 @dataclass
521 class LinesBlock:
522     """Class that holds information about a block of formatted lines.
523
524     This is introduced so that the EmptyLineTracker can look behind the standalone
525     comments and adjust their empty lines for class or def lines.
526     """
527
528     mode: Mode
529     previous_block: Optional["LinesBlock"]
530     original_line: Line
531     before: int = 0
532     content_lines: List[str] = field(default_factory=list)
533     after: int = 0
534
535     def all_lines(self) -> List[str]:
536         empty_line = str(Line(mode=self.mode))
537         return (
538             [empty_line * self.before] + self.content_lines + [empty_line * self.after]
539         )
540
541
542 @dataclass
543 class EmptyLineTracker:
544     """Provides a stateful method that returns the number of potential extra
545     empty lines needed before and after the currently processed line.
546
547     Note: this tracker works on lines that haven't been split yet.  It assumes
548     the prefix of the first leaf consists of optional newlines.  Those newlines
549     are consumed by `maybe_empty_lines()` and included in the computation.
550     """
551
552     mode: Mode
553     previous_line: Optional[Line] = None
554     previous_block: Optional[LinesBlock] = None
555     previous_defs: List[Line] = field(default_factory=list)
556     semantic_leading_comment: Optional[LinesBlock] = None
557
558     def maybe_empty_lines(self, current_line: Line) -> LinesBlock:
559         """Return the number of extra empty lines before and after the `current_line`.
560
561         This is for separating `def`, `async def` and `class` with extra empty
562         lines (two on module-level).
563         """
564         before, after = self._maybe_empty_lines(current_line)
565         previous_after = self.previous_block.after if self.previous_block else 0
566         before = (
567             # Black should not insert empty lines at the beginning
568             # of the file
569             0
570             if self.previous_line is None
571             else before - previous_after
572         )
573         if (
574             Preview.module_docstring_newlines in current_line.mode
575             and self.previous_block
576             and self.previous_block.previous_block is None
577             and len(self.previous_block.original_line.leaves) == 1
578             and self.previous_block.original_line.is_triple_quoted_string
579         ):
580             before = 1
581
582         block = LinesBlock(
583             mode=self.mode,
584             previous_block=self.previous_block,
585             original_line=current_line,
586             before=before,
587             after=after,
588         )
589
590         # Maintain the semantic_leading_comment state.
591         if current_line.is_comment:
592             if self.previous_line is None or (
593                 not self.previous_line.is_decorator
594                 # `or before` means this comment already has an empty line before
595                 and (not self.previous_line.is_comment or before)
596                 and (self.semantic_leading_comment is None or before)
597             ):
598                 self.semantic_leading_comment = block
599         # `or before` means this decorator already has an empty line before
600         elif not current_line.is_decorator or before:
601             self.semantic_leading_comment = None
602
603         self.previous_line = current_line
604         self.previous_block = block
605         return block
606
607     def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
608         max_allowed = 1
609         if current_line.depth == 0:
610             max_allowed = 1 if self.mode.is_pyi else 2
611         if current_line.leaves:
612             # Consume the first leaf's extra newlines.
613             first_leaf = current_line.leaves[0]
614             before = first_leaf.prefix.count("\n")
615             before = min(before, max_allowed)
616             first_leaf.prefix = ""
617         else:
618             before = 0
619
620         user_had_newline = bool(before)
621         depth = current_line.depth
622
623         previous_def = None
624         while self.previous_defs and self.previous_defs[-1].depth >= depth:
625             previous_def = self.previous_defs.pop()
626
627         if previous_def is not None:
628             assert self.previous_line is not None
629             if self.mode.is_pyi:
630                 if depth and not current_line.is_def and self.previous_line.is_def:
631                     # Empty lines between attributes and methods should be preserved.
632                     before = 1 if user_had_newline else 0
633                 elif (
634                     Preview.blank_line_after_nested_stub_class in self.mode
635                     and previous_def.is_class
636                     and not previous_def.is_stub_class
637                 ):
638                     before = 1
639                 elif depth:
640                     before = 0
641                 else:
642                     before = 1
643             else:
644                 if depth:
645                     before = 1
646                 elif (
647                     not depth
648                     and previous_def.depth
649                     and current_line.leaves[-1].type == token.COLON
650                     and (
651                         current_line.leaves[0].value
652                         not in ("with", "try", "for", "while", "if", "match")
653                     )
654                 ):
655                     # We shouldn't add two newlines between an indented function and
656                     # a dependent non-indented clause. This is to avoid issues with
657                     # conditional function definitions that are technically top-level
658                     # and therefore get two trailing newlines, but look weird and
659                     # inconsistent when they're followed by elif, else, etc. This is
660                     # worse because these functions only get *one* preceding newline
661                     # already.
662                     before = 1
663                 else:
664                     before = 2
665
666         if current_line.is_decorator or current_line.is_def or current_line.is_class:
667             return self._maybe_empty_lines_for_class_or_def(
668                 current_line, before, user_had_newline
669             )
670
671         if (
672             self.previous_line
673             and self.previous_line.is_import
674             and not current_line.is_import
675             and not current_line.is_fmt_pass_converted(first_leaf_matches=is_import)
676             and depth == self.previous_line.depth
677         ):
678             return (before or 1), 0
679
680         if (
681             self.previous_line
682             and self.previous_line.is_class
683             and current_line.is_triple_quoted_string
684         ):
685             if Preview.no_blank_line_before_class_docstring in current_line.mode:
686                 return 0, 1
687             return before, 1
688
689         if self.previous_line and self.previous_line.opens_block:
690             return 0, 0
691         return before, 0
692
693     def _maybe_empty_lines_for_class_or_def(  # noqa: C901
694         self, current_line: Line, before: int, user_had_newline: bool
695     ) -> Tuple[int, int]:
696         if not current_line.is_decorator:
697             self.previous_defs.append(current_line)
698         if self.previous_line is None:
699             # Don't insert empty lines before the first line in the file.
700             return 0, 0
701
702         if self.previous_line.is_decorator:
703             if self.mode.is_pyi and current_line.is_stub_class:
704                 # Insert an empty line after a decorated stub class
705                 return 0, 1
706
707             return 0, 0
708
709         if self.previous_line.depth < current_line.depth and (
710             self.previous_line.is_class or self.previous_line.is_def
711         ):
712             return 0, 0
713
714         comment_to_add_newlines: Optional[LinesBlock] = None
715         if (
716             self.previous_line.is_comment
717             and self.previous_line.depth == current_line.depth
718             and before == 0
719         ):
720             slc = self.semantic_leading_comment
721             if (
722                 slc is not None
723                 and slc.previous_block is not None
724                 and not slc.previous_block.original_line.is_class
725                 and not slc.previous_block.original_line.opens_block
726                 and slc.before <= 1
727             ):
728                 comment_to_add_newlines = slc
729             else:
730                 return 0, 0
731
732         if self.mode.is_pyi:
733             if current_line.is_class or self.previous_line.is_class:
734                 if self.previous_line.depth < current_line.depth:
735                     newlines = 0
736                 elif self.previous_line.depth > current_line.depth:
737                     newlines = 1
738                 elif current_line.is_stub_class and self.previous_line.is_stub_class:
739                     # No blank line between classes with an empty body
740                     newlines = 0
741                 else:
742                     newlines = 1
743             # Remove case `self.previous_line.depth > current_line.depth` below when
744             # this becomes stable.
745             #
746             # Don't inspect the previous line if it's part of the body of the previous
747             # statement in the same level, we always want a blank line if there's
748             # something with a body preceding.
749             elif (
750                 Preview.blank_line_between_nested_and_def_stub_file in current_line.mode
751                 and self.previous_line.depth > current_line.depth
752             ):
753                 newlines = 1
754             elif (
755                 current_line.is_def or current_line.is_decorator
756             ) and not self.previous_line.is_def:
757                 if current_line.depth:
758                     # In classes empty lines between attributes and methods should
759                     # be preserved.
760                     newlines = min(1, before)
761                 else:
762                     # Blank line between a block of functions (maybe with preceding
763                     # decorators) and a block of non-functions
764                     newlines = 1
765             elif self.previous_line.depth > current_line.depth:
766                 newlines = 1
767             else:
768                 newlines = 0
769         else:
770             newlines = 1 if current_line.depth else 2
771             # If a user has left no space after a dummy implementation, don't insert
772             # new lines. This is useful for instance for @overload or Protocols.
773             if (
774                 Preview.dummy_implementations in self.mode
775                 and self.previous_line.is_stub_def
776                 and not user_had_newline
777             ):
778                 newlines = 0
779         if comment_to_add_newlines is not None:
780             previous_block = comment_to_add_newlines.previous_block
781             if previous_block is not None:
782                 comment_to_add_newlines.before = (
783                     max(comment_to_add_newlines.before, newlines) - previous_block.after
784                 )
785                 newlines = 0
786         return newlines, 0
787
788
789 def enumerate_reversed(sequence: Sequence[T]) -> Iterator[Tuple[Index, T]]:
790     """Like `reversed(enumerate(sequence))` if that were possible."""
791     index = len(sequence) - 1
792     for element in reversed(sequence):
793         yield (index, element)
794         index -= 1
795
796
797 def append_leaves(
798     new_line: Line, old_line: Line, leaves: List[Leaf], preformatted: bool = False
799 ) -> None:
800     """
801     Append leaves (taken from @old_line) to @new_line, making sure to fix the
802     underlying Node structure where appropriate.
803
804     All of the leaves in @leaves are duplicated. The duplicates are then
805     appended to @new_line and used to replace their originals in the underlying
806     Node structure. Any comments attached to the old leaves are reattached to
807     the new leaves.
808
809     Pre-conditions:
810         set(@leaves) is a subset of set(@old_line.leaves).
811     """
812     for old_leaf in leaves:
813         new_leaf = Leaf(old_leaf.type, old_leaf.value)
814         replace_child(old_leaf, new_leaf)
815         new_line.append(new_leaf, preformatted=preformatted)
816
817         for comment_leaf in old_line.comments_after(old_leaf):
818             new_line.append(comment_leaf, preformatted=True)
819
820
821 def is_line_short_enough(  # noqa: C901
822     line: Line, *, mode: Mode, line_str: str = ""
823 ) -> bool:
824     """For non-multiline strings, return True if `line` is no longer than `line_length`.
825     For multiline strings, looks at the context around `line` to determine
826     if it should be inlined or split up.
827     Uses the provided `line_str` rendering, if any, otherwise computes a new one.
828     """
829     if not line_str:
830         line_str = line_to_string(line)
831
832     width = str_width if mode.preview else len
833
834     if Preview.multiline_string_handling not in mode:
835         return (
836             width(line_str) <= mode.line_length
837             and "\n" not in line_str  # multiline strings
838             and not line.contains_standalone_comments()
839         )
840
841     if line.contains_standalone_comments():
842         return False
843     if "\n" not in line_str:
844         # No multiline strings (MLS) present
845         return width(line_str) <= mode.line_length
846
847     first, *_, last = line_str.split("\n")
848     if width(first) > mode.line_length or width(last) > mode.line_length:
849         return False
850
851     # Traverse the AST to examine the context of the multiline string (MLS),
852     # tracking aspects such as depth and comma existence,
853     # to determine whether to split the MLS or keep it together.
854     # Depth (which is based on the existing bracket_depth concept)
855     # is needed to determine nesting level of the MLS.
856     # Includes special case for trailing commas.
857     commas: List[int] = []  # tracks number of commas per depth level
858     multiline_string: Optional[Leaf] = None
859     # store the leaves that contain parts of the MLS
860     multiline_string_contexts: List[LN] = []
861
862     max_level_to_update: Union[int, float] = math.inf  # track the depth of the MLS
863     for i, leaf in enumerate(line.leaves):
864         if max_level_to_update == math.inf:
865             had_comma: Optional[int] = None
866             if leaf.bracket_depth + 1 > len(commas):
867                 commas.append(0)
868             elif leaf.bracket_depth + 1 < len(commas):
869                 had_comma = commas.pop()
870             if (
871                 had_comma is not None
872                 and multiline_string is not None
873                 and multiline_string.bracket_depth == leaf.bracket_depth + 1
874             ):
875                 # Have left the level with the MLS, stop tracking commas
876                 max_level_to_update = leaf.bracket_depth
877                 if had_comma > 0:
878                     # MLS was in parens with at least one comma - force split
879                     return False
880
881         if leaf.bracket_depth <= max_level_to_update and leaf.type == token.COMMA:
882             # Ignore non-nested trailing comma
883             # directly after MLS/MLS-containing expression
884             ignore_ctxs: List[Optional[LN]] = [None]
885             ignore_ctxs += multiline_string_contexts
886             if not (leaf.prev_sibling in ignore_ctxs and i == len(line.leaves) - 1):
887                 commas[leaf.bracket_depth] += 1
888         if max_level_to_update != math.inf:
889             max_level_to_update = min(max_level_to_update, leaf.bracket_depth)
890
891         if is_multiline_string(leaf):
892             if len(multiline_string_contexts) > 0:
893                 # >1 multiline string cannot fit on a single line - force split
894                 return False
895             multiline_string = leaf
896             ctx: LN = leaf
897             # fetch the leaf components of the MLS in the AST
898             while str(ctx) in line_str:
899                 multiline_string_contexts.append(ctx)
900                 if ctx.parent is None:
901                     break
902                 ctx = ctx.parent
903
904     # May not have a triple-quoted multiline string at all,
905     # in case of a regular string with embedded newlines and line continuations
906     if len(multiline_string_contexts) == 0:
907         return True
908
909     return all(val == 0 for val in commas)
910
911
912 def can_be_split(line: Line) -> bool:
913     """Return False if the line cannot be split *for sure*.
914
915     This is not an exhaustive search but a cheap heuristic that we can use to
916     avoid some unfortunate formattings (mostly around wrapping unsplittable code
917     in unnecessary parentheses).
918     """
919     leaves = line.leaves
920     if len(leaves) < 2:
921         return False
922
923     if leaves[0].type == token.STRING and leaves[1].type == token.DOT:
924         call_count = 0
925         dot_count = 0
926         next = leaves[-1]
927         for leaf in leaves[-2::-1]:
928             if leaf.type in OPENING_BRACKETS:
929                 if next.type not in CLOSING_BRACKETS:
930                     return False
931
932                 call_count += 1
933             elif leaf.type == token.DOT:
934                 dot_count += 1
935             elif leaf.type == token.NAME:
936                 if not (next.type == token.DOT or next.type in OPENING_BRACKETS):
937                     return False
938
939             elif leaf.type not in CLOSING_BRACKETS:
940                 return False
941
942             if dot_count > 1 and call_count > 1:
943                 return False
944
945     return True
946
947
948 def can_omit_invisible_parens(
949     rhs: RHSResult,
950     line_length: int,
951 ) -> bool:
952     """Does `rhs.body` have a shape safe to reformat without optional parens around it?
953
954     Returns True for only a subset of potentially nice looking formattings but
955     the point is to not return false positives that end up producing lines that
956     are too long.
957     """
958     line = rhs.body
959     bt = line.bracket_tracker
960     if not bt.delimiters:
961         # Without delimiters the optional parentheses are useless.
962         return True
963
964     max_priority = bt.max_delimiter_priority()
965     delimiter_count = bt.delimiter_count_with_priority(max_priority)
966     if delimiter_count > 1:
967         # With more than one delimiter of a kind the optional parentheses read better.
968         return False
969
970     if delimiter_count == 1:
971         if (
972             Preview.wrap_multiple_context_managers_in_parens in line.mode
973             and max_priority == COMMA_PRIORITY
974             and rhs.head.is_with_or_async_with_stmt
975         ):
976             # For two context manager with statements, the optional parentheses read
977             # better. In this case, `rhs.body` is the context managers part of
978             # the with statement. `rhs.head` is the `with (` part on the previous
979             # line.
980             return False
981         # Otherwise it may also read better, but we don't do it today and requires
982         # careful considerations for all possible cases. See
983         # https://github.com/psf/black/issues/2156.
984
985     if max_priority == DOT_PRIORITY:
986         # A single stranded method call doesn't require optional parentheses.
987         return True
988
989     assert len(line.leaves) >= 2, "Stranded delimiter"
990
991     # With a single delimiter, omit if the expression starts or ends with
992     # a bracket.
993     first = line.leaves[0]
994     second = line.leaves[1]
995     if first.type in OPENING_BRACKETS and second.type not in CLOSING_BRACKETS:
996         if _can_omit_opening_paren(line, first=first, line_length=line_length):
997             return True
998
999         # Note: we are not returning False here because a line might have *both*
1000         # a leading opening bracket and a trailing closing bracket.  If the
1001         # opening bracket doesn't match our rule, maybe the closing will.
1002
1003     penultimate = line.leaves[-2]
1004     last = line.leaves[-1]
1005
1006     if (
1007         last.type == token.RPAR
1008         or last.type == token.RBRACE
1009         or (
1010             # don't use indexing for omitting optional parentheses;
1011             # it looks weird
1012             last.type == token.RSQB
1013             and last.parent
1014             and last.parent.type != syms.trailer
1015         )
1016     ):
1017         if penultimate.type in OPENING_BRACKETS:
1018             # Empty brackets don't help.
1019             return False
1020
1021         if is_multiline_string(first):
1022             # Additional wrapping of a multiline string in this situation is
1023             # unnecessary.
1024             return True
1025
1026         if _can_omit_closing_paren(line, last=last, line_length=line_length):
1027             return True
1028
1029     return False
1030
1031
1032 def _can_omit_opening_paren(line: Line, *, first: Leaf, line_length: int) -> bool:
1033     """See `can_omit_invisible_parens`."""
1034     remainder = False
1035     length = 4 * line.depth
1036     _index = -1
1037     for _index, leaf, leaf_length in line.enumerate_with_length():
1038         if leaf.type in CLOSING_BRACKETS and leaf.opening_bracket is first:
1039             remainder = True
1040         if remainder:
1041             length += leaf_length
1042             if length > line_length:
1043                 break
1044
1045             if leaf.type in OPENING_BRACKETS:
1046                 # There are brackets we can further split on.
1047                 remainder = False
1048
1049     else:
1050         # checked the entire string and line length wasn't exceeded
1051         if len(line.leaves) == _index + 1:
1052             return True
1053
1054     return False
1055
1056
1057 def _can_omit_closing_paren(line: Line, *, last: Leaf, line_length: int) -> bool:
1058     """See `can_omit_invisible_parens`."""
1059     length = 4 * line.depth
1060     seen_other_brackets = False
1061     for _index, leaf, leaf_length in line.enumerate_with_length():
1062         length += leaf_length
1063         if leaf is last.opening_bracket:
1064             if seen_other_brackets or length <= line_length:
1065                 return True
1066
1067         elif leaf.type in OPENING_BRACKETS:
1068             # There are brackets we can further split on.
1069             seen_other_brackets = True
1070
1071     return False
1072
1073
1074 def line_to_string(line: Line) -> str:
1075     """Returns the string representation of @line.
1076
1077     WARNING: This is known to be computationally expensive.
1078     """
1079     return str(line).strip("\n")