Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/black/lines.py: 18%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import itertools
2import math
3from collections.abc import Callable, Iterator, Sequence
4from dataclasses import dataclass, field
5from typing import NamedTuple, Optional, TypeVar, Union, cast
7from black.brackets import COMMA_PRIORITY, DOT_PRIORITY, BracketTracker
8from black.comments import FMT_ON, contains_fmt_directive
9from black.mode import Mode, Preview
10from black.nodes import (
11 BRACKETS,
12 CLOSING_BRACKETS,
13 OPENING_BRACKETS,
14 STANDALONE_COMMENT,
15 TEST_DESCENDANTS,
16 child_towards,
17 first_leaf,
18 is_docstring,
19 is_import,
20 is_multiline_string,
21 is_one_sequence_between,
22 is_one_tuple,
23 is_type_comment,
24 is_type_ignore_comment,
25 is_with_or_async_with_stmt,
26 last_leaf,
27 make_simple_prefix,
28 replace_child,
29 syms,
30 whitespace,
31)
32from black.strings import str_width
33from blib2to3.pgen2 import token
34from blib2to3.pytree import Leaf, Node
36# types
37T = TypeVar("T")
38Index = int
39LeafID = int
40LN = Union[Leaf, Node]
43@dataclass
44class Line:
45 """Holds leaves and comments. Can be printed with `str(line)`."""
47 mode: Mode = field(repr=False)
48 depth: int = 0
49 leaves: list[Leaf] = field(default_factory=list)
50 # keys ordered like `leaves`
51 comments: dict[LeafID, list[Leaf]] = field(default_factory=dict)
52 bracket_tracker: BracketTracker = field(default_factory=BracketTracker)
53 inside_brackets: bool = False
54 should_split_rhs: bool = False
55 magic_trailing_comma: Leaf | None = None
56 _complex_subscript_cache: dict[LeafID, bool] = field(
57 default_factory=dict, repr=False
58 )
60 def append(
61 self, leaf: Leaf, preformatted: bool = False, track_bracket: bool = False
62 ) -> None:
63 """Add a new `leaf` to the end of the line.
65 Unless `preformatted` is True, the `leaf` will receive a new consistent
66 whitespace prefix and metadata applied by :class:`BracketTracker`.
67 Trailing commas are maybe removed, unpacked for loop variables are
68 demoted from being delimiters.
70 Inline comments are put aside.
71 """
72 has_value = (
73 leaf.type in BRACKETS
74 # empty fstring and tstring middles must not be truncated
75 or leaf.type in (token.FSTRING_MIDDLE, token.TSTRING_MIDDLE)
76 or bool(leaf.value.strip())
77 )
78 if not has_value:
79 return
81 if leaf.type == token.COLON and self.is_class_paren_empty:
82 del self.leaves[-2:]
83 if self.leaves and not preformatted:
84 # Note: at this point leaf.prefix should be empty except for
85 # imports, for which we only preserve newlines.
86 leaf.prefix += whitespace(
87 leaf,
88 complex_subscript=self.is_complex_subscript(leaf),
89 mode=self.mode,
90 )
91 if self.inside_brackets or not preformatted or track_bracket:
92 self.bracket_tracker.mark(leaf)
93 if self.mode.magic_trailing_comma:
94 if self.has_magic_trailing_comma(leaf):
95 self.magic_trailing_comma = leaf
96 elif self.has_magic_trailing_comma(leaf) and not (
97 # A one-element tuple's trailing comma is syntactically required,
98 # not magic, so it must never be removed. This is normally caught
99 # by has_magic_trailing_comma, but that check misses the tuple
100 # when its opening bracket was split onto an earlier line (for
101 # example by a standalone comment inside the tuple), so verify
102 # against the tree here before dropping the comma.
103 leaf.parent is not None
104 and is_one_tuple(leaf.parent)
105 ):
106 self.remove_trailing_comma()
107 if not self.append_comment(leaf):
108 self.leaves.append(leaf)
110 def append_safe(self, leaf: Leaf, preformatted: bool = False) -> None:
111 """Like :func:`append()` but disallow invalid standalone comment structure.
113 Raises ValueError when any `leaf` is appended after a standalone comment
114 or when a standalone comment is not the first leaf on the line.
115 """
116 if (
117 self.bracket_tracker.depth == 0
118 or self.bracket_tracker.any_open_for_or_lambda()
119 ):
120 if self.is_comment:
121 raise ValueError("cannot append to standalone comments")
123 if self.leaves and leaf.type == STANDALONE_COMMENT:
124 raise ValueError(
125 "cannot append standalone comments to a populated line"
126 )
128 self.append(leaf, preformatted=preformatted)
130 @property
131 def is_comment(self) -> bool:
132 """Is this line a standalone comment?"""
133 return len(self.leaves) == 1 and self.leaves[0].type == STANDALONE_COMMENT
135 @property
136 def is_decorator(self) -> bool:
137 """Is this line a decorator?"""
138 return bool(self) and self.leaves[0].type == token.AT
140 @property
141 def is_import(self) -> bool:
142 """Is this an import line?"""
143 return bool(self) and is_import(self.leaves[0])
145 @property
146 def is_with_or_async_with_stmt(self) -> bool:
147 """Is this a with_stmt line?"""
148 return bool(self) and is_with_or_async_with_stmt(self.leaves[0])
150 @property
151 def is_class(self) -> bool:
152 """Is this line a class definition?"""
153 return (
154 bool(self)
155 and self.leaves[0].type == token.NAME
156 and self.leaves[0].value == "class"
157 )
159 @property
160 def is_stub_class(self) -> bool:
161 """Is this line a class definition with a body consisting only of "..."?"""
162 return self.is_class and self.leaves[-3:] == [
163 Leaf(token.DOT, ".") for _ in range(3)
164 ]
166 @property
167 def is_def(self) -> bool:
168 """Is this a function definition? (Also returns True for async defs.)"""
169 try:
170 first_leaf = self.leaves[0]
171 except IndexError:
172 return False
174 try:
175 second_leaf: Leaf | None = self.leaves[1]
176 except IndexError:
177 second_leaf = None
178 return (first_leaf.type == token.NAME and first_leaf.value == "def") or (
179 first_leaf.type == token.ASYNC
180 and second_leaf is not None
181 and second_leaf.type == token.NAME
182 and second_leaf.value == "def"
183 )
185 @property
186 def is_stub_def(self) -> bool:
187 """Is this line a function definition with a body consisting only of "..."?"""
188 return self.is_def and self.leaves[-4:] == [Leaf(token.COLON, ":")] + [
189 Leaf(token.DOT, ".") for _ in range(3)
190 ]
192 @property
193 def is_class_paren_empty(self) -> bool:
194 """Is this a class with no base classes but using parentheses?
196 Those are unnecessary and should be removed.
197 """
198 return (
199 bool(self)
200 and len(self.leaves) == 4
201 and self.is_class
202 and self.leaves[2].type == token.LPAR
203 and self.leaves[2].value == "("
204 and self.leaves[3].type == token.RPAR
205 and self.leaves[3].value == ")"
206 )
208 @property
209 def _is_triple_quoted_string(self) -> bool:
210 """Is the line a triple quoted string?"""
211 if not self or self.leaves[0].type != token.STRING:
212 return False
213 value = self.leaves[0].value
214 if value.startswith(('"""', "'''")):
215 return True
216 if value.startswith(("r'''", 'r"""', "R'''", 'R"""')):
217 return True
218 return False
220 @property
221 def is_docstring(self) -> bool:
222 """Is the line a docstring?"""
223 return bool(self) and is_docstring(self.leaves[0])
225 @property
226 def is_chained_assignment(self) -> bool:
227 """Is the line a chained assignment"""
228 return [leaf.type for leaf in self.leaves].count(token.EQUAL) > 1
230 @property
231 def opens_block(self) -> bool:
232 """Does this line open a new level of indentation."""
233 if len(self.leaves) == 0:
234 return False
235 return self.leaves[-1].type == token.COLON
237 def is_fmt_pass_converted(
238 self, *, first_leaf_matches: Callable[[Leaf], bool] | None = None
239 ) -> bool:
240 """Is this line converted from fmt off/skip code?
242 If first_leaf_matches is not None, it only returns True if the first
243 leaf of converted code matches.
244 """
245 if len(self.leaves) != 1:
246 return False
247 leaf = self.leaves[0]
248 if (
249 leaf.type != STANDALONE_COMMENT
250 or leaf.fmt_pass_converted_first_leaf is None
251 ):
252 return False
253 return first_leaf_matches is None or first_leaf_matches(
254 leaf.fmt_pass_converted_first_leaf
255 )
257 def contains_standalone_comments(self) -> bool:
258 """If so, needs to be split before emitting."""
259 for leaf in self.leaves:
260 if leaf.type == STANDALONE_COMMENT:
261 return True
263 return False
265 def contains_implicit_multiline_string_with_comments(self) -> bool:
266 """Check if we have an implicit multiline string with comments on the line"""
267 for leaf_type, leaf_group_iterator in itertools.groupby(
268 self.leaves, lambda leaf: leaf.type
269 ):
270 if leaf_type != token.STRING:
271 continue
272 leaf_list = list(leaf_group_iterator)
273 if len(leaf_list) == 1:
274 continue
275 for leaf in leaf_list:
276 if self.comments_after(leaf):
277 return True
278 return False
280 def contains_uncollapsable_type_comments(self) -> bool:
281 ignored_ids = set()
282 try:
283 last_leaf = self.leaves[-1]
284 ignored_ids.add(id(last_leaf))
285 if last_leaf.type == token.COMMA or (
286 last_leaf.type == token.RPAR and not last_leaf.value
287 ):
288 # When trailing commas or optional parens are inserted by Black for
289 # consistency, comments after the previous last element are not moved
290 # (they don't have to, rendering will still be correct). So we ignore
291 # trailing commas and invisible.
292 last_leaf = self.leaves[-2]
293 ignored_ids.add(id(last_leaf))
294 except IndexError:
295 return False
297 # A type comment is uncollapsable if it is attached to a leaf
298 # that isn't at the end of the line (since that could cause it
299 # to get associated to a different argument) or if there are
300 # comments before it (since that could cause it to get hidden
301 # behind a comment.
302 comment_seen = False
303 for leaf_id, comments in self.comments.items():
304 for comment in comments:
305 if is_type_comment(comment, mode=self.mode):
306 if comment_seen or (
307 not is_type_ignore_comment(comment, mode=self.mode)
308 and leaf_id not in ignored_ids
309 ):
310 return True
312 comment_seen = True
314 return False
316 def contains_unsplittable_type_ignore(self) -> bool:
317 if not self.leaves:
318 return False
320 # If a 'type: ignore' is attached to the end of a line, we
321 # can't split the line, because we can't know which of the
322 # subexpressions the ignore was meant to apply to.
323 #
324 # We only want this to apply to actual physical lines from the
325 # original source, though: we don't want the presence of a
326 # 'type: ignore' at the end of a multiline expression to
327 # justify pushing it all onto one line. Thus we
328 # (unfortunately) need to check the actual source lines and
329 # only report an unsplittable 'type: ignore' if this line was
330 # one line in the original code.
332 # Grab the first and last line numbers, skipping generated leaves
333 first_line = next((leaf.lineno for leaf in self.leaves if leaf.lineno != 0), 0)
334 last_line = next(
335 (leaf.lineno for leaf in reversed(self.leaves) if leaf.lineno != 0), 0
336 )
338 if first_line == last_line:
339 # We look at the last two leaves since a comma or an
340 # invisible paren could have been added at the end of the
341 # line.
342 for node in self.leaves[-2:]:
343 for comment in self.comments.get(id(node), []):
344 if is_type_ignore_comment(comment, mode=self.mode):
345 return True
347 return False
349 def contains_multiline_strings(self) -> bool:
350 return any(is_multiline_string(leaf) for leaf in self.leaves)
352 def has_magic_trailing_comma(self, closing: Leaf) -> bool:
353 """Return True if we have a magic trailing comma, that is when:
354 - there's a trailing comma here
355 - it's not from single-element square bracket indexing
356 - it's not a one-tuple
357 """
358 if not (
359 closing.type in CLOSING_BRACKETS
360 and self.leaves
361 and self.leaves[-1].type == token.COMMA
362 ):
363 return False
365 if closing.type == token.RBRACE:
366 return True
368 if closing.type == token.RSQB:
369 if (
370 closing.parent is not None
371 and closing.parent.type == syms.trailer
372 and closing.opening_bracket is not None
373 and is_one_sequence_between(
374 closing.opening_bracket,
375 closing,
376 self.leaves,
377 brackets=(token.LSQB, token.RSQB),
378 )
379 ):
380 assert closing.prev_sibling is not None
381 assert closing.prev_sibling.type == syms.subscriptlist
382 return False
384 return True
386 if self.is_import:
387 return True
389 if closing.opening_bracket is not None and not is_one_sequence_between(
390 closing.opening_bracket, closing, self.leaves
391 ):
392 return True
394 return False
396 def append_comment(self, comment: Leaf) -> bool:
397 """Add an inline or standalone comment to the line."""
398 if (
399 comment.type == STANDALONE_COMMENT
400 and self.bracket_tracker.any_open_brackets()
401 ):
402 comment.prefix = ""
403 return False
405 if comment.type != token.COMMENT:
406 return False
408 if not self.leaves:
409 comment.type = STANDALONE_COMMENT
410 comment.prefix = ""
411 return False
413 last_leaf = self.leaves[-1]
414 if (
415 last_leaf.type == token.RPAR
416 and not last_leaf.value
417 and last_leaf.parent
418 and len(list(last_leaf.parent.leaves())) <= 3
419 and not is_type_comment(comment, mode=self.mode)
420 ):
421 # Comments on an optional parens wrapping a single leaf should belong to
422 # the wrapped node except if it's a type comment. Pinning the comment like
423 # this avoids unstable formatting caused by comment migration.
424 if len(self.leaves) < 2:
425 comment.type = STANDALONE_COMMENT
426 comment.prefix = ""
427 return False
429 last_leaf = self.leaves[-2]
430 self.comments.setdefault(id(last_leaf), []).append(comment)
431 return True
433 def comments_after(self, leaf: Leaf) -> list[Leaf]:
434 """Generate comments that should appear directly after `leaf`."""
435 return self.comments.get(id(leaf), [])
437 def remove_trailing_comma(self) -> None:
438 """Remove the trailing comma and moves the comments attached to it."""
439 trailing_comma = self.leaves.pop()
440 trailing_comma_comments = self.comments.pop(id(trailing_comma), [])
441 self.comments.setdefault(id(self.leaves[-1]), []).extend(
442 trailing_comma_comments
443 )
445 def is_complex_subscript(self, leaf: Leaf) -> bool:
446 """Return True iff `leaf` is part of a slice with non-trivial exprs."""
447 open_lsqb = self.bracket_tracker.get_open_lsqb()
448 if open_lsqb is None:
449 return False
451 subscript_start = open_lsqb.next_sibling
453 if isinstance(subscript_start, Node):
454 if subscript_start.type == syms.listmaker:
455 return False
457 if subscript_start.type == syms.subscriptlist:
458 subscript_start = child_towards(subscript_start, leaf)
460 if subscript_start is None:
461 return False
463 # The pre_order walk only depends on subscript_start, which is stable
464 # while a line is built, so cache it per node. Without this, appending
465 # every leaf of a large bracketed expression that holds no TEST_DESCENDANTS
466 # node (e.g. a long run of implicitly concatenated strings) re-walks the
467 # whole subtree each time, which is quadratic.
468 key = id(subscript_start)
469 cached = self._complex_subscript_cache.get(key)
470 if cached is None:
471 cached = any(
472 n.type in TEST_DESCENDANTS for n in subscript_start.pre_order()
473 )
474 self._complex_subscript_cache[key] = cached
475 return cached
477 def enumerate_with_length(
478 self, is_reversed: bool = False
479 ) -> Iterator[tuple[Index, Leaf, int]]:
480 """Return an enumeration of leaves with their length.
482 Stops prematurely on multiline strings and standalone comments.
483 """
484 op = cast(
485 Callable[[Sequence[Leaf]], Iterator[tuple[Index, Leaf]]],
486 enumerate_reversed if is_reversed else enumerate,
487 )
488 for index, leaf in op(self.leaves):
489 length = len(leaf.prefix) + len(leaf.value)
490 if "\n" in leaf.value:
491 return # Multiline strings, we can't continue.
493 for comment in self.comments_after(leaf):
494 length += len(comment.value)
496 yield index, leaf, length
498 def clone(self) -> "Line":
499 return Line(
500 mode=self.mode,
501 depth=self.depth,
502 inside_brackets=self.inside_brackets,
503 should_split_rhs=self.should_split_rhs,
504 magic_trailing_comma=self.magic_trailing_comma,
505 )
507 def __str__(self) -> str:
508 """Render the line."""
509 if not self:
510 return "\n"
512 indent = " " * self.depth
513 leaves = iter(self.leaves)
514 first = next(leaves)
515 res = f"{first.prefix}{indent}{first.value}"
516 res += "".join(str(leaf) for leaf in leaves)
517 comments_iter = itertools.chain.from_iterable(self.comments.values())
518 comments = [str(comment) for comment in comments_iter]
519 res += "".join(comments)
521 return res + "\n"
523 def __bool__(self) -> bool:
524 """Return True if the line has leaves or comments."""
525 return bool(self.leaves or self.comments)
528@dataclass
529class RHSResult:
530 """Intermediate split result from a right hand split."""
532 head: Line
533 body: Line
534 tail: Line
535 opening_bracket: Leaf
536 closing_bracket: Leaf
539@dataclass
540class LinesBlock:
541 """Class that holds information about a block of formatted lines.
543 This is introduced so that the EmptyLineTracker can look behind the standalone
544 comments and adjust their empty lines for class or def lines.
545 """
547 mode: Mode
548 previous_block: Optional["LinesBlock"]
549 original_line: Line
550 before: int = 0
551 content_lines: list[str] = field(default_factory=list)
552 after: int = 0
553 form_feed: bool = False
555 def all_lines(self) -> list[str]:
556 empty_line = str(Line(mode=self.mode))
557 prefix = make_simple_prefix(self.before, self.form_feed, empty_line)
558 return [prefix] + self.content_lines + [empty_line * self.after]
561_WHITESPACE_TOKENS = (
562 token.NEWLINE,
563 token.NL,
564 token.INDENT,
565 token.DEDENT,
566 token.COMMENT,
567 token.ENDMARKER,
568)
571class _DecoratedFuncInfo(NamedTuple):
572 """Tracks the most recently seen decorated function for overload grouping."""
574 name: str
575 depth: int
576 is_multi: bool
579@dataclass
580class EmptyLineTracker:
581 """Provides a stateful method that returns the number of potential extra
582 empty lines needed before and after the currently processed line.
584 Note: this tracker works on lines that haven't been split yet. It assumes
585 the prefix of the first leaf consists of optional newlines. Those newlines
586 are consumed by `maybe_empty_lines()` and included in the computation.
587 """
589 mode: Mode
590 previous_line: Line | None = None
591 previous_block: LinesBlock | None = None
592 previous_defs: list[Line] = field(default_factory=list)
593 semantic_leading_comment: LinesBlock | None = None
594 _pyi_previous_decorated_func: _DecoratedFuncInfo | None = None
596 @staticmethod
597 def _get_funcdef_name(node: Node | Leaf) -> str | None:
598 """Extract the function name from a funcdef or async_funcdef node."""
599 funcdef: Node | Leaf = node
600 if isinstance(node, Node) and node.type == syms.async_funcdef:
601 for sub in node.children:
602 if sub.type == syms.funcdef:
603 funcdef = sub
604 break
605 if not isinstance(funcdef, Node) or funcdef.type != syms.funcdef:
606 return None
607 # Grammar: funcdef = 'def' NAME parameters ':' ...
608 name_node = funcdef.children[1]
609 assert isinstance(name_node, Leaf)
610 return name_node.value
612 @staticmethod
613 def _decorated_node_has_func_named(node: Node, name: str) -> bool:
614 """Check if a ``decorated`` node contains a function with the given name."""
615 return any(
616 sub.type in (syms.funcdef, syms.async_funcdef)
617 and EmptyLineTracker._get_funcdef_name(sub) == name
618 for sub in node.children
619 )
621 @staticmethod
622 def _find_adjacent_decorated(
623 node: Node | Leaf, *, reverse: bool = False
624 ) -> Node | None:
625 """Walk siblings skipping whitespace tokens, returning the first
626 ``decorated`` node found or ``None``."""
627 sibling = node.prev_sibling if reverse else node.next_sibling
628 while sibling is not None:
629 if sibling.type == syms.decorated:
630 assert isinstance(sibling, Node)
631 return sibling
632 elif sibling.type in _WHITESPACE_TOKENS:
633 sibling = sibling.prev_sibling if reverse else sibling.next_sibling
634 else:
635 return None
636 return None
638 @staticmethod
639 def _get_suite_first_decorated_funcname(suite: Node) -> str | None:
640 """Return the function name of the first decorated function in a suite."""
641 for child in suite.children:
642 if isinstance(child, Node) and child.type == syms.decorated:
643 for sub in child.children:
644 if sub.type in (syms.funcdef, syms.async_funcdef):
645 return EmptyLineTracker._get_funcdef_name(sub)
646 break
647 if child.type not in (token.NEWLINE, token.NL, token.INDENT, token.DEDENT):
648 break
649 return None
651 @staticmethod
652 def _if_stmt_branch_has_func_named(
653 if_stmt: Node, exclude_suite: Node, name: str
654 ) -> bool:
655 """Check if any branch of an ``if_stmt`` (other than *exclude_suite*)
656 contains a decorated function with the given *name*."""
657 for child in if_stmt.children:
658 if not isinstance(child, Node):
659 continue
660 if child.type != syms.suite:
661 continue
662 if child is exclude_suite:
663 continue
664 for stmt in child.children:
665 if not isinstance(stmt, Node):
666 continue
667 if stmt.type != syms.decorated:
668 continue
669 if EmptyLineTracker._decorated_node_has_func_named(stmt, name):
670 return True
671 break
672 return False
674 @staticmethod
675 def _get_def_name(line: Line) -> str | None:
676 """Extract the function name from a line that is a function definition."""
677 if not line.is_def or not line.leaves:
678 return None
679 if line.leaves[0].value == "def":
680 return line.leaves[1].value
681 # async def: leaves = ['async', 'def', NAME, ...]
682 return line.leaves[2].value
684 @staticmethod
685 def _is_line_decorated(line: Line) -> bool:
686 """Check if a def line is part of a decorated statement."""
687 if not line.is_def or not line.leaves:
688 return False
689 return EmptyLineTracker._find_decorated_node(line) is not None
691 @staticmethod
692 def _find_decorated_node(line: Line) -> Node | None:
693 """Walk up from the first leaf of a line to its ``decorated`` node."""
694 if not line.leaves:
695 return None
696 node = line.leaves[0].parent
697 while node is not None:
698 if node.type == syms.decorated:
699 assert isinstance(node, Node)
700 return node
701 if node.type in (syms.suite, syms.file_input):
702 return None
703 node = node.parent
704 return None
706 @staticmethod
707 def _get_decorator_target_name(line: Line) -> str | None:
708 """For a decorator line, extract the name of the function it decorates.
710 Only handles decorated functions, not decorated classes.
711 """
712 if not line.is_decorator:
713 return None
714 decorated = EmptyLineTracker._find_decorated_node(line)
715 if decorated is None:
716 return None
717 for child in decorated.children:
718 if child.type in (syms.funcdef, syms.async_funcdef):
719 return EmptyLineTracker._get_funcdef_name(child)
720 return None
722 @staticmethod
723 def _decorator_decorates_class(line: Line) -> bool:
724 """Check if a decorator line decorates a class definition."""
725 if not line.is_decorator:
726 return False
727 decorated = EmptyLineTracker._find_decorated_node(line)
728 if decorated is None:
729 return False
730 return any(child.type == syms.classdef for child in decorated.children)
732 @staticmethod
733 def _def_is_followed_by_same_name_decorated_func(
734 line: Line, *, include_conditional_blocks: bool = False
735 ) -> bool:
736 """Check if a decorated function is followed by a same-name decorated func.
738 If *include_conditional_blocks* is true, the next decorated function may
739 be inside an adjacent conditional block.
740 """
741 name = EmptyLineTracker._get_def_name(line)
742 decorated = EmptyLineTracker._find_decorated_node(line)
743 if name is None or decorated is None:
744 return False
746 sibling = decorated.next_sibling
747 while sibling is not None and sibling.type in _WHITESPACE_TOKENS:
748 sibling = sibling.next_sibling
750 if sibling is None or not isinstance(sibling, Node):
751 return False
752 if sibling.type == syms.decorated:
753 return EmptyLineTracker._decorated_node_has_func_named(sibling, name)
754 if not include_conditional_blocks or sibling.type != syms.if_stmt:
755 return False
756 for child in sibling.children:
757 if not isinstance(child, Node):
758 continue
759 if child.type != syms.suite:
760 continue
761 first_decorated_funcname = (
762 EmptyLineTracker._get_suite_first_decorated_funcname(child)
763 )
764 return first_decorated_funcname == name
765 return False
767 def _is_in_current_group(self, current_line: Line) -> bool:
768 """Check if current_line belongs to the same overload group being tracked."""
769 prev = self._pyi_previous_decorated_func
770 if prev is None:
771 return False
772 cur_name = (
773 self._get_decorator_target_name(current_line)
774 if current_line.is_decorator
775 else self._get_def_name(current_line)
776 )
777 return (
778 cur_name is not None
779 and cur_name == prev.name
780 and prev.depth == current_line.depth
781 and (current_line.is_decorator or self._is_line_decorated(current_line))
782 )
784 @staticmethod
785 def _decorated_node_starts_group(decorated_node: Node) -> bool:
786 """Check if a `decorated` AST node is the first in a multi-function group.
788 Returns True when the next statement-level sibling is also a decorated
789 function with the same name.
790 """
791 name = None
792 for child in decorated_node.children:
793 if child.type in (syms.funcdef, syms.async_funcdef):
794 name = EmptyLineTracker._get_funcdef_name(child)
795 break
796 if name is None:
797 return False
798 adjacent = EmptyLineTracker._find_adjacent_decorated(decorated_node)
799 return adjacent is not None and EmptyLineTracker._decorated_node_has_func_named(
800 adjacent, name
801 )
803 @staticmethod
804 def _is_start_of_decorated_group(line: Line) -> bool:
805 """Check if a decorator line starts a multi-function group.
807 A multi-function group is 2+ consecutive decorated functions sharing the
808 same name (e.g. @overload groups, @property + setter pairs).
809 """
810 if not line.is_decorator:
811 return False
812 decorated_node = EmptyLineTracker._find_decorated_node(line)
813 if decorated_node is None or decorated_node.parent is None:
814 return False
815 return EmptyLineTracker._decorated_node_starts_group(decorated_node)
817 @staticmethod
818 def _get_block_first_decorated_funcname(line: Line) -> str | None:
819 """Return the function name of the first decorated function in a block.
821 *line* must be a block-opening line (ending with ``:``) such as
822 ``if ...:``. Returns ``None`` when the block doesn't start with a
823 decorated function.
824 """
825 if not line.leaves or line.leaves[-1].type != token.COLON:
826 return None
827 suite = line.leaves[-1].next_sibling
828 if suite is None or not isinstance(suite, Node) or suite.type != syms.suite:
829 return None
830 return EmptyLineTracker._get_suite_first_decorated_funcname(suite)
832 @staticmethod
833 def _block_is_part_of_overload_group(line: Line) -> bool:
834 """Check if a block-opening line contains a decorated function that is
835 part of a larger overload group — either because the ``if_stmt``'s next
836 sibling is a same-name decorated function, or because another branch of
837 the same ``if_stmt`` has one.
838 """
839 func_name = EmptyLineTracker._get_block_first_decorated_funcname(line)
840 if func_name is None:
841 return False
843 suite = line.leaves[-1].next_sibling
844 if suite is None or not isinstance(suite, Node):
845 return False
846 if_stmt = suite.parent
847 if if_stmt is None:
848 return False
850 # Check if the if_stmt's next sibling is a same-name decorated function.
851 adjacent = EmptyLineTracker._find_adjacent_decorated(if_stmt)
852 if adjacent is not None and EmptyLineTracker._decorated_node_has_func_named(
853 adjacent, func_name
854 ):
855 return True
857 # Check other branches (elif/else) of the same if_stmt.
858 return EmptyLineTracker._if_stmt_branch_has_func_named(
859 if_stmt, suite, func_name
860 )
862 @staticmethod
863 def _is_decorator_in_conditional_overload(line: Line) -> bool:
864 """Check if a decorator is inside an if/else block that is part of a
865 broader overload group (a sibling or another branch of the same
866 ``if_stmt`` contains a same-name decorated function)."""
867 name = EmptyLineTracker._get_decorator_target_name(line)
868 if name is None:
869 return False
871 decorated = EmptyLineTracker._find_decorated_node(line)
872 if decorated is None:
873 return False
875 suite = decorated.parent
876 if suite is None or suite.type != syms.suite:
877 return False
879 if_stmt = suite.parent
880 if if_stmt is None or if_stmt.type != syms.if_stmt:
881 return False
883 # Check if_stmt's adjacent siblings for same-name decorated function.
884 for reverse in (True, False):
885 adjacent = EmptyLineTracker._find_adjacent_decorated(
886 if_stmt, reverse=reverse
887 )
888 if (
889 adjacent is not None
890 and EmptyLineTracker._decorated_node_has_func_named(adjacent, name)
891 ):
892 return True
894 # Check other branches of the same if_stmt.
895 return EmptyLineTracker._if_stmt_branch_has_func_named(if_stmt, suite, name)
897 def maybe_empty_lines(self, current_line: Line) -> LinesBlock:
898 """Return the number of extra empty lines before and after the `current_line`.
900 This is for separating `def`, `async def` and `class` with extra empty
901 lines (two on module-level).
902 """
903 form_feed = (
904 current_line.depth == 0
905 and bool(current_line.leaves)
906 and "\f\n" in current_line.leaves[0].prefix
907 )
908 before, after = self._maybe_empty_lines(current_line)
909 previous_after = self.previous_block.after if self.previous_block else 0
910 before = max(0, before - previous_after)
912 # Always have one empty line after a module docstring
913 if self._line_is_module_docstring(current_line):
914 before = 1
916 block = LinesBlock(
917 mode=self.mode,
918 previous_block=self.previous_block,
919 original_line=current_line,
920 before=before,
921 after=after,
922 form_feed=form_feed,
923 )
925 # Maintain the semantic_leading_comment state.
926 if current_line.is_comment:
927 if self.previous_line is None or (
928 not self.previous_line.is_decorator
929 # `or before` means this comment already has an empty line before
930 and (not self.previous_line.is_comment or before)
931 and (self.semantic_leading_comment is None or before)
932 ):
933 self.semantic_leading_comment = block
934 # `or before` means this decorator already has an empty line before
935 elif not current_line.is_decorator or before:
936 self.semantic_leading_comment = None
938 # Maintain _pyi_previous_decorated_func state for overload groups.
939 # The tuple is (name, depth, is_multi) where is_multi indicates
940 # the group has 2+ same-name decorated functions.
941 overload_groups = (
942 self.mode.is_pyi and Preview.pyi_overload_group_blank_lines in self.mode
943 )
944 if overload_groups:
945 if current_line.is_def and self._is_line_decorated(current_line):
946 name = self._get_def_name(current_line)
947 if name is not None:
948 prev = self._pyi_previous_decorated_func
949 is_multi = (
950 prev is not None
951 and prev.name == name
952 and prev.depth == current_line.depth
953 )
954 self._pyi_previous_decorated_func = _DecoratedFuncInfo(
955 name=name,
956 depth=current_line.depth,
957 is_multi=is_multi
958 or (prev is not None and prev.name == name and prev.is_multi),
959 )
960 elif (
961 not current_line.is_decorator
962 and not current_line.is_comment
963 and (
964 self._pyi_previous_decorated_func is None
965 or (
966 current_line.depth <= self._pyi_previous_decorated_func.depth
967 # Don't reset on else/elif — they continue an if/else
968 # chain that may contain overloads at a deeper depth.
969 and not (
970 current_line.leaves
971 and current_line.leaves[0].value in ("else", "elif")
972 )
973 )
974 )
975 ):
976 # Only reset when we see a non-decorator line at the same or
977 # lower depth. Body lines (docstrings, ...) at deeper depth
978 # should not clear the state.
979 self._pyi_previous_decorated_func = None
981 self.previous_line = current_line
982 self.previous_block = block
983 return block
985 def _line_is_module_docstring(self, current_line: Line) -> bool:
986 previous_block = self.previous_block
987 if not previous_block:
988 return False
989 if (
990 len(previous_block.original_line.leaves) != 1
991 or not previous_block.original_line.is_docstring
992 or previous_block.original_line.depth != 0
993 or current_line.is_class
994 or current_line.is_def
995 ):
996 return False
997 while previous_block := previous_block.previous_block:
998 if not previous_block.original_line.is_comment:
999 return False
1000 return True
1002 def _maybe_empty_lines(self, current_line: Line) -> tuple[int, int]:
1003 max_allowed = 1
1004 if current_line.depth == 0:
1005 max_allowed = 1 if self.mode.is_pyi else 2
1006 overload_groups = (
1007 self.mode.is_pyi and Preview.pyi_overload_group_blank_lines in self.mode
1008 )
1010 if current_line.leaves:
1011 # Consume the first leaf's extra newlines.
1012 first_leaf = current_line.leaves[0]
1013 before = first_leaf.prefix.count("\n")
1014 # The blank lines that terminate a `# fmt: off` region live in the
1015 # prefix of the `# fmt: on` comment, not in the verbatim block, so
1016 # capping them here would edit formatting that was opted out of.
1017 if not (
1018 first_leaf.type == STANDALONE_COMMENT
1019 and contains_fmt_directive(first_leaf.value, FMT_ON)
1020 and self.previous_line is not None
1021 and self.previous_line.is_fmt_pass_converted()
1022 ):
1023 before = min(before, max_allowed)
1024 first_leaf.prefix = ""
1025 else:
1026 before = 0
1028 user_had_newline = bool(before)
1029 depth = current_line.depth
1031 # Mutate self.previous_defs, remainder of this function should be pure
1032 previous_def = None
1033 while self.previous_defs and self.previous_defs[-1].depth >= depth:
1034 previous_def = self.previous_defs.pop()
1035 if current_line.is_def or current_line.is_class:
1036 self.previous_defs.append(current_line)
1038 if self.previous_line is None:
1039 # Don't insert empty lines before the first line in the file.
1040 return 0, 0
1042 if current_line.is_docstring:
1043 if self.previous_line.is_class:
1044 return 0, 1
1045 if self.previous_line.opens_block and self.previous_line.is_def:
1046 return 0, 0
1048 if previous_def is not None:
1049 assert self.previous_line is not None
1050 # Note: for decorator/def/class lines, `before` computed here is
1051 # passed to _maybe_empty_lines_for_class_or_def which may override
1052 # it. This block still matters for non-decorator/def/class lines
1053 # (e.g. a `var: int` statement following an overload group).
1054 if self.mode.is_pyi:
1055 if previous_def.is_class and not previous_def.is_stub_class:
1056 before = 1
1057 elif (
1058 overload_groups
1059 and self._pyi_previous_decorated_func is not None
1060 and self._pyi_previous_decorated_func.is_multi
1061 and not current_line.is_comment
1062 and self.previous_line.depth >= current_line.depth
1063 and not (
1064 current_line.leaves
1065 and current_line.leaves[0].value in ("else", "elif")
1066 )
1067 ):
1068 if self._is_in_current_group(current_line):
1069 before = 0
1070 elif current_line.opens_block and (
1071 self._get_block_first_decorated_funcname(current_line)
1072 == self._pyi_previous_decorated_func.name
1073 ):
1074 before = 0
1075 else:
1076 before = 1
1077 elif (
1078 overload_groups
1079 and current_line.opens_block
1080 and current_line.leaves
1081 and current_line.leaves[0].value in ("else", "elif")
1082 and self._block_is_part_of_overload_group(current_line)
1083 ):
1084 # else/elif continuing a conditional overload group:
1085 # don't insert a blank line above.
1086 before = 0
1087 elif (
1088 Preview.pyi_blank_line_after_function_docstring in self.mode
1089 and previous_def.is_def
1090 and self.previous_line.is_docstring
1091 and self.previous_line.depth == previous_def.depth + 1
1092 and not self._def_is_followed_by_same_name_decorated_func(
1093 previous_def,
1094 include_conditional_blocks=overload_groups,
1095 )
1096 ):
1097 before = 1
1098 elif depth and not current_line.is_def and self.previous_line.is_def:
1099 if (
1100 overload_groups
1101 and current_line.opens_block
1102 and self.previous_line.depth <= current_line.depth
1103 and self._block_is_part_of_overload_group(current_line)
1104 ):
1105 before = 1
1106 else:
1107 # Empty lines between attributes and methods should
1108 # be preserved.
1109 before = 1 if user_had_newline else 0
1110 elif (
1111 overload_groups
1112 and current_line.is_comment
1113 and self._pyi_previous_decorated_func is not None
1114 and self._pyi_previous_decorated_func.depth == current_line.depth
1115 ):
1116 # Own-line comments after a decorated function in .pyi:
1117 # preserve a single user blank line but never insert one.
1118 # For non-overload cases the comment_to_add_newlines
1119 # mechanism will retroactively add needed blank lines.
1120 before = 1 if user_had_newline else 0
1121 elif depth:
1122 before = 0
1123 else:
1124 before = 1
1125 else:
1126 if depth:
1127 before = 1
1128 elif (
1129 not depth
1130 and previous_def.depth
1131 and current_line.leaves[-1].type == token.COLON
1132 and (
1133 current_line.leaves[0].value
1134 not in ("with", "try", "for", "while", "if", "match")
1135 )
1136 ):
1137 # We shouldn't add two newlines between an indented function and
1138 # a dependent non-indented clause. This is to avoid issues with
1139 # conditional function definitions that are technically top-level
1140 # and therefore get two trailing newlines, but look weird and
1141 # inconsistent when they're followed by elif, else, etc. This is
1142 # worse because these functions only get *one* preceding newline
1143 # already.
1144 before = 1
1145 else:
1146 before = 2
1148 if current_line.is_decorator or current_line.is_def or current_line.is_class:
1149 return self._maybe_empty_lines_for_class_or_def(
1150 current_line, before, user_had_newline
1151 )
1153 if (
1154 Preview.fmt_off_class_blank_lines in self.mode
1155 and self.previous_line.is_import
1156 and self.previous_line.depth == 0
1157 and current_line.depth == 0
1158 and current_line.is_fmt_pass_converted(
1159 first_leaf_matches=lambda leaf: leaf.value == "class"
1160 )
1161 ):
1162 return 2, 0
1164 if (
1165 self.previous_line.is_import
1166 and self.previous_line.depth == 0
1167 and current_line.depth == 0
1168 and not current_line.is_import
1169 and not current_line.is_fmt_pass_converted(first_leaf_matches=is_import)
1170 ):
1171 return 1, 0
1173 if (
1174 self.previous_line.is_import
1175 and not current_line.is_import
1176 and not current_line.is_fmt_pass_converted(first_leaf_matches=is_import)
1177 and depth == self.previous_line.depth
1178 ):
1179 return (before or 1), 0
1181 return before, 0
1183 def _maybe_empty_lines_for_class_or_def(
1184 self, current_line: Line, before: int, user_had_newline: bool
1185 ) -> tuple[int, int]:
1186 assert self.previous_line is not None
1187 overload_groups = (
1188 self.mode.is_pyi and Preview.pyi_overload_group_blank_lines in self.mode
1189 )
1191 if self.previous_line.is_decorator:
1192 if self.mode.is_pyi and current_line.is_stub_class:
1193 # Insert an empty line after a decorated stub class
1194 return 0, 1
1195 return 0, 0
1197 if self.previous_line.depth < current_line.depth and (
1198 self.previous_line.is_class or self.previous_line.is_def
1199 ):
1200 if self.mode.is_pyi:
1201 return 0, 0
1202 return 1 if user_had_newline else 0, 0
1204 comment_to_add_newlines: LinesBlock | None = None
1205 if (
1206 self.previous_line.is_comment
1207 and self.previous_line.depth == current_line.depth
1208 and before == 0
1209 ):
1210 slc = self.semantic_leading_comment
1211 if (
1212 slc is not None
1213 and slc.previous_block is not None
1214 and not slc.previous_block.original_line.is_class
1215 and not slc.previous_block.original_line.opens_block
1216 and slc.before <= 1
1217 ):
1218 comment_to_add_newlines = slc
1219 else:
1220 return 0, 0
1222 if self.mode.is_pyi:
1223 if current_line.is_class or self.previous_line.is_class:
1224 if self.previous_line.depth < current_line.depth:
1225 newlines = 0
1226 elif self.previous_line.depth > current_line.depth:
1227 newlines = 1
1228 elif current_line.is_stub_class and self.previous_line.is_stub_class:
1229 # No blank line between classes with an empty body
1230 newlines = 0
1231 else:
1232 newlines = 1
1233 # Don't inspect only the previous line if it's part of the body of the
1234 # preceding statement. We always want a blank line after something with a
1235 # body.
1236 elif self.previous_line.depth > current_line.depth:
1237 if overload_groups and self._is_in_current_group(current_line):
1238 newlines = 0
1239 else:
1240 newlines = 1
1241 elif (
1242 overload_groups
1243 and self._pyi_previous_decorated_func is not None
1244 and self._pyi_previous_decorated_func.is_multi
1245 and self.previous_line.depth >= current_line.depth
1246 ):
1247 newlines = 0 if self._is_in_current_group(current_line) else 1
1248 elif overload_groups and self._is_in_current_group(current_line):
1249 # A comment between overloads may prevent is_multi from being
1250 # set, but _is_in_current_group still detects name continuity.
1251 newlines = 0
1252 elif (
1253 overload_groups
1254 and current_line.is_decorator
1255 and self.previous_line.depth >= current_line.depth
1256 and self._is_start_of_decorated_group(current_line)
1257 and (
1258 self._pyi_previous_decorated_func is None
1259 or (
1260 self._pyi_previous_decorated_func.name
1261 != self._get_decorator_target_name(current_line)
1262 )
1263 or self._pyi_previous_decorated_func.depth != current_line.depth
1264 )
1265 ):
1266 newlines = 1
1267 elif (
1268 current_line.is_def or current_line.is_decorator
1269 ) and not self.previous_line.is_def:
1270 if (
1271 overload_groups
1272 and current_line.is_decorator
1273 and self.previous_line.is_comment
1274 and self._is_decorator_in_conditional_overload(current_line)
1275 ):
1276 # Comment before an overload inside a conditional block:
1277 # remove blank lines between the comment and decorator.
1278 newlines = 0
1279 elif current_line.depth:
1280 # In classes empty lines between attributes and methods should
1281 # be preserved.
1282 newlines = min(1, before)
1283 else:
1284 # Blank line between a block of functions (maybe with preceding
1285 # decorators) and a block of non-functions
1286 newlines = 1
1287 elif (
1288 Preview.pyi_blank_line_before_decorated_class in self.mode
1289 and current_line.is_decorator
1290 and self._decorator_decorates_class(current_line)
1291 ):
1292 newlines = 1
1293 else:
1294 newlines = 0
1295 else:
1296 newlines = 1 if current_line.depth else 2
1297 # If a user has left no space after a dummy implementation, don't insert
1298 # new lines. This is useful for instance for @overload or Protocols.
1299 if self.previous_line.is_stub_def and not user_had_newline:
1300 newlines = 0
1301 if comment_to_add_newlines is not None:
1302 previous_block = comment_to_add_newlines.previous_block
1303 if previous_block is not None:
1304 comment_to_add_newlines.before = (
1305 max(comment_to_add_newlines.before, newlines) - previous_block.after
1306 )
1307 newlines = 0
1308 return newlines, 0
1311def enumerate_reversed(sequence: Sequence[T]) -> Iterator[tuple[Index, T]]:
1312 """Like `reversed(enumerate(sequence))` if that were possible."""
1313 index = len(sequence) - 1
1314 for element in reversed(sequence):
1315 yield (index, element)
1316 index -= 1
1319def append_leaves(
1320 new_line: Line, old_line: Line, leaves: list[Leaf], preformatted: bool = False
1321) -> None:
1322 """
1323 Append leaves (taken from @old_line) to @new_line, making sure to fix the
1324 underlying Node structure where appropriate.
1326 All of the leaves in @leaves are duplicated. The duplicates are then
1327 appended to @new_line and used to replace their originals in the underlying
1328 Node structure. Any comments attached to the old leaves are reattached to
1329 the new leaves.
1331 Pre-conditions:
1332 set(@leaves) is a subset of set(@old_line.leaves).
1333 """
1334 # @leaves is a slice of @old_line.leaves, so the leaves are in tree (DFS)
1335 # order and the children replaced within any one parent are reached at
1336 # strictly increasing positions. Remembering where the last child of each
1337 # parent was found lets the lookup resume from there instead of rescanning the
1338 # whole child list through Base.remove on every leaf, which is otherwise
1339 # O(n^2) when a node has many children replaced (e.g. wrapping the operand
1340 # tuple of "%s" % (a, b, c, ...) or copying a very long line for a second
1341 # formatting pass).
1342 search_start: dict[int, int] = {}
1343 for old_leaf in leaves:
1344 new_leaf = Leaf(old_leaf.type, old_leaf.value)
1345 parent = old_leaf.parent
1346 if parent is not None:
1347 children = parent.children
1348 index = search_start.get(id(parent), 0)
1349 while index < len(children) and children[index] is not old_leaf:
1350 index += 1
1351 if index < len(children):
1352 # set_child swaps the child in place (the old one keeps the same
1353 # position), so the next sibling to replace is always further on.
1354 parent.set_child(index, new_leaf)
1355 search_start[id(parent)] = index + 1
1356 else:
1357 # The resume hint missed (unexpected ordering); fall back to the
1358 # full scan so behaviour is unchanged.
1359 replace_child(old_leaf, new_leaf)
1360 new_line.append(new_leaf, preformatted=preformatted)
1362 for comment_leaf in old_line.comments_after(old_leaf):
1363 new_line.append(comment_leaf, preformatted=True)
1366def is_line_short_enough(line: Line, *, mode: Mode, line_str: str = "") -> bool:
1367 """For non-multiline strings, return True if `line` is no longer than `line_length`.
1368 For multiline strings, looks at the context around `line` to determine
1369 if it should be inlined or split up.
1370 Uses the provided `line_str` rendering, if any, otherwise computes a new one.
1371 """
1372 if not line_str:
1373 line_str = line_to_string(line)
1375 if line.contains_standalone_comments():
1376 return False
1377 if "\n" not in line_str:
1378 # No multiline strings (MLS) present
1379 return str_width(line_str) <= mode.line_length
1381 first, *_, last = line_str.split("\n")
1382 if str_width(first) > mode.line_length or str_width(last) > mode.line_length:
1383 return False
1385 # Traverse the AST to examine the context of the multiline string (MLS),
1386 # tracking aspects such as depth and comma existence,
1387 # to determine whether to split the MLS or keep it together.
1388 # Depth (which is based on the existing bracket_depth concept)
1389 # is needed to determine nesting level of the MLS.
1390 # Includes special case for trailing commas.
1391 commas: list[int] = [] # tracks number of commas per depth level
1392 multiline_string: Leaf | None = None
1393 # store the leaves that contain parts of the MLS
1394 multiline_string_contexts: list[LN] = []
1396 # `id()`s of the leaves on this line, used to find which ancestors of the
1397 # multiline string are rendered in full on this line (see below).
1398 line_leaf_ids = {id(leaf) for leaf in line.leaves}
1400 max_level_to_update: int | float = math.inf # track the depth of the MLS
1401 for i, leaf in enumerate(line.leaves):
1402 if max_level_to_update == math.inf:
1403 had_comma: int | None = None
1404 if leaf.bracket_depth + 1 > len(commas):
1405 commas.append(0)
1406 elif leaf.bracket_depth + 1 < len(commas):
1407 had_comma = commas.pop()
1408 if (
1409 had_comma is not None
1410 and multiline_string is not None
1411 and multiline_string.bracket_depth == leaf.bracket_depth + 1
1412 ):
1413 # Have left the level with the MLS, stop tracking commas
1414 max_level_to_update = leaf.bracket_depth
1415 if had_comma > 0:
1416 # MLS was in parens with at least one comma - force split
1417 return False
1419 if leaf.bracket_depth <= max_level_to_update and leaf.type == token.COMMA:
1420 # Inside brackets, ignore trailing comma
1421 # directly after MLS/MLS-containing expression
1422 ignore_ctxs: list[LN | None] = [None]
1423 ignore_ctxs += multiline_string_contexts
1424 if (line.inside_brackets or leaf.bracket_depth > 0) and (
1425 i != len(line.leaves) - 1 or leaf.prev_sibling not in ignore_ctxs
1426 ):
1427 commas[leaf.bracket_depth] += 1
1428 if max_level_to_update != math.inf:
1429 max_level_to_update = min(max_level_to_update, leaf.bracket_depth)
1431 if is_multiline_string(leaf):
1432 if leaf.parent and (
1433 leaf.parent.type == syms.test
1434 or (leaf.parent.parent and leaf.parent.parent.type == syms.dictsetmaker)
1435 ):
1436 # Keep ternary and dictionary values parenthesized
1437 return False
1438 if len(multiline_string_contexts) > 0:
1439 # >1 multiline string cannot fit on a single line - force split
1440 return False
1441 multiline_string = leaf
1442 ctx: LN = leaf
1443 # fetch the leaf components of the MLS in the AST. An ancestor is
1444 # part of the MLS context while it is rendered in full on this line,
1445 # i.e. its first and last leaves both belong to the line (a line is
1446 # a contiguous run of leaves). Walking the leaf ids instead of
1447 # re-rendering `str(ctx)` and substring-searching `line_str` at every
1448 # level keeps this linear; the old form was quadratic on lines with a
1449 # large multiline-string-bearing collection (e.g. a dict literal with
1450 # many triple-quoted values).
1451 while (
1452 id(first_leaf(ctx)) in line_leaf_ids
1453 and id(last_leaf(ctx)) in line_leaf_ids
1454 ):
1455 multiline_string_contexts.append(ctx)
1456 if ctx.parent is None:
1457 break
1458 ctx = ctx.parent
1460 # May not have a triple-quoted multiline string at all,
1461 # in case of a regular string with embedded newlines and line continuations
1462 if len(multiline_string_contexts) == 0:
1463 return True
1465 return all(val == 0 for val in commas)
1468def can_be_split(line: Line) -> bool:
1469 """Return False if the line cannot be split *for sure*.
1471 This is not an exhaustive search but a cheap heuristic that we can use to
1472 avoid some unfortunate formattings (mostly around wrapping unsplittable code
1473 in unnecessary parentheses).
1474 """
1475 leaves = line.leaves
1476 if len(leaves) < 2:
1477 return False
1479 if leaves[0].type == token.STRING and leaves[1].type == token.DOT:
1480 call_count = 0
1481 dot_count = 0
1482 next = leaves[-1]
1483 for leaf in leaves[-2::-1]:
1484 if leaf.type in OPENING_BRACKETS:
1485 if next.type not in CLOSING_BRACKETS:
1486 return False
1488 call_count += 1
1489 elif leaf.type == token.DOT:
1490 dot_count += 1
1491 elif leaf.type == token.NAME:
1492 if not (next.type == token.DOT or next.type in OPENING_BRACKETS):
1493 return False
1495 elif leaf.type not in CLOSING_BRACKETS:
1496 return False
1498 if dot_count > 1 and call_count > 1:
1499 return False
1501 return True
1504def _is_annotated_assignment(head: Line) -> bool:
1505 """Does `head` (an assignment's leaves up to the `=`) contain an annotation?
1507 Detects a `:` at the top bracket level, as in `x: dict[str, int] = ...`.
1508 Colons nested inside brackets (e.g. slices like `x[a:b]`) don't count.
1509 """
1510 depth = 0
1511 for leaf in head.leaves:
1512 if not leaf.value:
1513 continue
1514 if leaf.type in OPENING_BRACKETS:
1515 depth += 1
1516 elif leaf.type in CLOSING_BRACKETS:
1517 depth -= 1
1518 elif leaf.type == token.COLON and depth == 0:
1519 return True
1520 return False
1523def can_omit_invisible_parens(
1524 rhs: RHSResult,
1525 line_length: int,
1526 mode: Mode,
1527) -> bool:
1528 """Does `rhs.body` have a shape safe to reformat without optional parens around it?
1530 Returns True for only a subset of potentially nice looking formattings but
1531 the point is to not return false positives that end up producing lines that
1532 are too long.
1533 """
1534 line = rhs.body
1536 # Don't omit optional parens when the opening paren carries an inline comment.
1537 # Omitting them re-parents the comment onto a different leaf after the next
1538 # parse, which can make the RHS splitter choose a different shape on each
1539 # pass (unstable formatting / "different code on the second pass"). See
1540 # issues #3701, #3706, and #4384.
1541 if rhs.opening_bracket.type == token.LPAR and not rhs.opening_bracket.value:
1542 if rhs.head.comments.get(id(rhs.opening_bracket)):
1543 return False
1545 # We can't omit parens if doing so would result in a type: ignore comment
1546 # sharing a line with other comments, as that breaks type: ignore parsing.
1547 # Check if the opening bracket (last leaf of head) has comments that would merge
1548 # with comments from the first line of the body.
1549 if rhs.head.leaves:
1550 opening_bracket = rhs.head.leaves[-1]
1551 head_comments = rhs.head.comments.get(id(opening_bracket), [])
1553 # If there are comments on the opening bracket line, check if any would
1554 # conflict with type: ignore comments in the body
1555 if head_comments:
1556 has_type_ignore_in_head = any(
1557 is_type_ignore_comment(comment, mode=rhs.head.mode)
1558 for comment in head_comments
1559 )
1560 has_other_comment_in_head = any(
1561 not is_type_ignore_comment(comment, mode=rhs.head.mode)
1562 for comment in head_comments
1563 )
1565 # Check for comments in the body that would potentially end up on the
1566 # same line as the head comments when parens are removed
1567 has_type_ignore_in_body = False
1568 has_other_comment_in_body = False
1569 for leaf in rhs.body.leaves:
1570 for comment in rhs.body.comments.get(id(leaf), []):
1571 if is_type_ignore_comment(comment, mode=rhs.body.mode):
1572 has_type_ignore_in_body = True
1573 else:
1574 has_other_comment_in_body = True
1576 # Preserve parens if we have both type: ignore and other comments that
1577 # could end up on the same line
1578 if (has_type_ignore_in_head and has_other_comment_in_body) or (
1579 has_other_comment_in_head and has_type_ignore_in_body
1580 ):
1581 return False
1583 # We need optional parens in order to split standalone comments to their own lines
1584 # if there are no nested parens around the standalone comments
1585 closing_bracket: Leaf | None = None
1586 for leaf in reversed(line.leaves):
1587 if closing_bracket and leaf is closing_bracket.opening_bracket:
1588 closing_bracket = None
1589 if leaf.type == STANDALONE_COMMENT and not closing_bracket:
1590 return False
1591 if (
1592 not closing_bracket
1593 and leaf.type in CLOSING_BRACKETS
1594 and leaf.opening_bracket in line.leaves
1595 and leaf.value
1596 ):
1597 closing_bracket = leaf
1599 # For assignments to a subscripted target whose head is too long to fit
1600 # (e.g. `x[long_key][another_long_key] = expr`), the target must be split
1601 # at its subscript brackets no matter what, so optional parens around a
1602 # RHS that fits on the resulting tail line (`] = expr`) are unnecessary.
1603 # When the head fits on one line, paren-wrapping the RHS remains the
1604 # preferred style and this check must not fire. It must also come before
1605 # the delimiter_count > 1 early return below, which would otherwise
1606 # reject bodies with multiple delimiters such as `10 - 5`.
1607 if (
1608 Preview.fix_unnecessary_parens_in_indexed_assignment in mode
1609 and len(rhs.head.leaves) >= 3
1610 and rhs.head.leaves[-2].type == token.EQUAL
1611 # The target must actually end with a subscript: a visible `]`
1612 # immediately before the `=`. Invisible parens (e.g. around tuple
1613 # targets like `(x,) = ...`) have an empty value and don't count.
1614 and rhs.head.leaves[-3].type == token.RSQB
1615 and rhs.head.leaves[-3].value
1616 # In annotated assignments (`x: dict[str, int] = ...`) the `]` before
1617 # the `=` belongs to the annotation; splitting on the annotation's
1618 # brackets would be wrong, so leave the optional parens alone.
1619 and not _is_annotated_assignment(rhs.head)
1620 # The head must be too long to fit, forcing the subscript split.
1621 and not is_line_short_enough(rhs.head, mode=mode)
1622 ):
1623 # 4 extra characters for the `] = ` prefix on the tail line.
1624 tail_line_length = 4 * line.depth + 4
1625 for _index, _leaf, leaf_length in line.enumerate_with_length():
1626 tail_line_length += leaf_length
1627 if tail_line_length <= line_length:
1628 return True
1630 bt = line.bracket_tracker
1631 if not bt.delimiters:
1632 # Without delimiters the optional parentheses are useless.
1633 return True
1635 max_priority = bt.max_delimiter_priority()
1636 delimiter_count = bt.delimiter_count_with_priority(max_priority)
1637 if delimiter_count > 1:
1638 # With more than one delimiter of a kind the optional parentheses read better.
1639 return False
1641 if delimiter_count == 1:
1642 if max_priority == COMMA_PRIORITY and rhs.head.is_with_or_async_with_stmt:
1643 # For two context manager with statements, the optional parentheses read
1644 # better. In this case, `rhs.body` is the context managers part of
1645 # the with statement. `rhs.head` is the `with (` part on the previous
1646 # line.
1647 return False
1648 # Otherwise it may also read better, but we don't do it today and requires
1649 # careful considerations for all possible cases. See
1650 # https://github.com/psf/black/issues/2156.
1652 if max_priority == DOT_PRIORITY:
1653 # A single stranded method call doesn't require optional parentheses.
1654 return True
1656 assert len(line.leaves) >= 2, "Stranded delimiter"
1658 # With a single delimiter, omit if the expression starts or ends with
1659 # a bracket.
1660 first = line.leaves[0]
1661 second = line.leaves[1]
1662 if first.type in OPENING_BRACKETS and second.type not in CLOSING_BRACKETS:
1663 if _can_omit_opening_paren(line, first=first, line_length=line_length):
1664 return True
1666 # Note: we are not returning False here because a line might have *both*
1667 # a leading opening bracket and a trailing closing bracket. If the
1668 # opening bracket doesn't match our rule, maybe the closing will.
1670 penultimate = line.leaves[-2]
1671 last = line.leaves[-1]
1673 if (
1674 last.type == token.RPAR
1675 or last.type == token.RBRACE
1676 or (
1677 # don't use indexing for omitting optional parentheses;
1678 # it looks weird
1679 last.type == token.RSQB
1680 and last.parent
1681 and last.parent.type != syms.trailer
1682 )
1683 ):
1684 if penultimate.type in OPENING_BRACKETS:
1685 # Empty brackets don't help.
1686 return False
1688 if is_multiline_string(first):
1689 # Additional wrapping of a multiline string in this situation is
1690 # unnecessary.
1691 return True
1693 if _can_omit_closing_paren(line, last=last, line_length=line_length):
1694 return True
1696 return False
1699def _can_omit_opening_paren(line: Line, *, first: Leaf, line_length: int) -> bool:
1700 """See `can_omit_invisible_parens`."""
1701 remainder = False
1702 length = 4 * line.depth
1703 _index = -1
1704 for _index, leaf, leaf_length in line.enumerate_with_length():
1705 if leaf.type in CLOSING_BRACKETS and leaf.opening_bracket is first:
1706 remainder = True
1707 if remainder:
1708 length += leaf_length
1709 if length > line_length:
1710 break
1712 if leaf.type in OPENING_BRACKETS:
1713 # There are brackets we can further split on.
1714 remainder = False
1716 else:
1717 # checked the entire string and line length wasn't exceeded
1718 if len(line.leaves) == _index + 1:
1719 return True
1721 return False
1724def _can_omit_closing_paren(line: Line, *, last: Leaf, line_length: int) -> bool:
1725 """See `can_omit_invisible_parens`."""
1726 length = 4 * line.depth
1727 seen_other_brackets = False
1728 for _index, leaf, leaf_length in line.enumerate_with_length():
1729 length += leaf_length
1730 if leaf is last.opening_bracket:
1731 if seen_other_brackets or length <= line_length:
1732 return True
1734 elif leaf.type in OPENING_BRACKETS:
1735 # There are brackets we can further split on.
1736 seen_other_brackets = True
1738 return False
1741def line_to_string(line: Line) -> str:
1742 """Returns the string representation of @line.
1744 WARNING: This is known to be computationally expensive.
1745 """
1746 return str(line).strip("\n")