All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
   1 from dataclasses import dataclass, field
 
  16 from blib2to3.pytree import Node, Leaf
 
  17 from blib2to3.pgen2 import token
 
  19 from black.brackets import BracketTracker, DOT_PRIORITY
 
  20 from black.mode import Mode, Preview
 
  21 from black.nodes import STANDALONE_COMMENT, TEST_DESCENDANTS
 
  22 from black.nodes import BRACKETS, OPENING_BRACKETS, CLOSING_BRACKETS
 
  23 from black.nodes import syms, whitespace, replace_child, child_towards
 
  24 from black.nodes import is_multiline_string, is_import, is_type_comment
 
  25 from black.nodes import is_one_sequence_between
 
  35     """Holds leaves and comments. Can be printed with `str(line)`."""
 
  39     leaves: List[Leaf] = field(default_factory=list)
 
  40     # keys ordered like `leaves`
 
  41     comments: Dict[LeafID, List[Leaf]] = field(default_factory=dict)
 
  42     bracket_tracker: BracketTracker = field(default_factory=BracketTracker)
 
  43     inside_brackets: bool = False
 
  44     should_split_rhs: bool = False
 
  45     magic_trailing_comma: Optional[Leaf] = None
 
  47     def append(self, leaf: Leaf, preformatted: bool = False) -> None:
 
  48         """Add a new `leaf` to the end of the line.
 
  50         Unless `preformatted` is True, the `leaf` will receive a new consistent
 
  51         whitespace prefix and metadata applied by :class:`BracketTracker`.
 
  52         Trailing commas are maybe removed, unpacked for loop variables are
 
  53         demoted from being delimiters.
 
  55         Inline comments are put aside.
 
  57         has_value = leaf.type in BRACKETS or bool(leaf.value.strip())
 
  61         if token.COLON == leaf.type and self.is_class_paren_empty:
 
  63         if self.leaves and not preformatted:
 
  64             # Note: at this point leaf.prefix should be empty except for
 
  65             # imports, for which we only preserve newlines.
 
  66             leaf.prefix += whitespace(
 
  67                 leaf, complex_subscript=self.is_complex_subscript(leaf)
 
  69         if self.inside_brackets or not preformatted:
 
  70             self.bracket_tracker.mark(leaf)
 
  71             if self.mode.magic_trailing_comma:
 
  72                 if self.has_magic_trailing_comma(leaf):
 
  73                     self.magic_trailing_comma = leaf
 
  74             elif self.has_magic_trailing_comma(leaf, ensure_removable=True):
 
  75                 self.remove_trailing_comma()
 
  76         if not self.append_comment(leaf):
 
  77             self.leaves.append(leaf)
 
  79     def append_safe(self, leaf: Leaf, preformatted: bool = False) -> None:
 
  80         """Like :func:`append()` but disallow invalid standalone comment structure.
 
  82         Raises ValueError when any `leaf` is appended after a standalone comment
 
  83         or when a standalone comment is not the first leaf on the line.
 
  85         if self.bracket_tracker.depth == 0:
 
  87                 raise ValueError("cannot append to standalone comments")
 
  89             if self.leaves and leaf.type == STANDALONE_COMMENT:
 
  91                     "cannot append standalone comments to a populated line"
 
  94         self.append(leaf, preformatted=preformatted)
 
  97     def is_comment(self) -> bool:
 
  98         """Is this line a standalone comment?"""
 
  99         return len(self.leaves) == 1 and self.leaves[0].type == STANDALONE_COMMENT
 
 102     def is_decorator(self) -> bool:
 
 103         """Is this line a decorator?"""
 
 104         return bool(self) and self.leaves[0].type == token.AT
 
 107     def is_import(self) -> bool:
 
 108         """Is this an import line?"""
 
 109         return bool(self) and is_import(self.leaves[0])
 
 112     def is_class(self) -> bool:
 
 113         """Is this line a class definition?"""
 
 116             and self.leaves[0].type == token.NAME
 
 117             and self.leaves[0].value == "class"
 
 121     def is_stub_class(self) -> bool:
 
 122         """Is this line a class definition with a body consisting only of "..."?"""
 
 123         return self.is_class and self.leaves[-3:] == [
 
 124             Leaf(token.DOT, ".") for _ in range(3)
 
 128     def is_def(self) -> bool:
 
 129         """Is this a function definition? (Also returns True for async defs.)"""
 
 131             first_leaf = self.leaves[0]
 
 136             second_leaf: Optional[Leaf] = self.leaves[1]
 
 139         return (first_leaf.type == token.NAME and first_leaf.value == "def") or (
 
 140             first_leaf.type == token.ASYNC
 
 141             and second_leaf is not None
 
 142             and second_leaf.type == token.NAME
 
 143             and second_leaf.value == "def"
 
 147     def is_class_paren_empty(self) -> bool:
 
 148         """Is this a class with no base classes but using parentheses?
 
 150         Those are unnecessary and should be removed.
 
 154             and len(self.leaves) == 4
 
 156             and self.leaves[2].type == token.LPAR
 
 157             and self.leaves[2].value == "("
 
 158             and self.leaves[3].type == token.RPAR
 
 159             and self.leaves[3].value == ")"
 
 163     def is_triple_quoted_string(self) -> bool:
 
 164         """Is the line a triple quoted string?"""
 
 167             and self.leaves[0].type == token.STRING
 
 168             and self.leaves[0].value.startswith(('"""', "'''"))
 
 171     def contains_standalone_comments(self, depth_limit: int = sys.maxsize) -> bool:
 
 172         """If so, needs to be split before emitting."""
 
 173         for leaf in self.leaves:
 
 174             if leaf.type == STANDALONE_COMMENT and leaf.bracket_depth <= depth_limit:
 
 179     def contains_uncollapsable_type_comments(self) -> bool:
 
 182             last_leaf = self.leaves[-1]
 
 183             ignored_ids.add(id(last_leaf))
 
 184             if last_leaf.type == token.COMMA or (
 
 185                 last_leaf.type == token.RPAR and not last_leaf.value
 
 187                 # When trailing commas or optional parens are inserted by Black for
 
 188                 # consistency, comments after the previous last element are not moved
 
 189                 # (they don't have to, rendering will still be correct).  So we ignore
 
 190                 # trailing commas and invisible.
 
 191                 last_leaf = self.leaves[-2]
 
 192                 ignored_ids.add(id(last_leaf))
 
 196         # A type comment is uncollapsable if it is attached to a leaf
 
 197         # that isn't at the end of the line (since that could cause it
 
 198         # to get associated to a different argument) or if there are
 
 199         # comments before it (since that could cause it to get hidden
 
 202         for leaf_id, comments in self.comments.items():
 
 203             for comment in comments:
 
 204                 if is_type_comment(comment):
 
 206                         not is_type_comment(comment, " ignore")
 
 207                         and leaf_id not in ignored_ids
 
 215     def contains_unsplittable_type_ignore(self) -> bool:
 
 219         # If a 'type: ignore' is attached to the end of a line, we
 
 220         # can't split the line, because we can't know which of the
 
 221         # subexpressions the ignore was meant to apply to.
 
 223         # We only want this to apply to actual physical lines from the
 
 224         # original source, though: we don't want the presence of a
 
 225         # 'type: ignore' at the end of a multiline expression to
 
 226         # justify pushing it all onto one line. Thus we
 
 227         # (unfortunately) need to check the actual source lines and
 
 228         # only report an unsplittable 'type: ignore' if this line was
 
 229         # one line in the original code.
 
 231         # Grab the first and last line numbers, skipping generated leaves
 
 232         first_line = next((leaf.lineno for leaf in self.leaves if leaf.lineno != 0), 0)
 
 234             (leaf.lineno for leaf in reversed(self.leaves) if leaf.lineno != 0), 0
 
 237         if first_line == last_line:
 
 238             # We look at the last two leaves since a comma or an
 
 239             # invisible paren could have been added at the end of the
 
 241             for node in self.leaves[-2:]:
 
 242                 for comment in self.comments.get(id(node), []):
 
 243                     if is_type_comment(comment, " ignore"):
 
 248     def contains_multiline_strings(self) -> bool:
 
 249         return any(is_multiline_string(leaf) for leaf in self.leaves)
 
 251     def has_magic_trailing_comma(
 
 252         self, closing: Leaf, ensure_removable: bool = False
 
 254         """Return True if we have a magic trailing comma, that is when:
 
 255         - there's a trailing comma here
 
 256         - it's not a one-tuple
 
 257         - it's not a single-element subscript
 
 258         Additionally, if ensure_removable:
 
 259         - it's not from square bracket indexing
 
 262             closing.type in CLOSING_BRACKETS
 
 264             and self.leaves[-1].type == token.COMMA
 
 268         if closing.type == token.RBRACE:
 
 271         if closing.type == token.RSQB:
 
 273                 Preview.one_element_subscript in self.mode
 
 275                 and closing.parent.type == syms.trailer
 
 276                 and closing.opening_bracket
 
 277                 and is_one_sequence_between(
 
 278                     closing.opening_bracket,
 
 281                     brackets=(token.LSQB, token.RSQB),
 
 286             if not ensure_removable:
 
 288             comma = self.leaves[-1]
 
 289             return bool(comma.parent and comma.parent.type == syms.listmaker)
 
 294         if closing.opening_bracket is not None and not is_one_sequence_between(
 
 295             closing.opening_bracket, closing, self.leaves
 
 301     def append_comment(self, comment: Leaf) -> bool:
 
 302         """Add an inline or standalone comment to the line."""
 
 304             comment.type == STANDALONE_COMMENT
 
 305             and self.bracket_tracker.any_open_brackets()
 
 310         if comment.type != token.COMMENT:
 
 314             comment.type = STANDALONE_COMMENT
 
 318         last_leaf = self.leaves[-1]
 
 320             last_leaf.type == token.RPAR
 
 321             and not last_leaf.value
 
 323             and len(list(last_leaf.parent.leaves())) <= 3
 
 324             and not is_type_comment(comment)
 
 326             # Comments on an optional parens wrapping a single leaf should belong to
 
 327             # the wrapped node except if it's a type comment. Pinning the comment like
 
 328             # this avoids unstable formatting caused by comment migration.
 
 329             if len(self.leaves) < 2:
 
 330                 comment.type = STANDALONE_COMMENT
 
 334             last_leaf = self.leaves[-2]
 
 335         self.comments.setdefault(id(last_leaf), []).append(comment)
 
 338     def comments_after(self, leaf: Leaf) -> List[Leaf]:
 
 339         """Generate comments that should appear directly after `leaf`."""
 
 340         return self.comments.get(id(leaf), [])
 
 342     def remove_trailing_comma(self) -> None:
 
 343         """Remove the trailing comma and moves the comments attached to it."""
 
 344         trailing_comma = self.leaves.pop()
 
 345         trailing_comma_comments = self.comments.pop(id(trailing_comma), [])
 
 346         self.comments.setdefault(id(self.leaves[-1]), []).extend(
 
 347             trailing_comma_comments
 
 350     def is_complex_subscript(self, leaf: Leaf) -> bool:
 
 351         """Return True iff `leaf` is part of a slice with non-trivial exprs."""
 
 352         open_lsqb = self.bracket_tracker.get_open_lsqb()
 
 353         if open_lsqb is None:
 
 356         subscript_start = open_lsqb.next_sibling
 
 358         if isinstance(subscript_start, Node):
 
 359             if subscript_start.type == syms.listmaker:
 
 362             if subscript_start.type == syms.subscriptlist:
 
 363                 subscript_start = child_towards(subscript_start, leaf)
 
 364         return subscript_start is not None and any(
 
 365             n.type in TEST_DESCENDANTS for n in subscript_start.pre_order()
 
 368     def enumerate_with_length(
 
 369         self, reversed: bool = False
 
 370     ) -> Iterator[Tuple[Index, Leaf, int]]:
 
 371         """Return an enumeration of leaves with their length.
 
 373         Stops prematurely on multiline strings and standalone comments.
 
 376             Callable[[Sequence[Leaf]], Iterator[Tuple[Index, Leaf]]],
 
 377             enumerate_reversed if reversed else enumerate,
 
 379         for index, leaf in op(self.leaves):
 
 380             length = len(leaf.prefix) + len(leaf.value)
 
 381             if "\n" in leaf.value:
 
 382                 return  # Multiline strings, we can't continue.
 
 384             for comment in self.comments_after(leaf):
 
 385                 length += len(comment.value)
 
 387             yield index, leaf, length
 
 389     def clone(self) -> "Line":
 
 393             inside_brackets=self.inside_brackets,
 
 394             should_split_rhs=self.should_split_rhs,
 
 395             magic_trailing_comma=self.magic_trailing_comma,
 
 398     def __str__(self) -> str:
 
 399         """Render the line."""
 
 403         indent = "    " * self.depth
 
 404         leaves = iter(self.leaves)
 
 406         res = f"{first.prefix}{indent}{first.value}"
 
 409         for comment in itertools.chain.from_iterable(self.comments.values()):
 
 414     def __bool__(self) -> bool:
 
 415         """Return True if the line has leaves or comments."""
 
 416         return bool(self.leaves or self.comments)
 
 420 class EmptyLineTracker:
 
 421     """Provides a stateful method that returns the number of potential extra
 
 422     empty lines needed before and after the currently processed line.
 
 424     Note: this tracker works on lines that haven't been split yet.  It assumes
 
 425     the prefix of the first leaf consists of optional newlines.  Those newlines
 
 426     are consumed by `maybe_empty_lines()` and included in the computation.
 
 430     previous_line: Optional[Line] = None
 
 431     previous_after: int = 0
 
 432     previous_defs: List[int] = field(default_factory=list)
 
 434     def maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
 
 435         """Return the number of extra empty lines before and after the `current_line`.
 
 437         This is for separating `def`, `async def` and `class` with extra empty
 
 438         lines (two on module-level).
 
 440         before, after = self._maybe_empty_lines(current_line)
 
 442             # Black should not insert empty lines at the beginning
 
 445             if self.previous_line is None
 
 446             else before - self.previous_after
 
 448         self.previous_after = after
 
 449         self.previous_line = current_line
 
 452     def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
 
 454         if current_line.depth == 0:
 
 455             max_allowed = 1 if self.is_pyi else 2
 
 456         if current_line.leaves:
 
 457             # Consume the first leaf's extra newlines.
 
 458             first_leaf = current_line.leaves[0]
 
 459             before = first_leaf.prefix.count("\n")
 
 460             before = min(before, max_allowed)
 
 461             first_leaf.prefix = ""
 
 464         depth = current_line.depth
 
 465         while self.previous_defs and self.previous_defs[-1] >= depth:
 
 467                 assert self.previous_line is not None
 
 468                 if depth and not current_line.is_def and self.previous_line.is_def:
 
 469                     # Empty lines between attributes and methods should be preserved.
 
 470                     before = min(1, before)
 
 480                     and self.previous_defs[-1]
 
 481                     and current_line.leaves[-1].type == token.COLON
 
 483                         current_line.leaves[0].value
 
 484                         not in ("with", "try", "for", "while", "if", "match")
 
 487                     # We shouldn't add two newlines between an indented function and
 
 488                     # a dependent non-indented clause. This is to avoid issues with
 
 489                     # conditional function definitions that are technically top-level
 
 490                     # and therefore get two trailing newlines, but look weird and
 
 491                     # inconsistent when they're followed by elif, else, etc. This is
 
 492                     # worse because these functions only get *one* preceding newline
 
 497             self.previous_defs.pop()
 
 498         if current_line.is_decorator or current_line.is_def or current_line.is_class:
 
 499             return self._maybe_empty_lines_for_class_or_def(current_line, before)
 
 503             and self.previous_line.is_import
 
 504             and not current_line.is_import
 
 505             and depth == self.previous_line.depth
 
 507             return (before or 1), 0
 
 511             and self.previous_line.is_class
 
 512             and current_line.is_triple_quoted_string
 
 518     def _maybe_empty_lines_for_class_or_def(
 
 519         self, current_line: Line, before: int
 
 520     ) -> Tuple[int, int]:
 
 521         if not current_line.is_decorator:
 
 522             self.previous_defs.append(current_line.depth)
 
 523         if self.previous_line is None:
 
 524             # Don't insert empty lines before the first line in the file.
 
 527         if self.previous_line.is_decorator:
 
 528             if self.is_pyi and current_line.is_stub_class:
 
 529                 # Insert an empty line after a decorated stub class
 
 534         if self.previous_line.depth < current_line.depth and (
 
 535             self.previous_line.is_class or self.previous_line.is_def
 
 540             self.previous_line.is_comment
 
 541             and self.previous_line.depth == current_line.depth
 
 547             if current_line.is_class or self.previous_line.is_class:
 
 548                 if self.previous_line.depth < current_line.depth:
 
 550                 elif self.previous_line.depth > current_line.depth:
 
 552                 elif current_line.is_stub_class and self.previous_line.is_stub_class:
 
 553                     # No blank line between classes with an empty body
 
 558                 current_line.is_def or current_line.is_decorator
 
 559             ) and not self.previous_line.is_def:
 
 560                 if current_line.depth:
 
 561                     # In classes empty lines between attributes and methods should
 
 563                     newlines = min(1, before)
 
 565                     # Blank line between a block of functions (maybe with preceding
 
 566                     # decorators) and a block of non-functions
 
 568             elif self.previous_line.depth > current_line.depth:
 
 573             newlines = 1 if current_line.depth else 2
 
 577 def enumerate_reversed(sequence: Sequence[T]) -> Iterator[Tuple[Index, T]]:
 
 578     """Like `reversed(enumerate(sequence))` if that were possible."""
 
 579     index = len(sequence) - 1
 
 580     for element in reversed(sequence):
 
 581         yield (index, element)
 
 586     new_line: Line, old_line: Line, leaves: List[Leaf], preformatted: bool = False
 
 589     Append leaves (taken from @old_line) to @new_line, making sure to fix the
 
 590     underlying Node structure where appropriate.
 
 592     All of the leaves in @leaves are duplicated. The duplicates are then
 
 593     appended to @new_line and used to replace their originals in the underlying
 
 594     Node structure. Any comments attached to the old leaves are reattached to
 
 598         set(@leaves) is a subset of set(@old_line.leaves).
 
 600     for old_leaf in leaves:
 
 601         new_leaf = Leaf(old_leaf.type, old_leaf.value)
 
 602         replace_child(old_leaf, new_leaf)
 
 603         new_line.append(new_leaf, preformatted=preformatted)
 
 605         for comment_leaf in old_line.comments_after(old_leaf):
 
 606             new_line.append(comment_leaf, preformatted=True)
 
 609 def is_line_short_enough(line: Line, *, line_length: int, line_str: str = "") -> bool:
 
 610     """Return True if `line` is no longer than `line_length`.
 
 612     Uses the provided `line_str` rendering, if any, otherwise computes a new one.
 
 615         line_str = line_to_string(line)
 
 617         len(line_str) <= line_length
 
 618         and "\n" not in line_str  # multiline strings
 
 619         and not line.contains_standalone_comments()
 
 623 def can_be_split(line: Line) -> bool:
 
 624     """Return False if the line cannot be split *for sure*.
 
 626     This is not an exhaustive search but a cheap heuristic that we can use to
 
 627     avoid some unfortunate formattings (mostly around wrapping unsplittable code
 
 628     in unnecessary parentheses).
 
 634     if leaves[0].type == token.STRING and leaves[1].type == token.DOT:
 
 638         for leaf in leaves[-2::-1]:
 
 639             if leaf.type in OPENING_BRACKETS:
 
 640                 if next.type not in CLOSING_BRACKETS:
 
 644             elif leaf.type == token.DOT:
 
 646             elif leaf.type == token.NAME:
 
 647                 if not (next.type == token.DOT or next.type in OPENING_BRACKETS):
 
 650             elif leaf.type not in CLOSING_BRACKETS:
 
 653             if dot_count > 1 and call_count > 1:
 
 659 def can_omit_invisible_parens(
 
 663     """Does `line` have a shape safe to reformat without optional parens around it?
 
 665     Returns True for only a subset of potentially nice looking formattings but
 
 666     the point is to not return false positives that end up producing lines that
 
 669     bt = line.bracket_tracker
 
 670     if not bt.delimiters:
 
 671         # Without delimiters the optional parentheses are useless.
 
 674     max_priority = bt.max_delimiter_priority()
 
 675     if bt.delimiter_count_with_priority(max_priority) > 1:
 
 676         # With more than one delimiter of a kind the optional parentheses read better.
 
 679     if max_priority == DOT_PRIORITY:
 
 680         # A single stranded method call doesn't require optional parentheses.
 
 683     assert len(line.leaves) >= 2, "Stranded delimiter"
 
 685     # With a single delimiter, omit if the expression starts or ends with
 
 687     first = line.leaves[0]
 
 688     second = line.leaves[1]
 
 689     if first.type in OPENING_BRACKETS and second.type not in CLOSING_BRACKETS:
 
 690         if _can_omit_opening_paren(line, first=first, line_length=line_length):
 
 693         # Note: we are not returning False here because a line might have *both*
 
 694         # a leading opening bracket and a trailing closing bracket.  If the
 
 695         # opening bracket doesn't match our rule, maybe the closing will.
 
 697     penultimate = line.leaves[-2]
 
 698     last = line.leaves[-1]
 
 701         last.type == token.RPAR
 
 702         or last.type == token.RBRACE
 
 704             # don't use indexing for omitting optional parentheses;
 
 706             last.type == token.RSQB
 
 708             and last.parent.type != syms.trailer
 
 711         if penultimate.type in OPENING_BRACKETS:
 
 712             # Empty brackets don't help.
 
 715         if is_multiline_string(first):
 
 716             # Additional wrapping of a multiline string in this situation is
 
 720         if _can_omit_closing_paren(line, last=last, line_length=line_length):
 
 726 def _can_omit_opening_paren(line: Line, *, first: Leaf, line_length: int) -> bool:
 
 727     """See `can_omit_invisible_parens`."""
 
 729     length = 4 * line.depth
 
 731     for _index, leaf, leaf_length in line.enumerate_with_length():
 
 732         if leaf.type in CLOSING_BRACKETS and leaf.opening_bracket is first:
 
 735             length += leaf_length
 
 736             if length > line_length:
 
 739             if leaf.type in OPENING_BRACKETS:
 
 740                 # There are brackets we can further split on.
 
 744         # checked the entire string and line length wasn't exceeded
 
 745         if len(line.leaves) == _index + 1:
 
 751 def _can_omit_closing_paren(line: Line, *, last: Leaf, line_length: int) -> bool:
 
 752     """See `can_omit_invisible_parens`."""
 
 753     length = 4 * line.depth
 
 754     seen_other_brackets = False
 
 755     for _index, leaf, leaf_length in line.enumerate_with_length():
 
 756         length += leaf_length
 
 757         if leaf is last.opening_bracket:
 
 758             if seen_other_brackets or length <= line_length:
 
 761         elif leaf.type in OPENING_BRACKETS:
 
 762             # There are brackets we can further split on.
 
 763             seen_other_brackets = True
 
 768 def line_to_string(line: Line) -> str:
 
 769     """Returns the string representation of @line.
 
 771     WARNING: This is known to be computationally expensive.
 
 773     return str(line).strip("\n")