Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/black/lines.py: 19%
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.mode import Mode, Preview
9from black.nodes import (
10 BRACKETS,
11 CLOSING_BRACKETS,
12 OPENING_BRACKETS,
13 STANDALONE_COMMENT,
14 TEST_DESCENDANTS,
15 child_towards,
16 is_docstring,
17 is_import,
18 is_multiline_string,
19 is_one_sequence_between,
20 is_type_comment,
21 is_type_ignore_comment,
22 is_with_or_async_with_stmt,
23 make_simple_prefix,
24 replace_child,
25 syms,
26 whitespace,
27)
28from black.strings import str_width
29from blib2to3.pgen2 import token
30from blib2to3.pytree import Leaf, Node
32# types
33T = TypeVar("T")
34Index = int
35LeafID = int
36LN = Union[Leaf, Node]
39@dataclass
40class Line:
41 """Holds leaves and comments. Can be printed with `str(line)`."""
43 mode: Mode = field(repr=False)
44 depth: int = 0
45 leaves: list[Leaf] = field(default_factory=list)
46 # keys ordered like `leaves`
47 comments: dict[LeafID, list[Leaf]] = field(default_factory=dict)
48 bracket_tracker: BracketTracker = field(default_factory=BracketTracker)
49 inside_brackets: bool = False
50 should_split_rhs: bool = False
51 magic_trailing_comma: Leaf | None = None
53 def append(
54 self, leaf: Leaf, preformatted: bool = False, track_bracket: bool = False
55 ) -> None:
56 """Add a new `leaf` to the end of the line.
58 Unless `preformatted` is True, the `leaf` will receive a new consistent
59 whitespace prefix and metadata applied by :class:`BracketTracker`.
60 Trailing commas are maybe removed, unpacked for loop variables are
61 demoted from being delimiters.
63 Inline comments are put aside.
64 """
65 has_value = (
66 leaf.type in BRACKETS
67 # empty fstring and tstring middles must not be truncated
68 or leaf.type in (token.FSTRING_MIDDLE, token.TSTRING_MIDDLE)
69 or bool(leaf.value.strip())
70 )
71 if not has_value:
72 return
74 if leaf.type == token.COLON and self.is_class_paren_empty:
75 del self.leaves[-2:]
76 if self.leaves and not preformatted:
77 # Note: at this point leaf.prefix should be empty except for
78 # imports, for which we only preserve newlines.
79 leaf.prefix += whitespace(
80 leaf,
81 complex_subscript=self.is_complex_subscript(leaf),
82 mode=self.mode,
83 )
84 if self.inside_brackets or not preformatted or track_bracket:
85 self.bracket_tracker.mark(leaf)
86 if self.mode.magic_trailing_comma:
87 if self.has_magic_trailing_comma(leaf):
88 self.magic_trailing_comma = leaf
89 elif self.has_magic_trailing_comma(leaf):
90 self.remove_trailing_comma()
91 if not self.append_comment(leaf):
92 self.leaves.append(leaf)
94 def append_safe(self, leaf: Leaf, preformatted: bool = False) -> None:
95 """Like :func:`append()` but disallow invalid standalone comment structure.
97 Raises ValueError when any `leaf` is appended after a standalone comment
98 or when a standalone comment is not the first leaf on the line.
99 """
100 if (
101 self.bracket_tracker.depth == 0
102 or self.bracket_tracker.any_open_for_or_lambda()
103 ):
104 if self.is_comment:
105 raise ValueError("cannot append to standalone comments")
107 if self.leaves and leaf.type == STANDALONE_COMMENT:
108 raise ValueError(
109 "cannot append standalone comments to a populated line"
110 )
112 self.append(leaf, preformatted=preformatted)
114 @property
115 def is_comment(self) -> bool:
116 """Is this line a standalone comment?"""
117 return len(self.leaves) == 1 and self.leaves[0].type == STANDALONE_COMMENT
119 @property
120 def is_decorator(self) -> bool:
121 """Is this line a decorator?"""
122 return bool(self) and self.leaves[0].type == token.AT
124 @property
125 def is_import(self) -> bool:
126 """Is this an import line?"""
127 return bool(self) and is_import(self.leaves[0])
129 @property
130 def is_with_or_async_with_stmt(self) -> bool:
131 """Is this a with_stmt line?"""
132 return bool(self) and is_with_or_async_with_stmt(self.leaves[0])
134 @property
135 def is_class(self) -> bool:
136 """Is this line a class definition?"""
137 return (
138 bool(self)
139 and self.leaves[0].type == token.NAME
140 and self.leaves[0].value == "class"
141 )
143 @property
144 def is_stub_class(self) -> bool:
145 """Is this line a class definition with a body consisting only of "..."?"""
146 return self.is_class and self.leaves[-3:] == [
147 Leaf(token.DOT, ".") for _ in range(3)
148 ]
150 @property
151 def is_def(self) -> bool:
152 """Is this a function definition? (Also returns True for async defs.)"""
153 try:
154 first_leaf = self.leaves[0]
155 except IndexError:
156 return False
158 try:
159 second_leaf: Leaf | None = self.leaves[1]
160 except IndexError:
161 second_leaf = None
162 return (first_leaf.type == token.NAME and first_leaf.value == "def") or (
163 first_leaf.type == token.ASYNC
164 and second_leaf is not None
165 and second_leaf.type == token.NAME
166 and second_leaf.value == "def"
167 )
169 @property
170 def is_stub_def(self) -> bool:
171 """Is this line a function definition with a body consisting only of "..."?"""
172 return self.is_def and self.leaves[-4:] == [Leaf(token.COLON, ":")] + [
173 Leaf(token.DOT, ".") for _ in range(3)
174 ]
176 @property
177 def is_class_paren_empty(self) -> bool:
178 """Is this a class with no base classes but using parentheses?
180 Those are unnecessary and should be removed.
181 """
182 return (
183 bool(self)
184 and len(self.leaves) == 4
185 and self.is_class
186 and self.leaves[2].type == token.LPAR
187 and self.leaves[2].value == "("
188 and self.leaves[3].type == token.RPAR
189 and self.leaves[3].value == ")"
190 )
192 @property
193 def _is_triple_quoted_string(self) -> bool:
194 """Is the line a triple quoted string?"""
195 if not self or self.leaves[0].type != token.STRING:
196 return False
197 value = self.leaves[0].value
198 if value.startswith(('"""', "'''")):
199 return True
200 if value.startswith(("r'''", 'r"""', "R'''", 'R"""')):
201 return True
202 return False
204 @property
205 def is_docstring(self) -> bool:
206 """Is the line a docstring?"""
207 return bool(self) and is_docstring(self.leaves[0])
209 @property
210 def is_chained_assignment(self) -> bool:
211 """Is the line a chained assignment"""
212 return [leaf.type for leaf in self.leaves].count(token.EQUAL) > 1
214 @property
215 def opens_block(self) -> bool:
216 """Does this line open a new level of indentation."""
217 if len(self.leaves) == 0:
218 return False
219 return self.leaves[-1].type == token.COLON
221 def is_fmt_pass_converted(
222 self, *, first_leaf_matches: Callable[[Leaf], bool] | None = None
223 ) -> bool:
224 """Is this line converted from fmt off/skip code?
226 If first_leaf_matches is not None, it only returns True if the first
227 leaf of converted code matches.
228 """
229 if len(self.leaves) != 1:
230 return False
231 leaf = self.leaves[0]
232 if (
233 leaf.type != STANDALONE_COMMENT
234 or leaf.fmt_pass_converted_first_leaf is None
235 ):
236 return False
237 return first_leaf_matches is None or first_leaf_matches(
238 leaf.fmt_pass_converted_first_leaf
239 )
241 def contains_standalone_comments(self) -> bool:
242 """If so, needs to be split before emitting."""
243 for leaf in self.leaves:
244 if leaf.type == STANDALONE_COMMENT:
245 return True
247 return False
249 def contains_implicit_multiline_string_with_comments(self) -> bool:
250 """Check if we have an implicit multiline string with comments on the line"""
251 for leaf_type, leaf_group_iterator in itertools.groupby(
252 self.leaves, lambda leaf: leaf.type
253 ):
254 if leaf_type != token.STRING:
255 continue
256 leaf_list = list(leaf_group_iterator)
257 if len(leaf_list) == 1:
258 continue
259 for leaf in leaf_list:
260 if self.comments_after(leaf):
261 return True
262 return False
264 def contains_uncollapsable_type_comments(self) -> bool:
265 ignored_ids = set()
266 try:
267 last_leaf = self.leaves[-1]
268 ignored_ids.add(id(last_leaf))
269 if last_leaf.type == token.COMMA or (
270 last_leaf.type == token.RPAR and not last_leaf.value
271 ):
272 # When trailing commas or optional parens are inserted by Black for
273 # consistency, comments after the previous last element are not moved
274 # (they don't have to, rendering will still be correct). So we ignore
275 # trailing commas and invisible.
276 last_leaf = self.leaves[-2]
277 ignored_ids.add(id(last_leaf))
278 except IndexError:
279 return False
281 # A type comment is uncollapsable if it is attached to a leaf
282 # that isn't at the end of the line (since that could cause it
283 # to get associated to a different argument) or if there are
284 # comments before it (since that could cause it to get hidden
285 # behind a comment.
286 comment_seen = False
287 for leaf_id, comments in self.comments.items():
288 for comment in comments:
289 if is_type_comment(comment, mode=self.mode):
290 if comment_seen or (
291 not is_type_ignore_comment(comment, mode=self.mode)
292 and leaf_id not in ignored_ids
293 ):
294 return True
296 comment_seen = True
298 return False
300 def contains_unsplittable_type_ignore(self) -> bool:
301 if not self.leaves:
302 return False
304 # If a 'type: ignore' is attached to the end of a line, we
305 # can't split the line, because we can't know which of the
306 # subexpressions the ignore was meant to apply to.
307 #
308 # We only want this to apply to actual physical lines from the
309 # original source, though: we don't want the presence of a
310 # 'type: ignore' at the end of a multiline expression to
311 # justify pushing it all onto one line. Thus we
312 # (unfortunately) need to check the actual source lines and
313 # only report an unsplittable 'type: ignore' if this line was
314 # one line in the original code.
316 # Grab the first and last line numbers, skipping generated leaves
317 first_line = next((leaf.lineno for leaf in self.leaves if leaf.lineno != 0), 0)
318 last_line = next(
319 (leaf.lineno for leaf in reversed(self.leaves) if leaf.lineno != 0), 0
320 )
322 if first_line == last_line:
323 # We look at the last two leaves since a comma or an
324 # invisible paren could have been added at the end of the
325 # line.
326 for node in self.leaves[-2:]:
327 for comment in self.comments.get(id(node), []):
328 if is_type_ignore_comment(comment, mode=self.mode):
329 return True
331 return False
333 def contains_multiline_strings(self) -> bool:
334 return any(is_multiline_string(leaf) for leaf in self.leaves)
336 def has_magic_trailing_comma(self, closing: Leaf) -> bool:
337 """Return True if we have a magic trailing comma, that is when:
338 - there's a trailing comma here
339 - it's not from single-element square bracket indexing
340 - it's not a one-tuple
341 """
342 if not (
343 closing.type in CLOSING_BRACKETS
344 and self.leaves
345 and self.leaves[-1].type == token.COMMA
346 ):
347 return False
349 if closing.type == token.RBRACE:
350 return True
352 if closing.type == token.RSQB:
353 if (
354 closing.parent is not None
355 and closing.parent.type == syms.trailer
356 and closing.opening_bracket is not None
357 and is_one_sequence_between(
358 closing.opening_bracket,
359 closing,
360 self.leaves,
361 brackets=(token.LSQB, token.RSQB),
362 )
363 ):
364 assert closing.prev_sibling is not None
365 assert closing.prev_sibling.type == syms.subscriptlist
366 return False
368 return True
370 if self.is_import:
371 return True
373 if closing.opening_bracket is not None and not is_one_sequence_between(
374 closing.opening_bracket, closing, self.leaves
375 ):
376 return True
378 return False
380 def append_comment(self, comment: Leaf) -> bool:
381 """Add an inline or standalone comment to the line."""
382 if (
383 comment.type == STANDALONE_COMMENT
384 and self.bracket_tracker.any_open_brackets()
385 ):
386 comment.prefix = ""
387 return False
389 if comment.type != token.COMMENT:
390 return False
392 if not self.leaves:
393 comment.type = STANDALONE_COMMENT
394 comment.prefix = ""
395 return False
397 last_leaf = self.leaves[-1]
398 if (
399 last_leaf.type == token.RPAR
400 and not last_leaf.value
401 and last_leaf.parent
402 and len(list(last_leaf.parent.leaves())) <= 3
403 and not is_type_comment(comment, mode=self.mode)
404 ):
405 # Comments on an optional parens wrapping a single leaf should belong to
406 # the wrapped node except if it's a type comment. Pinning the comment like
407 # this avoids unstable formatting caused by comment migration.
408 if len(self.leaves) < 2:
409 comment.type = STANDALONE_COMMENT
410 comment.prefix = ""
411 return False
413 last_leaf = self.leaves[-2]
414 self.comments.setdefault(id(last_leaf), []).append(comment)
415 return True
417 def comments_after(self, leaf: Leaf) -> list[Leaf]:
418 """Generate comments that should appear directly after `leaf`."""
419 return self.comments.get(id(leaf), [])
421 def remove_trailing_comma(self) -> None:
422 """Remove the trailing comma and moves the comments attached to it."""
423 trailing_comma = self.leaves.pop()
424 trailing_comma_comments = self.comments.pop(id(trailing_comma), [])
425 self.comments.setdefault(id(self.leaves[-1]), []).extend(
426 trailing_comma_comments
427 )
429 def is_complex_subscript(self, leaf: Leaf) -> bool:
430 """Return True iff `leaf` is part of a slice with non-trivial exprs."""
431 open_lsqb = self.bracket_tracker.get_open_lsqb()
432 if open_lsqb is None:
433 return False
435 subscript_start = open_lsqb.next_sibling
437 if isinstance(subscript_start, Node):
438 if subscript_start.type == syms.listmaker:
439 return False
441 if subscript_start.type == syms.subscriptlist:
442 subscript_start = child_towards(subscript_start, leaf)
444 return subscript_start is not None and any(
445 n.type in TEST_DESCENDANTS for n in subscript_start.pre_order()
446 )
448 def enumerate_with_length(
449 self, is_reversed: bool = False
450 ) -> Iterator[tuple[Index, Leaf, int]]:
451 """Return an enumeration of leaves with their length.
453 Stops prematurely on multiline strings and standalone comments.
454 """
455 op = cast(
456 Callable[[Sequence[Leaf]], Iterator[tuple[Index, Leaf]]],
457 enumerate_reversed if is_reversed else enumerate,
458 )
459 for index, leaf in op(self.leaves):
460 length = len(leaf.prefix) + len(leaf.value)
461 if "\n" in leaf.value:
462 return # Multiline strings, we can't continue.
464 for comment in self.comments_after(leaf):
465 length += len(comment.value)
467 yield index, leaf, length
469 def clone(self) -> "Line":
470 return Line(
471 mode=self.mode,
472 depth=self.depth,
473 inside_brackets=self.inside_brackets,
474 should_split_rhs=self.should_split_rhs,
475 magic_trailing_comma=self.magic_trailing_comma,
476 )
478 def __str__(self) -> str:
479 """Render the line."""
480 if not self:
481 return "\n"
483 indent = " " * self.depth
484 leaves = iter(self.leaves)
485 first = next(leaves)
486 res = f"{first.prefix}{indent}{first.value}"
487 res += "".join(str(leaf) for leaf in leaves)
488 comments_iter = itertools.chain.from_iterable(self.comments.values())
489 comments = [str(comment) for comment in comments_iter]
490 res += "".join(comments)
492 return res + "\n"
494 def __bool__(self) -> bool:
495 """Return True if the line has leaves or comments."""
496 return bool(self.leaves or self.comments)
499@dataclass
500class RHSResult:
501 """Intermediate split result from a right hand split."""
503 head: Line
504 body: Line
505 tail: Line
506 opening_bracket: Leaf
507 closing_bracket: Leaf
510@dataclass
511class LinesBlock:
512 """Class that holds information about a block of formatted lines.
514 This is introduced so that the EmptyLineTracker can look behind the standalone
515 comments and adjust their empty lines for class or def lines.
516 """
518 mode: Mode
519 previous_block: Optional["LinesBlock"]
520 original_line: Line
521 before: int = 0
522 content_lines: list[str] = field(default_factory=list)
523 after: int = 0
524 form_feed: bool = False
526 def all_lines(self) -> list[str]:
527 empty_line = str(Line(mode=self.mode))
528 prefix = make_simple_prefix(self.before, self.form_feed, empty_line)
529 return [prefix] + self.content_lines + [empty_line * self.after]
532_WHITESPACE_TOKENS = (
533 token.NEWLINE,
534 token.NL,
535 token.INDENT,
536 token.DEDENT,
537 token.COMMENT,
538 token.ENDMARKER,
539)
542class _DecoratedFuncInfo(NamedTuple):
543 """Tracks the most recently seen decorated function for overload grouping."""
545 name: str
546 depth: int
547 is_multi: bool
550@dataclass
551class EmptyLineTracker:
552 """Provides a stateful method that returns the number of potential extra
553 empty lines needed before and after the currently processed line.
555 Note: this tracker works on lines that haven't been split yet. It assumes
556 the prefix of the first leaf consists of optional newlines. Those newlines
557 are consumed by `maybe_empty_lines()` and included in the computation.
558 """
560 mode: Mode
561 previous_line: Line | None = None
562 previous_block: LinesBlock | None = None
563 previous_defs: list[Line] = field(default_factory=list)
564 semantic_leading_comment: LinesBlock | None = None
565 _pyi_previous_decorated_func: _DecoratedFuncInfo | None = None
567 @staticmethod
568 def _get_funcdef_name(node: Node | Leaf) -> str | None:
569 """Extract the function name from a funcdef or async_funcdef node."""
570 funcdef: Node | Leaf = node
571 if isinstance(node, Node) and node.type == syms.async_funcdef:
572 for sub in node.children:
573 if sub.type == syms.funcdef:
574 funcdef = sub
575 break
576 if not isinstance(funcdef, Node) or funcdef.type != syms.funcdef:
577 return None
578 # Grammar: funcdef = 'def' NAME parameters ':' ...
579 name_node = funcdef.children[1]
580 assert isinstance(name_node, Leaf)
581 return name_node.value
583 @staticmethod
584 def _decorated_node_has_func_named(node: Node, name: str) -> bool:
585 """Check if a ``decorated`` node contains a function with the given name."""
586 return any(
587 sub.type in (syms.funcdef, syms.async_funcdef)
588 and EmptyLineTracker._get_funcdef_name(sub) == name
589 for sub in node.children
590 )
592 @staticmethod
593 def _find_adjacent_decorated(
594 node: Node | Leaf, *, reverse: bool = False
595 ) -> Node | None:
596 """Walk siblings skipping whitespace tokens, returning the first
597 ``decorated`` node found or ``None``."""
598 sibling = node.prev_sibling if reverse else node.next_sibling
599 while sibling is not None:
600 if sibling.type == syms.decorated:
601 assert isinstance(sibling, Node)
602 return sibling
603 elif sibling.type in _WHITESPACE_TOKENS:
604 sibling = sibling.prev_sibling if reverse else sibling.next_sibling
605 else:
606 return None
607 return None
609 @staticmethod
610 def _if_stmt_branch_has_func_named(
611 if_stmt: Node, exclude_suite: Node, name: str
612 ) -> bool:
613 """Check if any branch of an ``if_stmt`` (other than *exclude_suite*)
614 contains a decorated function with the given *name*."""
615 for child in if_stmt.children:
616 if not isinstance(child, Node):
617 continue
618 if child.type != syms.suite:
619 continue
620 if child is exclude_suite:
621 continue
622 for stmt in child.children:
623 if not isinstance(stmt, Node):
624 continue
625 if stmt.type != syms.decorated:
626 continue
627 if EmptyLineTracker._decorated_node_has_func_named(stmt, name):
628 return True
629 break
630 return False
632 @staticmethod
633 def _get_def_name(line: Line) -> str | None:
634 """Extract the function name from a line that is a function definition."""
635 if not line.is_def or not line.leaves:
636 return None
637 if line.leaves[0].value == "def":
638 return line.leaves[1].value
639 # async def: leaves = ['async', 'def', NAME, ...]
640 return line.leaves[2].value
642 @staticmethod
643 def _is_line_decorated(line: Line) -> bool:
644 """Check if a def line is part of a decorated statement."""
645 if not line.is_def or not line.leaves:
646 return False
647 return EmptyLineTracker._find_decorated_node(line) is not None
649 @staticmethod
650 def _find_decorated_node(line: Line) -> Node | None:
651 """Walk up from the first leaf of a line to its ``decorated`` node."""
652 if not line.leaves:
653 return None
654 node = line.leaves[0].parent
655 while node is not None:
656 if node.type == syms.decorated:
657 assert isinstance(node, Node)
658 return node
659 if node.type in (syms.suite, syms.file_input):
660 return None
661 node = node.parent
662 return None
664 @staticmethod
665 def _get_decorator_target_name(line: Line) -> str | None:
666 """For a decorator line, extract the name of the function it decorates.
668 Only handles decorated functions, not decorated classes.
669 """
670 if not line.is_decorator:
671 return None
672 decorated = EmptyLineTracker._find_decorated_node(line)
673 if decorated is None:
674 return None
675 for child in decorated.children:
676 if child.type in (syms.funcdef, syms.async_funcdef):
677 return EmptyLineTracker._get_funcdef_name(child)
678 return None
680 @staticmethod
681 def _decorator_decorates_class(line: Line) -> bool:
682 """Check if a decorator line decorates a class definition."""
683 if not line.is_decorator:
684 return False
685 decorated = EmptyLineTracker._find_decorated_node(line)
686 if decorated is None:
687 return False
688 return any(child.type == syms.classdef for child in decorated.children)
690 def _is_in_current_group(self, current_line: Line) -> bool:
691 """Check if current_line belongs to the same overload group being tracked."""
692 prev = self._pyi_previous_decorated_func
693 if prev is None:
694 return False
695 cur_name = (
696 self._get_decorator_target_name(current_line)
697 if current_line.is_decorator
698 else self._get_def_name(current_line)
699 )
700 return (
701 cur_name is not None
702 and cur_name == prev.name
703 and prev.depth == current_line.depth
704 and (current_line.is_decorator or self._is_line_decorated(current_line))
705 )
707 @staticmethod
708 def _decorated_node_starts_group(decorated_node: Node) -> bool:
709 """Check if a `decorated` AST node is the first in a multi-function group.
711 Returns True when the next statement-level sibling is also a decorated
712 function with the same name.
713 """
714 name = None
715 for child in decorated_node.children:
716 if child.type in (syms.funcdef, syms.async_funcdef):
717 name = EmptyLineTracker._get_funcdef_name(child)
718 break
719 if name is None:
720 return False
721 adjacent = EmptyLineTracker._find_adjacent_decorated(decorated_node)
722 return adjacent is not None and EmptyLineTracker._decorated_node_has_func_named(
723 adjacent, name
724 )
726 @staticmethod
727 def _is_start_of_decorated_group(line: Line) -> bool:
728 """Check if a decorator line starts a multi-function group.
730 A multi-function group is 2+ consecutive decorated functions sharing the
731 same name (e.g. @overload groups, @property + setter pairs).
732 """
733 if not line.is_decorator:
734 return False
735 decorated_node = EmptyLineTracker._find_decorated_node(line)
736 if decorated_node is None or decorated_node.parent is None:
737 return False
738 return EmptyLineTracker._decorated_node_starts_group(decorated_node)
740 @staticmethod
741 def _get_block_first_decorated_funcname(line: Line) -> str | None:
742 """Return the function name of the first decorated function in a block.
744 *line* must be a block-opening line (ending with ``:``) such as
745 ``if ...:``. Returns ``None`` when the block doesn't start with a
746 decorated function.
747 """
748 if not line.leaves or line.leaves[-1].type != token.COLON:
749 return None
750 suite = line.leaves[-1].next_sibling
751 if suite is None or not isinstance(suite, Node) or suite.type != syms.suite:
752 return None
753 for child in suite.children:
754 if isinstance(child, Node) and child.type == syms.decorated:
755 for sub in child.children:
756 if sub.type in (syms.funcdef, syms.async_funcdef):
757 return EmptyLineTracker._get_funcdef_name(sub)
758 break
759 if child.type not in (token.NEWLINE, token.NL, token.INDENT, token.DEDENT):
760 break
761 return None
763 @staticmethod
764 def _block_is_part_of_overload_group(line: Line) -> bool:
765 """Check if a block-opening line contains a decorated function that is
766 part of a larger overload group — either because the ``if_stmt``'s next
767 sibling is a same-name decorated function, or because another branch of
768 the same ``if_stmt`` has one.
769 """
770 func_name = EmptyLineTracker._get_block_first_decorated_funcname(line)
771 if func_name is None:
772 return False
774 suite = line.leaves[-1].next_sibling
775 if suite is None or not isinstance(suite, Node):
776 return False
777 if_stmt = suite.parent
778 if if_stmt is None or not isinstance(if_stmt, Node):
779 return False
781 # Check if the if_stmt's next sibling is a same-name decorated function.
782 adjacent = EmptyLineTracker._find_adjacent_decorated(if_stmt)
783 if adjacent is not None and EmptyLineTracker._decorated_node_has_func_named(
784 adjacent, func_name
785 ):
786 return True
788 # Check other branches (elif/else) of the same if_stmt.
789 return EmptyLineTracker._if_stmt_branch_has_func_named(
790 if_stmt, suite, func_name
791 )
793 @staticmethod
794 def _is_decorator_in_conditional_overload(line: Line) -> bool:
795 """Check if a decorator is inside an if/else block that is part of a
796 broader overload group (a sibling or another branch of the same
797 ``if_stmt`` contains a same-name decorated function)."""
798 name = EmptyLineTracker._get_decorator_target_name(line)
799 if name is None:
800 return False
802 decorated = EmptyLineTracker._find_decorated_node(line)
803 if decorated is None:
804 return False
806 suite = decorated.parent
807 if suite is None or suite.type != syms.suite:
808 return False
810 if_stmt = suite.parent
811 if if_stmt is None or if_stmt.type != syms.if_stmt:
812 return False
814 # Check if_stmt's adjacent siblings for same-name decorated function.
815 for reverse in (True, False):
816 adjacent = EmptyLineTracker._find_adjacent_decorated(
817 if_stmt, reverse=reverse
818 )
819 if (
820 adjacent is not None
821 and EmptyLineTracker._decorated_node_has_func_named(adjacent, name)
822 ):
823 return True
825 # Check other branches of the same if_stmt.
826 return EmptyLineTracker._if_stmt_branch_has_func_named(if_stmt, suite, name)
828 def maybe_empty_lines(self, current_line: Line) -> LinesBlock:
829 """Return the number of extra empty lines before and after the `current_line`.
831 This is for separating `def`, `async def` and `class` with extra empty
832 lines (two on module-level).
833 """
834 form_feed = (
835 current_line.depth == 0
836 and bool(current_line.leaves)
837 and "\f\n" in current_line.leaves[0].prefix
838 )
839 before, after = self._maybe_empty_lines(current_line)
840 previous_after = self.previous_block.after if self.previous_block else 0
841 before = max(0, before - previous_after)
843 # Always have one empty line after a module docstring
844 if self._line_is_module_docstring(current_line):
845 before = 1
847 block = LinesBlock(
848 mode=self.mode,
849 previous_block=self.previous_block,
850 original_line=current_line,
851 before=before,
852 after=after,
853 form_feed=form_feed,
854 )
856 # Maintain the semantic_leading_comment state.
857 if current_line.is_comment:
858 if self.previous_line is None or (
859 not self.previous_line.is_decorator
860 # `or before` means this comment already has an empty line before
861 and (not self.previous_line.is_comment or before)
862 and (self.semantic_leading_comment is None or before)
863 ):
864 self.semantic_leading_comment = block
865 # `or before` means this decorator already has an empty line before
866 elif not current_line.is_decorator or before:
867 self.semantic_leading_comment = None
869 # Maintain _pyi_previous_decorated_func state for overload groups.
870 # The tuple is (name, depth, is_multi) where is_multi indicates
871 # the group has 2+ same-name decorated functions.
872 overload_groups = (
873 self.mode.is_pyi and Preview.pyi_overload_group_blank_lines in self.mode
874 )
875 if overload_groups:
876 if current_line.is_def and self._is_line_decorated(current_line):
877 name = self._get_def_name(current_line)
878 if name is not None:
879 prev = self._pyi_previous_decorated_func
880 is_multi = (
881 prev is not None
882 and prev.name == name
883 and prev.depth == current_line.depth
884 )
885 self._pyi_previous_decorated_func = _DecoratedFuncInfo(
886 name=name,
887 depth=current_line.depth,
888 is_multi=is_multi
889 or (prev is not None and prev.name == name and prev.is_multi),
890 )
891 elif (
892 not current_line.is_decorator
893 and not current_line.is_comment
894 and (
895 self._pyi_previous_decorated_func is None
896 or (
897 current_line.depth <= self._pyi_previous_decorated_func.depth
898 # Don't reset on else/elif — they continue an if/else
899 # chain that may contain overloads at a deeper depth.
900 and not (
901 current_line.leaves
902 and current_line.leaves[0].value in ("else", "elif")
903 )
904 )
905 )
906 ):
907 # Only reset when we see a non-decorator line at the same or
908 # lower depth. Body lines (docstrings, ...) at deeper depth
909 # should not clear the state.
910 self._pyi_previous_decorated_func = None
912 self.previous_line = current_line
913 self.previous_block = block
914 return block
916 def _line_is_module_docstring(self, current_line: Line) -> bool:
917 previous_block = self.previous_block
918 if not previous_block:
919 return False
920 if (
921 len(previous_block.original_line.leaves) != 1
922 or not previous_block.original_line.is_docstring
923 or current_line.is_class
924 or current_line.is_def
925 ):
926 return False
927 while previous_block := previous_block.previous_block:
928 if not previous_block.original_line.is_comment:
929 return False
930 return True
932 def _maybe_empty_lines(self, current_line: Line) -> tuple[int, int]:
933 max_allowed = 1
934 if current_line.depth == 0:
935 max_allowed = 1 if self.mode.is_pyi else 2
936 overload_groups = (
937 self.mode.is_pyi and Preview.pyi_overload_group_blank_lines in self.mode
938 )
940 if current_line.leaves:
941 # Consume the first leaf's extra newlines.
942 first_leaf = current_line.leaves[0]
943 before = first_leaf.prefix.count("\n")
944 before = min(before, max_allowed)
945 first_leaf.prefix = ""
946 else:
947 before = 0
949 user_had_newline = bool(before)
950 depth = current_line.depth
952 # Mutate self.previous_defs, remainder of this function should be pure
953 previous_def = None
954 while self.previous_defs and self.previous_defs[-1].depth >= depth:
955 previous_def = self.previous_defs.pop()
956 if current_line.is_def or current_line.is_class:
957 self.previous_defs.append(current_line)
959 if self.previous_line is None:
960 # Don't insert empty lines before the first line in the file.
961 return 0, 0
963 if current_line.is_docstring:
964 if self.previous_line.is_class:
965 return 0, 1
966 if self.previous_line.opens_block and self.previous_line.is_def:
967 return 0, 0
969 if previous_def is not None:
970 assert self.previous_line is not None
971 # Note: for decorator/def/class lines, `before` computed here is
972 # passed to _maybe_empty_lines_for_class_or_def which may override
973 # it. This block still matters for non-decorator/def/class lines
974 # (e.g. a `var: int` statement following an overload group).
975 if self.mode.is_pyi:
976 if previous_def.is_class and not previous_def.is_stub_class:
977 before = 1
978 elif (
979 overload_groups
980 and self._pyi_previous_decorated_func is not None
981 and self._pyi_previous_decorated_func.is_multi
982 and not current_line.is_comment
983 and self.previous_line.depth >= current_line.depth
984 and not (
985 current_line.leaves
986 and current_line.leaves[0].value in ("else", "elif")
987 )
988 ):
989 if self._is_in_current_group(current_line):
990 before = 0
991 elif current_line.opens_block and (
992 self._get_block_first_decorated_funcname(current_line)
993 == self._pyi_previous_decorated_func.name
994 ):
995 before = 0
996 else:
997 before = 1
998 elif (
999 overload_groups
1000 and current_line.opens_block
1001 and current_line.leaves
1002 and current_line.leaves[0].value in ("else", "elif")
1003 and self._block_is_part_of_overload_group(current_line)
1004 ):
1005 # else/elif continuing a conditional overload group:
1006 # don't insert a blank line above.
1007 before = 0
1008 elif depth and not current_line.is_def and self.previous_line.is_def:
1009 if (
1010 overload_groups
1011 and current_line.opens_block
1012 and self.previous_line.depth <= current_line.depth
1013 and self._block_is_part_of_overload_group(current_line)
1014 ):
1015 before = 1
1016 else:
1017 # Empty lines between attributes and methods should
1018 # be preserved.
1019 before = 1 if user_had_newline else 0
1020 elif (
1021 overload_groups
1022 and current_line.is_comment
1023 and self._pyi_previous_decorated_func is not None
1024 and self._pyi_previous_decorated_func.depth == current_line.depth
1025 ):
1026 # Own-line comments after a decorated function in .pyi:
1027 # preserve a single user blank line but never insert one.
1028 # For non-overload cases the comment_to_add_newlines
1029 # mechanism will retroactively add needed blank lines.
1030 before = 1 if user_had_newline else 0
1031 elif depth:
1032 before = 0
1033 else:
1034 before = 1
1035 else:
1036 if depth:
1037 before = 1
1038 elif (
1039 not depth
1040 and previous_def.depth
1041 and current_line.leaves[-1].type == token.COLON
1042 and (
1043 current_line.leaves[0].value
1044 not in ("with", "try", "for", "while", "if", "match")
1045 )
1046 ):
1047 # We shouldn't add two newlines between an indented function and
1048 # a dependent non-indented clause. This is to avoid issues with
1049 # conditional function definitions that are technically top-level
1050 # and therefore get two trailing newlines, but look weird and
1051 # inconsistent when they're followed by elif, else, etc. This is
1052 # worse because these functions only get *one* preceding newline
1053 # already.
1054 before = 1
1055 else:
1056 before = 2
1058 if current_line.is_decorator or current_line.is_def or current_line.is_class:
1059 return self._maybe_empty_lines_for_class_or_def(
1060 current_line, before, user_had_newline
1061 )
1063 if (
1064 self.previous_line.is_import
1065 and self.previous_line.depth == 0
1066 and current_line.depth == 0
1067 and not current_line.is_import
1068 and not current_line.is_fmt_pass_converted(first_leaf_matches=is_import)
1069 ):
1070 return 1, 0
1072 if (
1073 self.previous_line.is_import
1074 and not current_line.is_import
1075 and not current_line.is_fmt_pass_converted(first_leaf_matches=is_import)
1076 and depth == self.previous_line.depth
1077 ):
1078 return (before or 1), 0
1080 return before, 0
1082 def _maybe_empty_lines_for_class_or_def(
1083 self, current_line: Line, before: int, user_had_newline: bool
1084 ) -> tuple[int, int]:
1085 assert self.previous_line is not None
1086 overload_groups = (
1087 self.mode.is_pyi and Preview.pyi_overload_group_blank_lines in self.mode
1088 )
1090 if self.previous_line.is_decorator:
1091 if self.mode.is_pyi and current_line.is_stub_class:
1092 # Insert an empty line after a decorated stub class
1093 return 0, 1
1094 return 0, 0
1096 if self.previous_line.depth < current_line.depth and (
1097 self.previous_line.is_class or self.previous_line.is_def
1098 ):
1099 if self.mode.is_pyi:
1100 return 0, 0
1101 return 1 if user_had_newline else 0, 0
1103 comment_to_add_newlines: LinesBlock | None = None
1104 if (
1105 self.previous_line.is_comment
1106 and self.previous_line.depth == current_line.depth
1107 and before == 0
1108 ):
1109 slc = self.semantic_leading_comment
1110 if (
1111 slc is not None
1112 and slc.previous_block is not None
1113 and not slc.previous_block.original_line.is_class
1114 and not slc.previous_block.original_line.opens_block
1115 and slc.before <= 1
1116 ):
1117 comment_to_add_newlines = slc
1118 else:
1119 return 0, 0
1121 if self.mode.is_pyi:
1122 if current_line.is_class or self.previous_line.is_class:
1123 if self.previous_line.depth < current_line.depth:
1124 newlines = 0
1125 elif self.previous_line.depth > current_line.depth:
1126 newlines = 1
1127 elif current_line.is_stub_class and self.previous_line.is_stub_class:
1128 # No blank line between classes with an empty body
1129 newlines = 0
1130 else:
1131 newlines = 1
1132 # Don't inspect the previous line if it's part of the body of the previous
1133 # statement in the same level, we always want a blank line if there's
1134 # something with a body preceding.
1135 elif self.previous_line.depth > current_line.depth:
1136 if overload_groups and self._is_in_current_group(current_line):
1137 newlines = 0
1138 else:
1139 newlines = 1
1140 elif (
1141 overload_groups
1142 and self._pyi_previous_decorated_func is not None
1143 and self._pyi_previous_decorated_func.is_multi
1144 and self.previous_line.depth >= current_line.depth
1145 ):
1146 newlines = 0 if self._is_in_current_group(current_line) else 1
1147 elif overload_groups and self._is_in_current_group(current_line):
1148 # A comment between overloads may prevent is_multi from being
1149 # set, but _is_in_current_group still detects name continuity.
1150 newlines = 0
1151 elif (
1152 overload_groups
1153 and current_line.is_decorator
1154 and self.previous_line.depth >= current_line.depth
1155 and self._is_start_of_decorated_group(current_line)
1156 and (
1157 self._pyi_previous_decorated_func is None
1158 or (
1159 self._pyi_previous_decorated_func.name
1160 != self._get_decorator_target_name(current_line)
1161 )
1162 or self._pyi_previous_decorated_func.depth != current_line.depth
1163 )
1164 ):
1165 newlines = 1
1166 elif (
1167 current_line.is_def or current_line.is_decorator
1168 ) and not self.previous_line.is_def:
1169 if (
1170 overload_groups
1171 and current_line.is_decorator
1172 and self.previous_line.is_comment
1173 and self._is_decorator_in_conditional_overload(current_line)
1174 ):
1175 # Comment before an overload inside a conditional block:
1176 # remove blank lines between the comment and decorator.
1177 newlines = 0
1178 elif current_line.depth:
1179 # In classes empty lines between attributes and methods should
1180 # be preserved.
1181 newlines = min(1, before)
1182 else:
1183 # Blank line between a block of functions (maybe with preceding
1184 # decorators) and a block of non-functions
1185 newlines = 1
1186 elif (
1187 Preview.pyi_blank_line_before_decorated_class in self.mode
1188 and current_line.is_decorator
1189 and self._decorator_decorates_class(current_line)
1190 ):
1191 newlines = 1
1192 else:
1193 newlines = 0
1194 else:
1195 newlines = 1 if current_line.depth else 2
1196 # If a user has left no space after a dummy implementation, don't insert
1197 # new lines. This is useful for instance for @overload or Protocols.
1198 if self.previous_line.is_stub_def and not user_had_newline:
1199 newlines = 0
1200 if comment_to_add_newlines is not None:
1201 previous_block = comment_to_add_newlines.previous_block
1202 if previous_block is not None:
1203 comment_to_add_newlines.before = (
1204 max(comment_to_add_newlines.before, newlines) - previous_block.after
1205 )
1206 newlines = 0
1207 return newlines, 0
1210def enumerate_reversed(sequence: Sequence[T]) -> Iterator[tuple[Index, T]]:
1211 """Like `reversed(enumerate(sequence))` if that were possible."""
1212 index = len(sequence) - 1
1213 for element in reversed(sequence):
1214 yield (index, element)
1215 index -= 1
1218def append_leaves(
1219 new_line: Line, old_line: Line, leaves: list[Leaf], preformatted: bool = False
1220) -> None:
1221 """
1222 Append leaves (taken from @old_line) to @new_line, making sure to fix the
1223 underlying Node structure where appropriate.
1225 All of the leaves in @leaves are duplicated. The duplicates are then
1226 appended to @new_line and used to replace their originals in the underlying
1227 Node structure. Any comments attached to the old leaves are reattached to
1228 the new leaves.
1230 Pre-conditions:
1231 set(@leaves) is a subset of set(@old_line.leaves).
1232 """
1233 for old_leaf in leaves:
1234 new_leaf = Leaf(old_leaf.type, old_leaf.value)
1235 replace_child(old_leaf, new_leaf)
1236 new_line.append(new_leaf, preformatted=preformatted)
1238 for comment_leaf in old_line.comments_after(old_leaf):
1239 new_line.append(comment_leaf, preformatted=True)
1242def is_line_short_enough(line: Line, *, mode: Mode, line_str: str = "") -> bool:
1243 """For non-multiline strings, return True if `line` is no longer than `line_length`.
1244 For multiline strings, looks at the context around `line` to determine
1245 if it should be inlined or split up.
1246 Uses the provided `line_str` rendering, if any, otherwise computes a new one.
1247 """
1248 if not line_str:
1249 line_str = line_to_string(line)
1251 if line.contains_standalone_comments():
1252 return False
1253 if "\n" not in line_str:
1254 # No multiline strings (MLS) present
1255 return str_width(line_str) <= mode.line_length
1257 first, *_, last = line_str.split("\n")
1258 if str_width(first) > mode.line_length or str_width(last) > mode.line_length:
1259 return False
1261 # Traverse the AST to examine the context of the multiline string (MLS),
1262 # tracking aspects such as depth and comma existence,
1263 # to determine whether to split the MLS or keep it together.
1264 # Depth (which is based on the existing bracket_depth concept)
1265 # is needed to determine nesting level of the MLS.
1266 # Includes special case for trailing commas.
1267 commas: list[int] = [] # tracks number of commas per depth level
1268 multiline_string: Leaf | None = None
1269 # store the leaves that contain parts of the MLS
1270 multiline_string_contexts: list[LN] = []
1272 max_level_to_update: int | float = math.inf # track the depth of the MLS
1273 for i, leaf in enumerate(line.leaves):
1274 if max_level_to_update == math.inf:
1275 had_comma: int | None = None
1276 if leaf.bracket_depth + 1 > len(commas):
1277 commas.append(0)
1278 elif leaf.bracket_depth + 1 < len(commas):
1279 had_comma = commas.pop()
1280 if (
1281 had_comma is not None
1282 and multiline_string is not None
1283 and multiline_string.bracket_depth == leaf.bracket_depth + 1
1284 ):
1285 # Have left the level with the MLS, stop tracking commas
1286 max_level_to_update = leaf.bracket_depth
1287 if had_comma > 0:
1288 # MLS was in parens with at least one comma - force split
1289 return False
1291 if leaf.bracket_depth <= max_level_to_update and leaf.type == token.COMMA:
1292 # Inside brackets, ignore trailing comma
1293 # directly after MLS/MLS-containing expression
1294 ignore_ctxs: list[LN | None] = [None]
1295 ignore_ctxs += multiline_string_contexts
1296 if (line.inside_brackets or leaf.bracket_depth > 0) and (
1297 i != len(line.leaves) - 1 or leaf.prev_sibling not in ignore_ctxs
1298 ):
1299 commas[leaf.bracket_depth] += 1
1300 if max_level_to_update != math.inf:
1301 max_level_to_update = min(max_level_to_update, leaf.bracket_depth)
1303 if is_multiline_string(leaf):
1304 if leaf.parent and (
1305 leaf.parent.type == syms.test
1306 or (leaf.parent.parent and leaf.parent.parent.type == syms.dictsetmaker)
1307 ):
1308 # Keep ternary and dictionary values parenthesized
1309 return False
1310 if len(multiline_string_contexts) > 0:
1311 # >1 multiline string cannot fit on a single line - force split
1312 return False
1313 multiline_string = leaf
1314 ctx: LN = leaf
1315 # fetch the leaf components of the MLS in the AST
1316 while str(ctx) in line_str:
1317 multiline_string_contexts.append(ctx)
1318 if ctx.parent is None:
1319 break
1320 ctx = ctx.parent
1322 # May not have a triple-quoted multiline string at all,
1323 # in case of a regular string with embedded newlines and line continuations
1324 if len(multiline_string_contexts) == 0:
1325 return True
1327 return all(val == 0 for val in commas)
1330def can_be_split(line: Line) -> bool:
1331 """Return False if the line cannot be split *for sure*.
1333 This is not an exhaustive search but a cheap heuristic that we can use to
1334 avoid some unfortunate formattings (mostly around wrapping unsplittable code
1335 in unnecessary parentheses).
1336 """
1337 leaves = line.leaves
1338 if len(leaves) < 2:
1339 return False
1341 if leaves[0].type == token.STRING and leaves[1].type == token.DOT:
1342 call_count = 0
1343 dot_count = 0
1344 next = leaves[-1]
1345 for leaf in leaves[-2::-1]:
1346 if leaf.type in OPENING_BRACKETS:
1347 if next.type not in CLOSING_BRACKETS:
1348 return False
1350 call_count += 1
1351 elif leaf.type == token.DOT:
1352 dot_count += 1
1353 elif leaf.type == token.NAME:
1354 if not (next.type == token.DOT or next.type in OPENING_BRACKETS):
1355 return False
1357 elif leaf.type not in CLOSING_BRACKETS:
1358 return False
1360 if dot_count > 1 and call_count > 1:
1361 return False
1363 return True
1366def can_omit_invisible_parens(
1367 rhs: RHSResult,
1368 line_length: int,
1369) -> bool:
1370 """Does `rhs.body` have a shape safe to reformat without optional parens around it?
1372 Returns True for only a subset of potentially nice looking formattings but
1373 the point is to not return false positives that end up producing lines that
1374 are too long.
1375 """
1376 line = rhs.body
1378 # We can't omit parens if doing so would result in a type: ignore comment
1379 # sharing a line with other comments, as that breaks type: ignore parsing.
1380 # Check if the opening bracket (last leaf of head) has comments that would merge
1381 # with comments from the first line of the body.
1382 if rhs.head.leaves:
1383 opening_bracket = rhs.head.leaves[-1]
1384 head_comments = rhs.head.comments.get(id(opening_bracket), [])
1386 # If there are comments on the opening bracket line, check if any would
1387 # conflict with type: ignore comments in the body
1388 if head_comments:
1389 has_type_ignore_in_head = any(
1390 is_type_ignore_comment(comment, mode=rhs.head.mode)
1391 for comment in head_comments
1392 )
1393 has_other_comment_in_head = any(
1394 not is_type_ignore_comment(comment, mode=rhs.head.mode)
1395 for comment in head_comments
1396 )
1398 # Check for comments in the body that would potentially end up on the
1399 # same line as the head comments when parens are removed
1400 has_type_ignore_in_body = False
1401 has_other_comment_in_body = False
1402 for leaf in rhs.body.leaves:
1403 for comment in rhs.body.comments.get(id(leaf), []):
1404 if is_type_ignore_comment(comment, mode=rhs.body.mode):
1405 has_type_ignore_in_body = True
1406 else:
1407 has_other_comment_in_body = True
1409 # Preserve parens if we have both type: ignore and other comments that
1410 # could end up on the same line
1411 if (has_type_ignore_in_head and has_other_comment_in_body) or (
1412 has_other_comment_in_head and has_type_ignore_in_body
1413 ):
1414 return False
1416 # We need optional parens in order to split standalone comments to their own lines
1417 # if there are no nested parens around the standalone comments
1418 closing_bracket: Leaf | None = None
1419 for leaf in reversed(line.leaves):
1420 if closing_bracket and leaf is closing_bracket.opening_bracket:
1421 closing_bracket = None
1422 if leaf.type == STANDALONE_COMMENT and not closing_bracket:
1423 return False
1424 if (
1425 not closing_bracket
1426 and leaf.type in CLOSING_BRACKETS
1427 and leaf.opening_bracket in line.leaves
1428 and leaf.value
1429 ):
1430 closing_bracket = leaf
1432 bt = line.bracket_tracker
1433 if not bt.delimiters:
1434 # Without delimiters the optional parentheses are useless.
1435 return True
1437 max_priority = bt.max_delimiter_priority()
1438 delimiter_count = bt.delimiter_count_with_priority(max_priority)
1439 if delimiter_count > 1:
1440 # With more than one delimiter of a kind the optional parentheses read better.
1441 return False
1443 if delimiter_count == 1:
1444 if max_priority == COMMA_PRIORITY and rhs.head.is_with_or_async_with_stmt:
1445 # For two context manager with statements, the optional parentheses read
1446 # better. In this case, `rhs.body` is the context managers part of
1447 # the with statement. `rhs.head` is the `with (` part on the previous
1448 # line.
1449 return False
1450 # Otherwise it may also read better, but we don't do it today and requires
1451 # careful considerations for all possible cases. See
1452 # https://github.com/psf/black/issues/2156.
1454 if max_priority == DOT_PRIORITY:
1455 # A single stranded method call doesn't require optional parentheses.
1456 return True
1458 assert len(line.leaves) >= 2, "Stranded delimiter"
1460 # With a single delimiter, omit if the expression starts or ends with
1461 # a bracket.
1462 first = line.leaves[0]
1463 second = line.leaves[1]
1464 if first.type in OPENING_BRACKETS and second.type not in CLOSING_BRACKETS:
1465 if _can_omit_opening_paren(line, first=first, line_length=line_length):
1466 return True
1468 # Note: we are not returning False here because a line might have *both*
1469 # a leading opening bracket and a trailing closing bracket. If the
1470 # opening bracket doesn't match our rule, maybe the closing will.
1472 penultimate = line.leaves[-2]
1473 last = line.leaves[-1]
1475 if (
1476 last.type == token.RPAR
1477 or last.type == token.RBRACE
1478 or (
1479 # don't use indexing for omitting optional parentheses;
1480 # it looks weird
1481 last.type == token.RSQB
1482 and last.parent
1483 and last.parent.type != syms.trailer
1484 )
1485 ):
1486 if penultimate.type in OPENING_BRACKETS:
1487 # Empty brackets don't help.
1488 return False
1490 if is_multiline_string(first):
1491 # Additional wrapping of a multiline string in this situation is
1492 # unnecessary.
1493 return True
1495 if _can_omit_closing_paren(line, last=last, line_length=line_length):
1496 return True
1498 return False
1501def _can_omit_opening_paren(line: Line, *, first: Leaf, line_length: int) -> bool:
1502 """See `can_omit_invisible_parens`."""
1503 remainder = False
1504 length = 4 * line.depth
1505 _index = -1
1506 for _index, leaf, leaf_length in line.enumerate_with_length():
1507 if leaf.type in CLOSING_BRACKETS and leaf.opening_bracket is first:
1508 remainder = True
1509 if remainder:
1510 length += leaf_length
1511 if length > line_length:
1512 break
1514 if leaf.type in OPENING_BRACKETS:
1515 # There are brackets we can further split on.
1516 remainder = False
1518 else:
1519 # checked the entire string and line length wasn't exceeded
1520 if len(line.leaves) == _index + 1:
1521 return True
1523 return False
1526def _can_omit_closing_paren(line: Line, *, last: Leaf, line_length: int) -> bool:
1527 """See `can_omit_invisible_parens`."""
1528 length = 4 * line.depth
1529 seen_other_brackets = False
1530 for _index, leaf, leaf_length in line.enumerate_with_length():
1531 length += leaf_length
1532 if leaf is last.opening_bracket:
1533 if seen_other_brackets or length <= line_length:
1534 return True
1536 elif leaf.type in OPENING_BRACKETS:
1537 # There are brackets we can further split on.
1538 seen_other_brackets = True
1540 return False
1543def line_to_string(line: Line) -> str:
1544 """Returns the string representation of @line.
1546 WARNING: This is known to be computationally expensive.
1547 """
1548 return str(line).strip("\n")