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.
3 from asyncio.base_events import BaseEventLoop
4 from concurrent.futures import Executor, ProcessPoolExecutor
6 from functools import partial, wraps
9 from multiprocessing import Manager
11 from pathlib import Path
36 from appdirs import user_cache_dir
37 from attr import dataclass, Factory
41 from blib2to3.pytree import Node, Leaf, type_repr
42 from blib2to3 import pygram, pytree
43 from blib2to3.pgen2 import driver, token
44 from blib2to3.pgen2.parse import ParseError
47 __version__ = "18.5b0"
48 DEFAULT_LINE_LENGTH = 88
49 CACHE_DIR = Path(user_cache_dir("black", version=__version__))
60 LN = Union[Leaf, Node]
61 SplitFunc = Callable[["Line", bool], Iterator["Line"]]
64 CacheInfo = Tuple[Timestamp, FileSize]
65 Cache = Dict[Path, CacheInfo]
66 out = partial(click.secho, bold=True, err=True)
67 err = partial(click.secho, fg="red", err=True)
69 pygram.initialize(CACHE_DIR)
70 syms = pygram.python_symbols
73 class NothingChanged(UserWarning):
74 """Raised by :func:`format_file` when reformatted code is the same as source."""
77 class CannotSplit(Exception):
78 """A readable split that fits the allotted line length is impossible.
80 Raised by :func:`left_hand_split`, :func:`right_hand_split`, and
81 :func:`delimiter_split`.
85 class FormatError(Exception):
86 """Base exception for `# fmt: on` and `# fmt: off` handling.
88 It holds the number of bytes of the prefix consumed before the format
89 control comment appeared.
92 def __init__(self, consumed: int) -> None:
93 super().__init__(consumed)
94 self.consumed = consumed
96 def trim_prefix(self, leaf: Leaf) -> None:
97 leaf.prefix = leaf.prefix[self.consumed :]
99 def leaf_from_consumed(self, leaf: Leaf) -> Leaf:
100 """Returns a new Leaf from the consumed part of the prefix."""
101 unformatted_prefix = leaf.prefix[: self.consumed]
102 return Leaf(token.NEWLINE, unformatted_prefix)
105 class FormatOn(FormatError):
106 """Found a comment like `# fmt: on` in the file."""
109 class FormatOff(FormatError):
110 """Found a comment like `# fmt: off` in the file."""
113 class WriteBack(Enum):
130 default=DEFAULT_LINE_LENGTH,
131 help="How many character per line to allow.",
138 "Don't write the files back, just return the status. Return code 0 "
139 "means nothing would change. Return code 1 means some files would be "
140 "reformatted. Return code 123 means there was an internal error."
146 help="Don't write the files back, just output a diff for each file on stdout.",
151 help="If --fast given, skip temporary sanity checks. [default: --safe]",
158 "Don't emit non-error messages to stderr. Errors are still emitted, "
159 "silence those with 2>/dev/null."
165 help="Force pyi (stub file) formatting, regardless of file extension.",
171 "Force Python 3.6 mode, even if file doesn't currently use "
172 "Python 3.6-only syntax."
175 @click.version_option(version=__version__)
180 exists=True, file_okay=True, dir_okay=True, readable=True, allow_dash=True
195 """The uncompromising code formatter."""
196 sources: List[Path] = []
200 sources.extend(gen_python_files_in_dir(p))
202 # if a file was explicitly given, we don't care about its extension
205 sources.append(Path("-"))
207 err(f"invalid path: {s}")
209 if check and not diff:
210 write_back = WriteBack.NO
212 write_back = WriteBack.DIFF
214 write_back = WriteBack.YES
215 report = Report(check=check, quiet=quiet)
216 if len(sources) == 0:
217 out("No paths given. Nothing to do 😴")
221 elif len(sources) == 1:
224 line_length=line_length,
228 write_back=write_back,
232 loop = asyncio.get_event_loop()
233 executor = ProcessPoolExecutor(max_workers=os.cpu_count())
235 loop.run_until_complete(
238 line_length=line_length,
242 write_back=write_back,
251 out("All done! ✨ 🍰 ✨")
252 click.echo(str(report))
253 ctx.exit(report.return_code)
262 write_back: WriteBack,
265 """Reformat a single file under `src` without spawning child processes.
267 If `quiet` is True, non-error messages are not output. `line_length`,
268 `write_back`, `fast` and `pyi` options are passed to
269 :func:`format_file_in_place` or :func:`format_stdin_to_stdout`.
273 if not src.is_file() and str(src) == "-":
274 if format_stdin_to_stdout(
275 line_length=line_length,
279 write_back=write_back,
281 changed = Changed.YES
284 if write_back != WriteBack.DIFF:
285 cache = read_cache(line_length, pyi, py36)
287 if src in cache and cache[src] == get_cache_info(src):
288 changed = Changed.CACHED
289 if changed is not Changed.CACHED and format_file_in_place(
291 line_length=line_length,
295 write_back=write_back,
297 changed = Changed.YES
298 if write_back == WriteBack.YES and changed is not Changed.NO:
299 write_cache(cache, [src], line_length, pyi, py36)
300 report.done(src, changed)
301 except Exception as exc:
302 report.failed(src, str(exc))
305 async def schedule_formatting(
311 write_back: WriteBack,
316 """Run formatting of `sources` in parallel using the provided `executor`.
318 (Use ProcessPoolExecutors for actual parallelism.)
320 `line_length`, `write_back`, `fast`, and `pyi` options are passed to
321 :func:`format_file_in_place`.
324 if write_back != WriteBack.DIFF:
325 cache = read_cache(line_length, pyi, py36)
326 sources, cached = filter_cached(cache, sources)
328 report.done(src, Changed.CACHED)
333 if write_back == WriteBack.DIFF:
334 # For diff output, we need locks to ensure we don't interleave output
335 # from different processes.
337 lock = manager.Lock()
339 loop.run_in_executor(
341 format_file_in_place,
350 for src in sorted(sources)
352 pending: Iterable[asyncio.Task] = tasks.keys()
354 loop.add_signal_handler(signal.SIGINT, cancel, pending)
355 loop.add_signal_handler(signal.SIGTERM, cancel, pending)
356 except NotImplementedError:
357 # There are no good alternatives for these on Windows
360 done, _ = await asyncio.wait(pending, return_when=asyncio.FIRST_COMPLETED)
362 src = tasks.pop(task)
364 cancelled.append(task)
365 elif task.exception():
366 report.failed(src, str(task.exception()))
368 formatted.append(src)
369 report.done(src, Changed.YES if task.result() else Changed.NO)
371 await asyncio.gather(*cancelled, loop=loop, return_exceptions=True)
372 if write_back == WriteBack.YES and formatted:
373 write_cache(cache, formatted, line_length, pyi, py36)
376 def format_file_in_place(
380 force_pyi: bool = False,
381 force_py36: bool = False,
382 write_back: WriteBack = WriteBack.NO,
383 lock: Any = None, # multiprocessing.Manager().Lock() is some crazy proxy
385 """Format file under `src` path. Return True if changed.
387 If `write_back` is True, write reformatted code back to stdout.
388 `line_length` and `fast` options are passed to :func:`format_file_contents`.
390 is_pyi = force_pyi or src.suffix == ".pyi"
392 with tokenize.open(src) as src_buffer:
393 src_contents = src_buffer.read()
395 dst_contents = format_file_contents(
397 line_length=line_length,
400 force_py36=force_py36,
402 except NothingChanged:
405 if write_back == write_back.YES:
406 with open(src, "w", encoding=src_buffer.encoding) as f:
407 f.write(dst_contents)
408 elif write_back == write_back.DIFF:
409 src_name = f"{src} (original)"
410 dst_name = f"{src} (formatted)"
411 diff_contents = diff(src_contents, dst_contents, src_name, dst_name)
415 sys.stdout.write(diff_contents)
422 def format_stdin_to_stdout(
425 is_pyi: bool = False,
426 force_py36: bool = False,
427 write_back: WriteBack = WriteBack.NO,
429 """Format file on stdin. Return True if changed.
431 If `write_back` is True, write reformatted code back to stdout.
432 `line_length`, `fast`, `is_pyi`, and `force_py36` arguments are passed to
433 :func:`format_file_contents`.
435 src = sys.stdin.read()
438 dst = format_file_contents(
440 line_length=line_length,
443 force_py36=force_py36,
447 except NothingChanged:
451 if write_back == WriteBack.YES:
452 sys.stdout.write(dst)
453 elif write_back == WriteBack.DIFF:
454 src_name = "<stdin> (original)"
455 dst_name = "<stdin> (formatted)"
456 sys.stdout.write(diff(src, dst, src_name, dst_name))
459 def format_file_contents(
464 is_pyi: bool = False,
465 force_py36: bool = False,
467 """Reformat contents a file and return new contents.
469 If `fast` is False, additionally confirm that the reformatted code is
470 valid by calling :func:`assert_equivalent` and :func:`assert_stable` on it.
471 `line_length` is passed to :func:`format_str`.
473 if src_contents.strip() == "":
476 dst_contents = format_str(
477 src_contents, line_length=line_length, is_pyi=is_pyi, force_py36=force_py36
479 if src_contents == dst_contents:
483 assert_equivalent(src_contents, dst_contents)
487 line_length=line_length,
489 force_py36=force_py36,
498 is_pyi: bool = False,
499 force_py36: bool = False,
501 """Reformat a string and return new contents.
503 `line_length` determines how many characters per line are allowed.
505 src_node = lib2to3_parse(src_contents)
507 future_imports = get_future_imports(src_node)
508 elt = EmptyLineTracker(is_pyi=is_pyi)
509 py36 = force_py36 or is_python36(src_node)
510 lines = LineGenerator(
511 remove_u_prefix=py36 or "unicode_literals" in future_imports, is_pyi=is_pyi
515 for current_line in lines.visit(src_node):
516 for _ in range(after):
517 dst_contents += str(empty_line)
518 before, after = elt.maybe_empty_lines(current_line)
519 for _ in range(before):
520 dst_contents += str(empty_line)
521 for line in split_line(current_line, line_length=line_length, py36=py36):
522 dst_contents += str(line)
527 pygram.python_grammar_no_print_statement_no_exec_statement,
528 pygram.python_grammar_no_print_statement,
529 pygram.python_grammar,
533 def lib2to3_parse(src_txt: str) -> Node:
534 """Given a string with source, return the lib2to3 Node."""
535 grammar = pygram.python_grammar_no_print_statement
536 if src_txt[-1] != "\n":
537 nl = "\r\n" if "\r\n" in src_txt[:1024] else "\n"
539 for grammar in GRAMMARS:
540 drv = driver.Driver(grammar, pytree.convert)
542 result = drv.parse_string(src_txt, True)
545 except ParseError as pe:
546 lineno, column = pe.context[1]
547 lines = src_txt.splitlines()
549 faulty_line = lines[lineno - 1]
551 faulty_line = "<line number missing in source>"
552 exc = ValueError(f"Cannot parse: {lineno}:{column}: {faulty_line}")
556 if isinstance(result, Leaf):
557 result = Node(syms.file_input, [result])
561 def lib2to3_unparse(node: Node) -> str:
562 """Given a lib2to3 node, return its string representation."""
570 class Visitor(Generic[T]):
571 """Basic lib2to3 visitor that yields things of type `T` on `visit()`."""
573 def visit(self, node: LN) -> Iterator[T]:
574 """Main method to visit `node` and its children.
576 It tries to find a `visit_*()` method for the given `node.type`, like
577 `visit_simple_stmt` for Node objects or `visit_INDENT` for Leaf objects.
578 If no dedicated `visit_*()` method is found, chooses `visit_default()`
581 Then yields objects of type `T` from the selected visitor.
584 name = token.tok_name[node.type]
586 name = type_repr(node.type)
587 yield from getattr(self, f"visit_{name}", self.visit_default)(node)
589 def visit_default(self, node: LN) -> Iterator[T]:
590 """Default `visit_*()` implementation. Recurses to children of `node`."""
591 if isinstance(node, Node):
592 for child in node.children:
593 yield from self.visit(child)
597 class DebugVisitor(Visitor[T]):
600 def visit_default(self, node: LN) -> Iterator[T]:
601 indent = " " * (2 * self.tree_depth)
602 if isinstance(node, Node):
603 _type = type_repr(node.type)
604 out(f"{indent}{_type}", fg="yellow")
606 for child in node.children:
607 yield from self.visit(child)
610 out(f"{indent}/{_type}", fg="yellow", bold=False)
612 _type = token.tok_name.get(node.type, str(node.type))
613 out(f"{indent}{_type}", fg="blue", nl=False)
615 # We don't have to handle prefixes for `Node` objects since
616 # that delegates to the first child anyway.
617 out(f" {node.prefix!r}", fg="green", bold=False, nl=False)
618 out(f" {node.value!r}", fg="blue", bold=False)
621 def show(cls, code: str) -> None:
622 """Pretty-print the lib2to3 AST of a given string of `code`.
624 Convenience method for debugging.
626 v: DebugVisitor[None] = DebugVisitor()
627 list(v.visit(lib2to3_parse(code)))
630 KEYWORDS = set(keyword.kwlist)
631 WHITESPACE = {token.DEDENT, token.INDENT, token.NEWLINE}
632 FLOW_CONTROL = {"return", "raise", "break", "continue"}
643 STANDALONE_COMMENT = 153
644 LOGIC_OPERATORS = {"and", "or"}
669 STARS = {token.STAR, token.DOUBLESTAR}
672 syms.argument, # double star in arglist
673 syms.trailer, # single argument to call
675 syms.varargslist, # lambdas
677 UNPACKING_PARENTS = {
678 syms.atom, # single element of a list or set literal
716 COMPREHENSION_PRIORITY = 20
718 TERNARY_PRIORITY = 16
721 COMPARATOR_PRIORITY = 10
732 token.DOUBLESLASH: 4,
742 class BracketTracker:
743 """Keeps track of brackets on a line."""
746 bracket_match: Dict[Tuple[Depth, NodeType], Leaf] = Factory(dict)
747 delimiters: Dict[LeafID, Priority] = Factory(dict)
748 previous: Optional[Leaf] = None
749 _for_loop_variable: int = 0
750 _lambda_arguments: int = 0
752 def mark(self, leaf: Leaf) -> None:
753 """Mark `leaf` with bracket-related metadata. Keep track of delimiters.
755 All leaves receive an int `bracket_depth` field that stores how deep
756 within brackets a given leaf is. 0 means there are no enclosing brackets
757 that started on this line.
759 If a leaf is itself a closing bracket, it receives an `opening_bracket`
760 field that it forms a pair with. This is a one-directional link to
761 avoid reference cycles.
763 If a leaf is a delimiter (a token on which Black can split the line if
764 needed) and it's on depth 0, its `id()` is stored in the tracker's
767 if leaf.type == token.COMMENT:
770 self.maybe_decrement_after_for_loop_variable(leaf)
771 self.maybe_decrement_after_lambda_arguments(leaf)
772 if leaf.type in CLOSING_BRACKETS:
774 opening_bracket = self.bracket_match.pop((self.depth, leaf.type))
775 leaf.opening_bracket = opening_bracket
776 leaf.bracket_depth = self.depth
778 delim = is_split_before_delimiter(leaf, self.previous)
779 if delim and self.previous is not None:
780 self.delimiters[id(self.previous)] = delim
782 delim = is_split_after_delimiter(leaf, self.previous)
784 self.delimiters[id(leaf)] = delim
785 if leaf.type in OPENING_BRACKETS:
786 self.bracket_match[self.depth, BRACKET[leaf.type]] = leaf
789 self.maybe_increment_lambda_arguments(leaf)
790 self.maybe_increment_for_loop_variable(leaf)
792 def any_open_brackets(self) -> bool:
793 """Return True if there is an yet unmatched open bracket on the line."""
794 return bool(self.bracket_match)
796 def max_delimiter_priority(self, exclude: Iterable[LeafID] = ()) -> int:
797 """Return the highest priority of a delimiter found on the line.
799 Values are consistent with what `is_split_*_delimiter()` return.
800 Raises ValueError on no delimiters.
802 return max(v for k, v in self.delimiters.items() if k not in exclude)
804 def delimiter_count_with_priority(self, priority: int = 0) -> int:
805 """Return the number of delimiters with the given `priority`.
807 If no `priority` is passed, defaults to max priority on the line.
809 if not self.delimiters:
812 priority = priority or self.max_delimiter_priority()
813 return sum(1 for p in self.delimiters.values() if p == priority)
815 def maybe_increment_for_loop_variable(self, leaf: Leaf) -> bool:
816 """In a for loop, or comprehension, the variables are often unpacks.
818 To avoid splitting on the comma in this situation, increase the depth of
819 tokens between `for` and `in`.
821 if leaf.type == token.NAME and leaf.value == "for":
823 self._for_loop_variable += 1
828 def maybe_decrement_after_for_loop_variable(self, leaf: Leaf) -> bool:
829 """See `maybe_increment_for_loop_variable` above for explanation."""
830 if self._for_loop_variable and leaf.type == token.NAME and leaf.value == "in":
832 self._for_loop_variable -= 1
837 def maybe_increment_lambda_arguments(self, leaf: Leaf) -> bool:
838 """In a lambda expression, there might be more than one argument.
840 To avoid splitting on the comma in this situation, increase the depth of
841 tokens between `lambda` and `:`.
843 if leaf.type == token.NAME and leaf.value == "lambda":
845 self._lambda_arguments += 1
850 def maybe_decrement_after_lambda_arguments(self, leaf: Leaf) -> bool:
851 """See `maybe_increment_lambda_arguments` above for explanation."""
852 if self._lambda_arguments and leaf.type == token.COLON:
854 self._lambda_arguments -= 1
859 def get_open_lsqb(self) -> Optional[Leaf]:
860 """Return the most recent opening square bracket (if any)."""
861 return self.bracket_match.get((self.depth - 1, token.RSQB))
866 """Holds leaves and comments. Can be printed with `str(line)`."""
869 leaves: List[Leaf] = Factory(list)
870 comments: List[Tuple[Index, Leaf]] = Factory(list)
871 bracket_tracker: BracketTracker = Factory(BracketTracker)
872 inside_brackets: bool = False
873 should_explode: bool = False
875 def append(self, leaf: Leaf, preformatted: bool = False) -> None:
876 """Add a new `leaf` to the end of the line.
878 Unless `preformatted` is True, the `leaf` will receive a new consistent
879 whitespace prefix and metadata applied by :class:`BracketTracker`.
880 Trailing commas are maybe removed, unpacked for loop variables are
881 demoted from being delimiters.
883 Inline comments are put aside.
885 has_value = leaf.type in BRACKETS or bool(leaf.value.strip())
889 if token.COLON == leaf.type and self.is_class_paren_empty:
891 if self.leaves and not preformatted:
892 # Note: at this point leaf.prefix should be empty except for
893 # imports, for which we only preserve newlines.
894 leaf.prefix += whitespace(
895 leaf, complex_subscript=self.is_complex_subscript(leaf)
897 if self.inside_brackets or not preformatted:
898 self.bracket_tracker.mark(leaf)
899 self.maybe_remove_trailing_comma(leaf)
900 if not self.append_comment(leaf):
901 self.leaves.append(leaf)
903 def append_safe(self, leaf: Leaf, preformatted: bool = False) -> None:
904 """Like :func:`append()` but disallow invalid standalone comment structure.
906 Raises ValueError when any `leaf` is appended after a standalone comment
907 or when a standalone comment is not the first leaf on the line.
909 if self.bracket_tracker.depth == 0:
911 raise ValueError("cannot append to standalone comments")
913 if self.leaves and leaf.type == STANDALONE_COMMENT:
915 "cannot append standalone comments to a populated line"
918 self.append(leaf, preformatted=preformatted)
921 def is_comment(self) -> bool:
922 """Is this line a standalone comment?"""
923 return len(self.leaves) == 1 and self.leaves[0].type == STANDALONE_COMMENT
926 def is_decorator(self) -> bool:
927 """Is this line a decorator?"""
928 return bool(self) and self.leaves[0].type == token.AT
931 def is_import(self) -> bool:
932 """Is this an import line?"""
933 return bool(self) and is_import(self.leaves[0])
936 def is_class(self) -> bool:
937 """Is this line a class definition?"""
940 and self.leaves[0].type == token.NAME
941 and self.leaves[0].value == "class"
945 def is_stub_class(self) -> bool:
946 """Is this line a class definition with a body consisting only of "..."?"""
947 return self.is_class and self.leaves[-3:] == [
948 Leaf(token.DOT, ".") for _ in range(3)
952 def is_def(self) -> bool:
953 """Is this a function definition? (Also returns True for async defs.)"""
955 first_leaf = self.leaves[0]
960 second_leaf: Optional[Leaf] = self.leaves[1]
963 return (first_leaf.type == token.NAME and first_leaf.value == "def") or (
964 first_leaf.type == token.ASYNC
965 and second_leaf is not None
966 and second_leaf.type == token.NAME
967 and second_leaf.value == "def"
971 def is_flow_control(self) -> bool:
972 """Is this line a flow control statement?
974 Those are `return`, `raise`, `break`, and `continue`.
978 and self.leaves[0].type == token.NAME
979 and self.leaves[0].value in FLOW_CONTROL
983 def is_yield(self) -> bool:
984 """Is this line a yield statement?"""
987 and self.leaves[0].type == token.NAME
988 and self.leaves[0].value == "yield"
992 def is_class_paren_empty(self) -> bool:
993 """Is this a class with no base classes but using parentheses?
995 Those are unnecessary and should be removed.
999 and len(self.leaves) == 4
1001 and self.leaves[2].type == token.LPAR
1002 and self.leaves[2].value == "("
1003 and self.leaves[3].type == token.RPAR
1004 and self.leaves[3].value == ")"
1007 def contains_standalone_comments(self, depth_limit: int = sys.maxsize) -> bool:
1008 """If so, needs to be split before emitting."""
1009 for leaf in self.leaves:
1010 if leaf.type == STANDALONE_COMMENT:
1011 if leaf.bracket_depth <= depth_limit:
1016 def maybe_remove_trailing_comma(self, closing: Leaf) -> bool:
1017 """Remove trailing comma if there is one and it's safe."""
1020 and self.leaves[-1].type == token.COMMA
1021 and closing.type in CLOSING_BRACKETS
1025 if closing.type == token.RBRACE:
1026 self.remove_trailing_comma()
1029 if closing.type == token.RSQB:
1030 comma = self.leaves[-1]
1031 if comma.parent and comma.parent.type == syms.listmaker:
1032 self.remove_trailing_comma()
1035 # For parens let's check if it's safe to remove the comma.
1036 # Imports are always safe.
1038 self.remove_trailing_comma()
1041 # Otheriwsse, if the trailing one is the only one, we might mistakenly
1042 # change a tuple into a different type by removing the comma.
1043 depth = closing.bracket_depth + 1
1045 opening = closing.opening_bracket
1046 for _opening_index, leaf in enumerate(self.leaves):
1053 for leaf in self.leaves[_opening_index + 1 :]:
1057 bracket_depth = leaf.bracket_depth
1058 if bracket_depth == depth and leaf.type == token.COMMA:
1060 if leaf.parent and leaf.parent.type == syms.arglist:
1065 self.remove_trailing_comma()
1070 def append_comment(self, comment: Leaf) -> bool:
1071 """Add an inline or standalone comment to the line."""
1073 comment.type == STANDALONE_COMMENT
1074 and self.bracket_tracker.any_open_brackets()
1079 if comment.type != token.COMMENT:
1082 after = len(self.leaves) - 1
1084 comment.type = STANDALONE_COMMENT
1089 self.comments.append((after, comment))
1092 def comments_after(self, leaf: Leaf, _index: int = -1) -> Iterator[Leaf]:
1093 """Generate comments that should appear directly after `leaf`.
1095 Provide a non-negative leaf `_index` to speed up the function.
1098 for _index, _leaf in enumerate(self.leaves):
1105 for index, comment_after in self.comments:
1109 def remove_trailing_comma(self) -> None:
1110 """Remove the trailing comma and moves the comments attached to it."""
1111 comma_index = len(self.leaves) - 1
1112 for i in range(len(self.comments)):
1113 comment_index, comment = self.comments[i]
1114 if comment_index == comma_index:
1115 self.comments[i] = (comma_index - 1, comment)
1118 def is_complex_subscript(self, leaf: Leaf) -> bool:
1119 """Return True iff `leaf` is part of a slice with non-trivial exprs."""
1121 leaf if leaf.type == token.LSQB else self.bracket_tracker.get_open_lsqb()
1123 if open_lsqb is None:
1126 subscript_start = open_lsqb.next_sibling
1128 isinstance(subscript_start, Node)
1129 and subscript_start.type == syms.subscriptlist
1131 subscript_start = child_towards(subscript_start, leaf)
1132 return subscript_start is not None and any(
1133 n.type in TEST_DESCENDANTS for n in subscript_start.pre_order()
1136 def __str__(self) -> str:
1137 """Render the line."""
1141 indent = " " * self.depth
1142 leaves = iter(self.leaves)
1143 first = next(leaves)
1144 res = f"{first.prefix}{indent}{first.value}"
1147 for _, comment in self.comments:
1151 def __bool__(self) -> bool:
1152 """Return True if the line has leaves or comments."""
1153 return bool(self.leaves or self.comments)
1156 class UnformattedLines(Line):
1157 """Just like :class:`Line` but stores lines which aren't reformatted."""
1159 def append(self, leaf: Leaf, preformatted: bool = True) -> None:
1160 """Just add a new `leaf` to the end of the lines.
1162 The `preformatted` argument is ignored.
1164 Keeps track of indentation `depth`, which is useful when the user
1165 says `# fmt: on`. Otherwise, doesn't do anything with the `leaf`.
1168 list(generate_comments(leaf))
1169 except FormatOn as f_on:
1170 self.leaves.append(f_on.leaf_from_consumed(leaf))
1173 self.leaves.append(leaf)
1174 if leaf.type == token.INDENT:
1176 elif leaf.type == token.DEDENT:
1179 def __str__(self) -> str:
1180 """Render unformatted lines from leaves which were added with `append()`.
1182 `depth` is not used for indentation in this case.
1188 for leaf in self.leaves:
1192 def append_comment(self, comment: Leaf) -> bool:
1193 """Not implemented in this class. Raises `NotImplementedError`."""
1194 raise NotImplementedError("Unformatted lines don't store comments separately.")
1196 def maybe_remove_trailing_comma(self, closing: Leaf) -> bool:
1197 """Does nothing and returns False."""
1200 def maybe_increment_for_loop_variable(self, leaf: Leaf) -> bool:
1201 """Does nothing and returns False."""
1206 class EmptyLineTracker:
1207 """Provides a stateful method that returns the number of potential extra
1208 empty lines needed before and after the currently processed line.
1210 Note: this tracker works on lines that haven't been split yet. It assumes
1211 the prefix of the first leaf consists of optional newlines. Those newlines
1212 are consumed by `maybe_empty_lines()` and included in the computation.
1214 is_pyi: bool = False
1215 previous_line: Optional[Line] = None
1216 previous_after: int = 0
1217 previous_defs: List[int] = Factory(list)
1219 def maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
1220 """Return the number of extra empty lines before and after the `current_line`.
1222 This is for separating `def`, `async def` and `class` with extra empty
1223 lines (two on module-level), as well as providing an extra empty line
1224 after flow control keywords to make them more prominent.
1226 if isinstance(current_line, UnformattedLines):
1229 before, after = self._maybe_empty_lines(current_line)
1230 before -= self.previous_after
1231 self.previous_after = after
1232 self.previous_line = current_line
1233 return before, after
1235 def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
1237 if current_line.depth == 0:
1238 max_allowed = 1 if self.is_pyi else 2
1239 if current_line.leaves:
1240 # Consume the first leaf's extra newlines.
1241 first_leaf = current_line.leaves[0]
1242 before = first_leaf.prefix.count("\n")
1243 before = min(before, max_allowed)
1244 first_leaf.prefix = ""
1247 depth = current_line.depth
1248 while self.previous_defs and self.previous_defs[-1] >= depth:
1249 self.previous_defs.pop()
1251 before = 0 if depth else 1
1253 before = 1 if depth else 2
1254 is_decorator = current_line.is_decorator
1255 if is_decorator or current_line.is_def or current_line.is_class:
1256 if not is_decorator:
1257 self.previous_defs.append(depth)
1258 if self.previous_line is None:
1259 # Don't insert empty lines before the first line in the file.
1262 if self.previous_line.is_decorator:
1266 self.previous_line.is_comment
1267 and self.previous_line.depth == current_line.depth
1273 if self.previous_line.depth > current_line.depth:
1275 elif current_line.is_class or self.previous_line.is_class:
1276 if current_line.is_stub_class and self.previous_line.is_stub_class:
1284 if current_line.depth and newlines:
1290 and self.previous_line.is_import
1291 and not current_line.is_import
1292 and depth == self.previous_line.depth
1294 return (before or 1), 0
1300 class LineGenerator(Visitor[Line]):
1301 """Generates reformatted Line objects. Empty lines are not emitted.
1303 Note: destroys the tree it's visiting by mutating prefixes of its leaves
1304 in ways that will no longer stringify to valid Python code on the tree.
1306 is_pyi: bool = False
1307 current_line: Line = Factory(Line)
1308 remove_u_prefix: bool = False
1310 def line(self, indent: int = 0, type: Type[Line] = Line) -> Iterator[Line]:
1313 If the line is empty, only emit if it makes sense.
1314 If the line is too long, split it first and then generate.
1316 If any lines were generated, set up a new current_line.
1318 if not self.current_line:
1319 if self.current_line.__class__ == type:
1320 self.current_line.depth += indent
1322 self.current_line = type(depth=self.current_line.depth + indent)
1323 return # Line is empty, don't emit. Creating a new one unnecessary.
1325 complete_line = self.current_line
1326 self.current_line = type(depth=complete_line.depth + indent)
1329 def visit(self, node: LN) -> Iterator[Line]:
1330 """Main method to visit `node` and its children.
1332 Yields :class:`Line` objects.
1334 if isinstance(self.current_line, UnformattedLines):
1335 # File contained `# fmt: off`
1336 yield from self.visit_unformatted(node)
1339 yield from super().visit(node)
1341 def visit_default(self, node: LN) -> Iterator[Line]:
1342 """Default `visit_*()` implementation. Recurses to children of `node`."""
1343 if isinstance(node, Leaf):
1344 any_open_brackets = self.current_line.bracket_tracker.any_open_brackets()
1346 for comment in generate_comments(node):
1347 if any_open_brackets:
1348 # any comment within brackets is subject to splitting
1349 self.current_line.append(comment)
1350 elif comment.type == token.COMMENT:
1351 # regular trailing comment
1352 self.current_line.append(comment)
1353 yield from self.line()
1356 # regular standalone comment
1357 yield from self.line()
1359 self.current_line.append(comment)
1360 yield from self.line()
1362 except FormatOff as f_off:
1363 f_off.trim_prefix(node)
1364 yield from self.line(type=UnformattedLines)
1365 yield from self.visit(node)
1367 except FormatOn as f_on:
1368 # This only happens here if somebody says "fmt: on" multiple
1370 f_on.trim_prefix(node)
1371 yield from self.visit_default(node)
1374 normalize_prefix(node, inside_brackets=any_open_brackets)
1375 if node.type == token.STRING:
1376 normalize_string_prefix(node, remove_u_prefix=self.remove_u_prefix)
1377 normalize_string_quotes(node)
1378 if node.type not in WHITESPACE:
1379 self.current_line.append(node)
1380 yield from super().visit_default(node)
1382 def visit_INDENT(self, node: Node) -> Iterator[Line]:
1383 """Increase indentation level, maybe yield a line."""
1384 # In blib2to3 INDENT never holds comments.
1385 yield from self.line(+1)
1386 yield from self.visit_default(node)
1388 def visit_DEDENT(self, node: Node) -> Iterator[Line]:
1389 """Decrease indentation level, maybe yield a line."""
1390 # The current line might still wait for trailing comments. At DEDENT time
1391 # there won't be any (they would be prefixes on the preceding NEWLINE).
1392 # Emit the line then.
1393 yield from self.line()
1395 # While DEDENT has no value, its prefix may contain standalone comments
1396 # that belong to the current indentation level. Get 'em.
1397 yield from self.visit_default(node)
1399 # Finally, emit the dedent.
1400 yield from self.line(-1)
1403 self, node: Node, keywords: Set[str], parens: Set[str]
1404 ) -> Iterator[Line]:
1405 """Visit a statement.
1407 This implementation is shared for `if`, `while`, `for`, `try`, `except`,
1408 `def`, `with`, `class`, `assert` and assignments.
1410 The relevant Python language `keywords` for a given statement will be
1411 NAME leaves within it. This methods puts those on a separate line.
1413 `parens` holds a set of string leaf values immediately after which
1414 invisible parens should be put.
1416 normalize_invisible_parens(node, parens_after=parens)
1417 for child in node.children:
1418 if child.type == token.NAME and child.value in keywords: # type: ignore
1419 yield from self.line()
1421 yield from self.visit(child)
1423 def visit_suite(self, node: Node) -> Iterator[Line]:
1424 """Visit a suite."""
1425 if self.is_pyi and is_stub_suite(node):
1426 yield from self.visit(node.children[2])
1428 yield from self.visit_default(node)
1430 def visit_simple_stmt(self, node: Node) -> Iterator[Line]:
1431 """Visit a statement without nested statements."""
1432 is_suite_like = node.parent and node.parent.type in STATEMENT
1434 if self.is_pyi and is_stub_body(node):
1435 yield from self.visit_default(node)
1437 yield from self.line(+1)
1438 yield from self.visit_default(node)
1439 yield from self.line(-1)
1442 if not self.is_pyi or not node.parent or not is_stub_suite(node.parent):
1443 yield from self.line()
1444 yield from self.visit_default(node)
1446 def visit_async_stmt(self, node: Node) -> Iterator[Line]:
1447 """Visit `async def`, `async for`, `async with`."""
1448 yield from self.line()
1450 children = iter(node.children)
1451 for child in children:
1452 yield from self.visit(child)
1454 if child.type == token.ASYNC:
1457 internal_stmt = next(children)
1458 for child in internal_stmt.children:
1459 yield from self.visit(child)
1461 def visit_decorators(self, node: Node) -> Iterator[Line]:
1462 """Visit decorators."""
1463 for child in node.children:
1464 yield from self.line()
1465 yield from self.visit(child)
1467 def visit_SEMI(self, leaf: Leaf) -> Iterator[Line]:
1468 """Remove a semicolon and put the other statement on a separate line."""
1469 yield from self.line()
1471 def visit_ENDMARKER(self, leaf: Leaf) -> Iterator[Line]:
1472 """End of file. Process outstanding comments and end with a newline."""
1473 yield from self.visit_default(leaf)
1474 yield from self.line()
1476 def visit_unformatted(self, node: LN) -> Iterator[Line]:
1477 """Used when file contained a `# fmt: off`."""
1478 if isinstance(node, Node):
1479 for child in node.children:
1480 yield from self.visit(child)
1484 self.current_line.append(node)
1485 except FormatOn as f_on:
1486 f_on.trim_prefix(node)
1487 yield from self.line()
1488 yield from self.visit(node)
1490 if node.type == token.ENDMARKER:
1491 # somebody decided not to put a final `# fmt: on`
1492 yield from self.line()
1494 def __attrs_post_init__(self) -> None:
1495 """You are in a twisty little maze of passages."""
1498 self.visit_assert_stmt = partial(v, keywords={"assert"}, parens={"assert", ","})
1499 self.visit_if_stmt = partial(
1500 v, keywords={"if", "else", "elif"}, parens={"if", "elif"}
1502 self.visit_while_stmt = partial(v, keywords={"while", "else"}, parens={"while"})
1503 self.visit_for_stmt = partial(v, keywords={"for", "else"}, parens={"for", "in"})
1504 self.visit_try_stmt = partial(
1505 v, keywords={"try", "except", "else", "finally"}, parens=Ø
1507 self.visit_except_clause = partial(v, keywords={"except"}, parens=Ø)
1508 self.visit_with_stmt = partial(v, keywords={"with"}, parens=Ø)
1509 self.visit_funcdef = partial(v, keywords={"def"}, parens=Ø)
1510 self.visit_classdef = partial(v, keywords={"class"}, parens=Ø)
1511 self.visit_expr_stmt = partial(v, keywords=Ø, parens=ASSIGNMENTS)
1512 self.visit_return_stmt = partial(v, keywords={"return"}, parens={"return"})
1513 self.visit_import_from = partial(v, keywords=Ø, parens={"import"})
1514 self.visit_async_funcdef = self.visit_async_stmt
1515 self.visit_decorated = self.visit_decorators
1518 IMPLICIT_TUPLE = {syms.testlist, syms.testlist_star_expr, syms.exprlist}
1519 BRACKET = {token.LPAR: token.RPAR, token.LSQB: token.RSQB, token.LBRACE: token.RBRACE}
1520 OPENING_BRACKETS = set(BRACKET.keys())
1521 CLOSING_BRACKETS = set(BRACKET.values())
1522 BRACKETS = OPENING_BRACKETS | CLOSING_BRACKETS
1523 ALWAYS_NO_SPACE = CLOSING_BRACKETS | {token.COMMA, STANDALONE_COMMENT}
1526 def whitespace(leaf: Leaf, *, complex_subscript: bool) -> str: # noqa C901
1527 """Return whitespace prefix if needed for the given `leaf`.
1529 `complex_subscript` signals whether the given leaf is part of a subscription
1530 which has non-trivial arguments, like arithmetic expressions or function calls.
1538 if t in ALWAYS_NO_SPACE:
1541 if t == token.COMMENT:
1544 assert p is not None, f"INTERNAL ERROR: hand-made leaf without parent: {leaf!r}"
1545 if t == token.COLON and p.type not in {
1552 prev = leaf.prev_sibling
1554 prevp = preceding_leaf(p)
1555 if not prevp or prevp.type in OPENING_BRACKETS:
1558 if t == token.COLON:
1559 if prevp.type == token.COLON:
1562 elif prevp.type != token.COMMA and not complex_subscript:
1567 if prevp.type == token.EQUAL:
1569 if prevp.parent.type in {
1577 elif prevp.parent.type == syms.typedargslist:
1578 # A bit hacky: if the equal sign has whitespace, it means we
1579 # previously found it's a typed argument. So, we're using
1583 elif prevp.type in STARS:
1584 if is_vararg(prevp, within=VARARGS_PARENTS | UNPACKING_PARENTS):
1587 elif prevp.type == token.COLON:
1588 if prevp.parent and prevp.parent.type in {syms.subscript, syms.sliceop}:
1589 return SPACE if complex_subscript else NO
1593 and prevp.parent.type == syms.factor
1594 and prevp.type in MATH_OPERATORS
1599 prevp.type == token.RIGHTSHIFT
1601 and prevp.parent.type == syms.shift_expr
1602 and prevp.prev_sibling
1603 and prevp.prev_sibling.type == token.NAME
1604 and prevp.prev_sibling.value == "print" # type: ignore
1606 # Python 2 print chevron
1609 elif prev.type in OPENING_BRACKETS:
1612 if p.type in {syms.parameters, syms.arglist}:
1613 # untyped function signatures or calls
1614 if not prev or prev.type != token.COMMA:
1617 elif p.type == syms.varargslist:
1619 if prev and prev.type != token.COMMA:
1622 elif p.type == syms.typedargslist:
1623 # typed function signatures
1627 if t == token.EQUAL:
1628 if prev.type != syms.tname:
1631 elif prev.type == token.EQUAL:
1632 # A bit hacky: if the equal sign has whitespace, it means we
1633 # previously found it's a typed argument. So, we're using that, too.
1636 elif prev.type != token.COMMA:
1639 elif p.type == syms.tname:
1642 prevp = preceding_leaf(p)
1643 if not prevp or prevp.type != token.COMMA:
1646 elif p.type == syms.trailer:
1647 # attributes and calls
1648 if t == token.LPAR or t == token.RPAR:
1653 prevp = preceding_leaf(p)
1654 if not prevp or prevp.type != token.NUMBER:
1657 elif t == token.LSQB:
1660 elif prev.type != token.COMMA:
1663 elif p.type == syms.argument:
1665 if t == token.EQUAL:
1669 prevp = preceding_leaf(p)
1670 if not prevp or prevp.type == token.LPAR:
1673 elif prev.type in {token.EQUAL} | STARS:
1676 elif p.type == syms.decorator:
1680 elif p.type == syms.dotted_name:
1684 prevp = preceding_leaf(p)
1685 if not prevp or prevp.type == token.AT or prevp.type == token.DOT:
1688 elif p.type == syms.classdef:
1692 if prev and prev.type == token.LPAR:
1695 elif p.type in {syms.subscript, syms.sliceop}:
1698 assert p.parent is not None, "subscripts are always parented"
1699 if p.parent.type == syms.subscriptlist:
1704 elif not complex_subscript:
1707 elif p.type == syms.atom:
1708 if prev and t == token.DOT:
1709 # dots, but not the first one.
1712 elif p.type == syms.dictsetmaker:
1714 if prev and prev.type == token.DOUBLESTAR:
1717 elif p.type in {syms.factor, syms.star_expr}:
1720 prevp = preceding_leaf(p)
1721 if not prevp or prevp.type in OPENING_BRACKETS:
1724 prevp_parent = prevp.parent
1725 assert prevp_parent is not None
1726 if prevp.type == token.COLON and prevp_parent.type in {
1732 elif prevp.type == token.EQUAL and prevp_parent.type == syms.argument:
1735 elif t == token.NAME or t == token.NUMBER:
1738 elif p.type == syms.import_from:
1740 if prev and prev.type == token.DOT:
1743 elif t == token.NAME:
1747 if prev and prev.type == token.DOT:
1750 elif p.type == syms.sliceop:
1756 def preceding_leaf(node: Optional[LN]) -> Optional[Leaf]:
1757 """Return the first leaf that precedes `node`, if any."""
1759 res = node.prev_sibling
1761 if isinstance(res, Leaf):
1765 return list(res.leaves())[-1]
1774 def child_towards(ancestor: Node, descendant: LN) -> Optional[LN]:
1775 """Return the child of `ancestor` that contains `descendant`."""
1776 node: Optional[LN] = descendant
1777 while node and node.parent != ancestor:
1782 def is_split_after_delimiter(leaf: Leaf, previous: Leaf = None) -> int:
1783 """Return the priority of the `leaf` delimiter, given a line break after it.
1785 The delimiter priorities returned here are from those delimiters that would
1786 cause a line break after themselves.
1788 Higher numbers are higher priority.
1790 if leaf.type == token.COMMA:
1791 return COMMA_PRIORITY
1796 def is_split_before_delimiter(leaf: Leaf, previous: Leaf = None) -> int:
1797 """Return the priority of the `leaf` delimiter, given a line before after it.
1799 The delimiter priorities returned here are from those delimiters that would
1800 cause a line break before themselves.
1802 Higher numbers are higher priority.
1804 if is_vararg(leaf, within=VARARGS_PARENTS | UNPACKING_PARENTS):
1805 # * and ** might also be MATH_OPERATORS but in this case they are not.
1806 # Don't treat them as a delimiter.
1810 leaf.type == token.DOT
1812 and leaf.parent.type not in {syms.import_from, syms.dotted_name}
1813 and (previous is None or previous.type in CLOSING_BRACKETS)
1818 leaf.type in MATH_OPERATORS
1820 and leaf.parent.type not in {syms.factor, syms.star_expr}
1822 return MATH_PRIORITIES[leaf.type]
1824 if leaf.type in COMPARATORS:
1825 return COMPARATOR_PRIORITY
1828 leaf.type == token.STRING
1829 and previous is not None
1830 and previous.type == token.STRING
1832 return STRING_PRIORITY
1834 if leaf.type != token.NAME:
1840 and leaf.parent.type in {syms.comp_for, syms.old_comp_for}
1842 return COMPREHENSION_PRIORITY
1847 and leaf.parent.type in {syms.comp_if, syms.old_comp_if}
1849 return COMPREHENSION_PRIORITY
1851 if leaf.value in {"if", "else"} and leaf.parent and leaf.parent.type == syms.test:
1852 return TERNARY_PRIORITY
1854 if leaf.value == "is":
1855 return COMPARATOR_PRIORITY
1860 and leaf.parent.type in {syms.comp_op, syms.comparison}
1862 previous is not None
1863 and previous.type == token.NAME
1864 and previous.value == "not"
1867 return COMPARATOR_PRIORITY
1872 and leaf.parent.type == syms.comp_op
1874 previous is not None
1875 and previous.type == token.NAME
1876 and previous.value == "is"
1879 return COMPARATOR_PRIORITY
1881 if leaf.value in LOGIC_OPERATORS and leaf.parent:
1882 return LOGIC_PRIORITY
1887 def generate_comments(leaf: LN) -> Iterator[Leaf]:
1888 """Clean the prefix of the `leaf` and generate comments from it, if any.
1890 Comments in lib2to3 are shoved into the whitespace prefix. This happens
1891 in `pgen2/driver.py:Driver.parse_tokens()`. This was a brilliant implementation
1892 move because it does away with modifying the grammar to include all the
1893 possible places in which comments can be placed.
1895 The sad consequence for us though is that comments don't "belong" anywhere.
1896 This is why this function generates simple parentless Leaf objects for
1897 comments. We simply don't know what the correct parent should be.
1899 No matter though, we can live without this. We really only need to
1900 differentiate between inline and standalone comments. The latter don't
1901 share the line with any code.
1903 Inline comments are emitted as regular token.COMMENT leaves. Standalone
1904 are emitted with a fake STANDALONE_COMMENT token identifier.
1915 for index, line in enumerate(p.split("\n")):
1916 consumed += len(line) + 1 # adding the length of the split '\n'
1917 line = line.lstrip()
1920 if not line.startswith("#"):
1923 if index == 0 and leaf.type != token.ENDMARKER:
1924 comment_type = token.COMMENT # simple trailing comment
1926 comment_type = STANDALONE_COMMENT
1927 comment = make_comment(line)
1928 yield Leaf(comment_type, comment, prefix="\n" * nlines)
1930 if comment in {"# fmt: on", "# yapf: enable"}:
1931 raise FormatOn(consumed)
1933 if comment in {"# fmt: off", "# yapf: disable"}:
1934 if comment_type == STANDALONE_COMMENT:
1935 raise FormatOff(consumed)
1937 prev = preceding_leaf(leaf)
1938 if not prev or prev.type in WHITESPACE: # standalone comment in disguise
1939 raise FormatOff(consumed)
1944 def make_comment(content: str) -> str:
1945 """Return a consistently formatted comment from the given `content` string.
1947 All comments (except for "##", "#!", "#:") should have a single space between
1948 the hash sign and the content.
1950 If `content` didn't start with a hash sign, one is provided.
1952 content = content.rstrip()
1956 if content[0] == "#":
1957 content = content[1:]
1958 if content and content[0] not in " !:#":
1959 content = " " + content
1960 return "#" + content
1964 line: Line, line_length: int, inner: bool = False, py36: bool = False
1965 ) -> Iterator[Line]:
1966 """Split a `line` into potentially many lines.
1968 They should fit in the allotted `line_length` but might not be able to.
1969 `inner` signifies that there were a pair of brackets somewhere around the
1970 current `line`, possibly transitively. This means we can fallback to splitting
1971 by delimiters if the LHS/RHS don't yield any results.
1973 If `py36` is True, splitting may generate syntax that is only compatible
1974 with Python 3.6 and later.
1976 if isinstance(line, UnformattedLines) or line.is_comment:
1980 line_str = str(line).strip("\n")
1981 if not line.should_explode and is_line_short_enough(
1982 line, line_length=line_length, line_str=line_str
1987 split_funcs: List[SplitFunc]
1989 split_funcs = [left_hand_split]
1992 def rhs(line: Line, py36: bool = False) -> Iterator[Line]:
1993 for omit in generate_trailers_to_omit(line, line_length):
1994 lines = list(right_hand_split(line, line_length, py36, omit=omit))
1995 if is_line_short_enough(lines[0], line_length=line_length):
1999 # All splits failed, best effort split with no omits.
2000 # This mostly happens to multiline strings that are by definition
2001 # reported as not fitting a single line.
2002 yield from right_hand_split(line, py36)
2004 if line.inside_brackets:
2005 split_funcs = [delimiter_split, standalone_comment_split, rhs]
2008 for split_func in split_funcs:
2009 # We are accumulating lines in `result` because we might want to abort
2010 # mission and return the original line in the end, or attempt a different
2012 result: List[Line] = []
2014 for l in split_func(line, py36):
2015 if str(l).strip("\n") == line_str:
2016 raise CannotSplit("Split function returned an unchanged result")
2019 split_line(l, line_length=line_length, inner=True, py36=py36)
2021 except CannotSplit as cs:
2032 def left_hand_split(line: Line, py36: bool = False) -> Iterator[Line]:
2033 """Split line into many lines, starting with the first matching bracket pair.
2035 Note: this usually looks weird, only use this for function definitions.
2036 Prefer RHS otherwise. This is why this function is not symmetrical with
2037 :func:`right_hand_split` which also handles optional parentheses.
2039 head = Line(depth=line.depth)
2040 body = Line(depth=line.depth + 1, inside_brackets=True)
2041 tail = Line(depth=line.depth)
2042 tail_leaves: List[Leaf] = []
2043 body_leaves: List[Leaf] = []
2044 head_leaves: List[Leaf] = []
2045 current_leaves = head_leaves
2046 matching_bracket = None
2047 for leaf in line.leaves:
2049 current_leaves is body_leaves
2050 and leaf.type in CLOSING_BRACKETS
2051 and leaf.opening_bracket is matching_bracket
2053 current_leaves = tail_leaves if body_leaves else head_leaves
2054 current_leaves.append(leaf)
2055 if current_leaves is head_leaves:
2056 if leaf.type in OPENING_BRACKETS:
2057 matching_bracket = leaf
2058 current_leaves = body_leaves
2059 # Since body is a new indent level, remove spurious leading whitespace.
2061 normalize_prefix(body_leaves[0], inside_brackets=True)
2062 # Build the new lines.
2063 for result, leaves in (head, head_leaves), (body, body_leaves), (tail, tail_leaves):
2065 result.append(leaf, preformatted=True)
2066 for comment_after in line.comments_after(leaf):
2067 result.append(comment_after, preformatted=True)
2068 bracket_split_succeeded_or_raise(head, body, tail)
2069 for result in (head, body, tail):
2074 def right_hand_split(
2075 line: Line, line_length: int, py36: bool = False, omit: Collection[LeafID] = ()
2076 ) -> Iterator[Line]:
2077 """Split line into many lines, starting with the last matching bracket pair.
2079 If the split was by optional parentheses, attempt splitting without them, too.
2080 `omit` is a collection of closing bracket IDs that shouldn't be considered for
2083 Note: running this function modifies `bracket_depth` on the leaves of `line`.
2085 head = Line(depth=line.depth)
2086 body = Line(depth=line.depth + 1, inside_brackets=True)
2087 tail = Line(depth=line.depth)
2088 tail_leaves: List[Leaf] = []
2089 body_leaves: List[Leaf] = []
2090 head_leaves: List[Leaf] = []
2091 current_leaves = tail_leaves
2092 opening_bracket = None
2093 closing_bracket = None
2094 for leaf in reversed(line.leaves):
2095 if current_leaves is body_leaves:
2096 if leaf is opening_bracket:
2097 current_leaves = head_leaves if body_leaves else tail_leaves
2098 current_leaves.append(leaf)
2099 if current_leaves is tail_leaves:
2100 if leaf.type in CLOSING_BRACKETS and id(leaf) not in omit:
2101 opening_bracket = leaf.opening_bracket
2102 closing_bracket = leaf
2103 current_leaves = body_leaves
2104 tail_leaves.reverse()
2105 body_leaves.reverse()
2106 head_leaves.reverse()
2107 # Since body is a new indent level, remove spurious leading whitespace.
2109 normalize_prefix(body_leaves[0], inside_brackets=True)
2111 # No `head` means the split failed. Either `tail` has all content or
2112 # the matching `opening_bracket` wasn't available on `line` anymore.
2113 raise CannotSplit("No brackets found")
2115 # Build the new lines.
2116 for result, leaves in (head, head_leaves), (body, body_leaves), (tail, tail_leaves):
2118 result.append(leaf, preformatted=True)
2119 for comment_after in line.comments_after(leaf):
2120 result.append(comment_after, preformatted=True)
2121 bracket_split_succeeded_or_raise(head, body, tail)
2122 assert opening_bracket and closing_bracket
2124 # the opening bracket is an optional paren
2125 opening_bracket.type == token.LPAR
2126 and not opening_bracket.value
2127 # the closing bracket is an optional paren
2128 and closing_bracket.type == token.RPAR
2129 and not closing_bracket.value
2130 # there are no standalone comments in the body
2131 and not line.contains_standalone_comments(0)
2132 # and it's not an import (optional parens are the only thing we can split
2133 # on in this case; attempting a split without them is a waste of time)
2134 and not line.is_import
2136 omit = {id(closing_bracket), *omit}
2137 if can_omit_invisible_parens(body, line_length):
2139 yield from right_hand_split(line, line_length, py36=py36, omit=omit)
2144 ensure_visible(opening_bracket)
2145 ensure_visible(closing_bracket)
2146 body.should_explode = should_explode(body, opening_bracket)
2147 for result in (head, body, tail):
2152 def bracket_split_succeeded_or_raise(head: Line, body: Line, tail: Line) -> None:
2153 """Raise :exc:`CannotSplit` if the last left- or right-hand split failed.
2155 Do nothing otherwise.
2157 A left- or right-hand split is based on a pair of brackets. Content before
2158 (and including) the opening bracket is left on one line, content inside the
2159 brackets is put on a separate line, and finally content starting with and
2160 following the closing bracket is put on a separate line.
2162 Those are called `head`, `body`, and `tail`, respectively. If the split
2163 produced the same line (all content in `head`) or ended up with an empty `body`
2164 and the `tail` is just the closing bracket, then it's considered failed.
2166 tail_len = len(str(tail).strip())
2169 raise CannotSplit("Splitting brackets produced the same line")
2173 f"Splitting brackets on an empty body to save "
2174 f"{tail_len} characters is not worth it"
2178 def dont_increase_indentation(split_func: SplitFunc) -> SplitFunc:
2179 """Normalize prefix of the first leaf in every line returned by `split_func`.
2181 This is a decorator over relevant split functions.
2185 def split_wrapper(line: Line, py36: bool = False) -> Iterator[Line]:
2186 for l in split_func(line, py36):
2187 normalize_prefix(l.leaves[0], inside_brackets=True)
2190 return split_wrapper
2193 @dont_increase_indentation
2194 def delimiter_split(line: Line, py36: bool = False) -> Iterator[Line]:
2195 """Split according to delimiters of the highest priority.
2197 If `py36` is True, the split will add trailing commas also in function
2198 signatures that contain `*` and `**`.
2201 last_leaf = line.leaves[-1]
2203 raise CannotSplit("Line empty")
2205 bt = line.bracket_tracker
2207 delimiter_priority = bt.max_delimiter_priority(exclude={id(last_leaf)})
2209 raise CannotSplit("No delimiters found")
2211 if delimiter_priority == DOT_PRIORITY:
2212 if bt.delimiter_count_with_priority(delimiter_priority) == 1:
2213 raise CannotSplit("Splitting a single attribute from its owner looks wrong")
2215 current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
2216 lowest_depth = sys.maxsize
2217 trailing_comma_safe = True
2219 def append_to_line(leaf: Leaf) -> Iterator[Line]:
2220 """Append `leaf` to current line or to new line if appending impossible."""
2221 nonlocal current_line
2223 current_line.append_safe(leaf, preformatted=True)
2224 except ValueError as ve:
2227 current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
2228 current_line.append(leaf)
2230 for index, leaf in enumerate(line.leaves):
2231 yield from append_to_line(leaf)
2233 for comment_after in line.comments_after(leaf, index):
2234 yield from append_to_line(comment_after)
2236 lowest_depth = min(lowest_depth, leaf.bracket_depth)
2237 if leaf.bracket_depth == lowest_depth and is_vararg(
2238 leaf, within=VARARGS_PARENTS
2240 trailing_comma_safe = trailing_comma_safe and py36
2241 leaf_priority = bt.delimiters.get(id(leaf))
2242 if leaf_priority == delimiter_priority:
2245 current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
2249 and delimiter_priority == COMMA_PRIORITY
2250 and current_line.leaves[-1].type != token.COMMA
2251 and current_line.leaves[-1].type != STANDALONE_COMMENT
2253 current_line.append(Leaf(token.COMMA, ","))
2257 @dont_increase_indentation
2258 def standalone_comment_split(line: Line, py36: bool = False) -> Iterator[Line]:
2259 """Split standalone comments from the rest of the line."""
2260 if not line.contains_standalone_comments(0):
2261 raise CannotSplit("Line does not have any standalone comments")
2263 current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
2265 def append_to_line(leaf: Leaf) -> Iterator[Line]:
2266 """Append `leaf` to current line or to new line if appending impossible."""
2267 nonlocal current_line
2269 current_line.append_safe(leaf, preformatted=True)
2270 except ValueError as ve:
2273 current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
2274 current_line.append(leaf)
2276 for index, leaf in enumerate(line.leaves):
2277 yield from append_to_line(leaf)
2279 for comment_after in line.comments_after(leaf, index):
2280 yield from append_to_line(comment_after)
2286 def is_import(leaf: Leaf) -> bool:
2287 """Return True if the given leaf starts an import statement."""
2294 (v == "import" and p and p.type == syms.import_name)
2295 or (v == "from" and p and p.type == syms.import_from)
2300 def normalize_prefix(leaf: Leaf, *, inside_brackets: bool) -> None:
2301 """Leave existing extra newlines if not `inside_brackets`. Remove everything
2304 Note: don't use backslashes for formatting or you'll lose your voting rights.
2306 if not inside_brackets:
2307 spl = leaf.prefix.split("#")
2308 if "\\" not in spl[0]:
2309 nl_count = spl[-1].count("\n")
2312 leaf.prefix = "\n" * nl_count
2318 def normalize_string_prefix(leaf: Leaf, remove_u_prefix: bool = False) -> None:
2319 """Make all string prefixes lowercase.
2321 If remove_u_prefix is given, also removes any u prefix from the string.
2323 Note: Mutates its argument.
2325 match = re.match(r"^([furbFURB]*)(.*)$", leaf.value, re.DOTALL)
2326 assert match is not None, f"failed to match string {leaf.value!r}"
2327 orig_prefix = match.group(1)
2328 new_prefix = orig_prefix.lower()
2330 new_prefix = new_prefix.replace("u", "")
2331 leaf.value = f"{new_prefix}{match.group(2)}"
2334 def normalize_string_quotes(leaf: Leaf) -> None:
2335 """Prefer double quotes but only if it doesn't cause more escaping.
2337 Adds or removes backslashes as appropriate. Doesn't parse and fix
2338 strings nested in f-strings (yet).
2340 Note: Mutates its argument.
2342 value = leaf.value.lstrip("furbFURB")
2343 if value[:3] == '"""':
2346 elif value[:3] == "'''":
2349 elif value[0] == '"':
2355 first_quote_pos = leaf.value.find(orig_quote)
2356 if first_quote_pos == -1:
2357 return # There's an internal error
2359 prefix = leaf.value[:first_quote_pos]
2360 unescaped_new_quote = re.compile(rf"(([^\\]|^)(\\\\)*){new_quote}")
2361 escaped_new_quote = re.compile(rf"([^\\]|^)\\(\\\\)*{new_quote}")
2362 escaped_orig_quote = re.compile(rf"([^\\]|^)\\(\\\\)*{orig_quote}")
2363 body = leaf.value[first_quote_pos + len(orig_quote) : -len(orig_quote)]
2364 if "r" in prefix.casefold():
2365 if unescaped_new_quote.search(body):
2366 # There's at least one unescaped new_quote in this raw string
2367 # so converting is impossible
2370 # Do not introduce or remove backslashes in raw strings
2373 # remove unnecessary quotes
2374 new_body = sub_twice(escaped_new_quote, rf"\1\2{new_quote}", body)
2375 if body != new_body:
2376 # Consider the string without unnecessary quotes as the original
2378 leaf.value = f"{prefix}{orig_quote}{body}{orig_quote}"
2379 new_body = sub_twice(escaped_orig_quote, rf"\1\2{orig_quote}", new_body)
2380 new_body = sub_twice(unescaped_new_quote, rf"\1\\{new_quote}", new_body)
2381 if new_quote == '"""' and new_body[-1] == '"':
2383 new_body = new_body[:-1] + '\\"'
2384 orig_escape_count = body.count("\\")
2385 new_escape_count = new_body.count("\\")
2386 if new_escape_count > orig_escape_count:
2387 return # Do not introduce more escaping
2389 if new_escape_count == orig_escape_count and orig_quote == '"':
2390 return # Prefer double quotes
2392 leaf.value = f"{prefix}{new_quote}{new_body}{new_quote}"
2395 def normalize_invisible_parens(node: Node, parens_after: Set[str]) -> None:
2396 """Make existing optional parentheses invisible or create new ones.
2398 `parens_after` is a set of string leaf values immeditely after which parens
2401 Standardizes on visible parentheses for single-element tuples, and keeps
2402 existing visible parentheses for other tuples and generator expressions.
2405 list(generate_comments(node))
2407 return # This `node` has a prefix with `# fmt: off`, don't mess with parens.
2410 for index, child in enumerate(list(node.children)):
2412 if child.type == syms.atom:
2413 maybe_make_parens_invisible_in_atom(child)
2414 elif is_one_tuple(child):
2415 # wrap child in visible parentheses
2416 lpar = Leaf(token.LPAR, "(")
2417 rpar = Leaf(token.RPAR, ")")
2419 node.insert_child(index, Node(syms.atom, [lpar, child, rpar]))
2420 elif node.type == syms.import_from:
2421 # "import from" nodes store parentheses directly as part of
2423 if child.type == token.LPAR:
2424 # make parentheses invisible
2425 child.value = "" # type: ignore
2426 node.children[-1].value = "" # type: ignore
2427 elif child.type != token.STAR:
2428 # insert invisible parentheses
2429 node.insert_child(index, Leaf(token.LPAR, ""))
2430 node.append_child(Leaf(token.RPAR, ""))
2433 elif not (isinstance(child, Leaf) and is_multiline_string(child)):
2434 # wrap child in invisible parentheses
2435 lpar = Leaf(token.LPAR, "")
2436 rpar = Leaf(token.RPAR, "")
2437 index = child.remove() or 0
2438 node.insert_child(index, Node(syms.atom, [lpar, child, rpar]))
2440 check_lpar = isinstance(child, Leaf) and child.value in parens_after
2443 def maybe_make_parens_invisible_in_atom(node: LN) -> bool:
2444 """If it's safe, make the parens in the atom `node` invisible, recusively."""
2446 node.type != syms.atom
2447 or is_empty_tuple(node)
2448 or is_one_tuple(node)
2450 or max_delimiter_priority_in_atom(node) >= COMMA_PRIORITY
2454 first = node.children[0]
2455 last = node.children[-1]
2456 if first.type == token.LPAR and last.type == token.RPAR:
2457 # make parentheses invisible
2458 first.value = "" # type: ignore
2459 last.value = "" # type: ignore
2460 if len(node.children) > 1:
2461 maybe_make_parens_invisible_in_atom(node.children[1])
2467 def is_empty_tuple(node: LN) -> bool:
2468 """Return True if `node` holds an empty tuple."""
2470 node.type == syms.atom
2471 and len(node.children) == 2
2472 and node.children[0].type == token.LPAR
2473 and node.children[1].type == token.RPAR
2477 def is_one_tuple(node: LN) -> bool:
2478 """Return True if `node` holds a tuple with one element, with or without parens."""
2479 if node.type == syms.atom:
2480 if len(node.children) != 3:
2483 lpar, gexp, rpar = node.children
2485 lpar.type == token.LPAR
2486 and gexp.type == syms.testlist_gexp
2487 and rpar.type == token.RPAR
2491 return len(gexp.children) == 2 and gexp.children[1].type == token.COMMA
2494 node.type in IMPLICIT_TUPLE
2495 and len(node.children) == 2
2496 and node.children[1].type == token.COMMA
2500 def is_yield(node: LN) -> bool:
2501 """Return True if `node` holds a `yield` or `yield from` expression."""
2502 if node.type == syms.yield_expr:
2505 if node.type == token.NAME and node.value == "yield": # type: ignore
2508 if node.type != syms.atom:
2511 if len(node.children) != 3:
2514 lpar, expr, rpar = node.children
2515 if lpar.type == token.LPAR and rpar.type == token.RPAR:
2516 return is_yield(expr)
2521 def is_vararg(leaf: Leaf, within: Set[NodeType]) -> bool:
2522 """Return True if `leaf` is a star or double star in a vararg or kwarg.
2524 If `within` includes VARARGS_PARENTS, this applies to function signatures.
2525 If `within` includes UNPACKING_PARENTS, it applies to right hand-side
2526 extended iterable unpacking (PEP 3132) and additional unpacking
2527 generalizations (PEP 448).
2529 if leaf.type not in STARS or not leaf.parent:
2533 if p.type == syms.star_expr:
2534 # Star expressions are also used as assignment targets in extended
2535 # iterable unpacking (PEP 3132). See what its parent is instead.
2541 return p.type in within
2544 def is_multiline_string(leaf: Leaf) -> bool:
2545 """Return True if `leaf` is a multiline string that actually spans many lines."""
2546 value = leaf.value.lstrip("furbFURB")
2547 return value[:3] in {'"""', "'''"} and "\n" in value
2550 def is_stub_suite(node: Node) -> bool:
2551 """Return True if `node` is a suite with a stub body."""
2553 len(node.children) != 4
2554 or node.children[0].type != token.NEWLINE
2555 or node.children[1].type != token.INDENT
2556 or node.children[3].type != token.DEDENT
2560 return is_stub_body(node.children[2])
2563 def is_stub_body(node: LN) -> bool:
2564 """Return True if `node` is a simple statement containing an ellipsis."""
2565 if not isinstance(node, Node) or node.type != syms.simple_stmt:
2568 if len(node.children) != 2:
2571 child = node.children[0]
2573 child.type == syms.atom
2574 and len(child.children) == 3
2575 and all(leaf == Leaf(token.DOT, ".") for leaf in child.children)
2579 def max_delimiter_priority_in_atom(node: LN) -> int:
2580 """Return maximum delimiter priority inside `node`.
2582 This is specific to atoms with contents contained in a pair of parentheses.
2583 If `node` isn't an atom or there are no enclosing parentheses, returns 0.
2585 if node.type != syms.atom:
2588 first = node.children[0]
2589 last = node.children[-1]
2590 if not (first.type == token.LPAR and last.type == token.RPAR):
2593 bt = BracketTracker()
2594 for c in node.children[1:-1]:
2595 if isinstance(c, Leaf):
2598 for leaf in c.leaves():
2601 return bt.max_delimiter_priority()
2607 def ensure_visible(leaf: Leaf) -> None:
2608 """Make sure parentheses are visible.
2610 They could be invisible as part of some statements (see
2611 :func:`normalize_invible_parens` and :func:`visit_import_from`).
2613 if leaf.type == token.LPAR:
2615 elif leaf.type == token.RPAR:
2619 def should_explode(line: Line, opening_bracket: Leaf) -> bool:
2620 """Should `line` immediately be split with `delimiter_split()` after RHS?"""
2622 opening_bracket.parent
2623 and opening_bracket.parent.type in {syms.atom, syms.import_from}
2624 and opening_bracket.value in "[{("
2629 last_leaf = line.leaves[-1]
2630 exclude = {id(last_leaf)} if last_leaf.type == token.COMMA else set()
2631 max_priority = line.bracket_tracker.max_delimiter_priority(exclude=exclude)
2632 except (IndexError, ValueError):
2635 return max_priority == COMMA_PRIORITY
2638 def is_python36(node: Node) -> bool:
2639 """Return True if the current file is using Python 3.6+ features.
2641 Currently looking for:
2643 - trailing commas after * or ** in function signatures and calls.
2645 for n in node.pre_order():
2646 if n.type == token.STRING:
2647 value_head = n.value[:2] # type: ignore
2648 if value_head in {'f"', 'F"', "f'", "F'", "rf", "fr", "RF", "FR"}:
2652 n.type in {syms.typedargslist, syms.arglist}
2654 and n.children[-1].type == token.COMMA
2656 for ch in n.children:
2657 if ch.type in STARS:
2660 if ch.type == syms.argument:
2661 for argch in ch.children:
2662 if argch.type in STARS:
2668 def generate_trailers_to_omit(line: Line, line_length: int) -> Iterator[Set[LeafID]]:
2669 """Generate sets of closing bracket IDs that should be omitted in a RHS.
2671 Brackets can be omitted if the entire trailer up to and including
2672 a preceding closing bracket fits in one line.
2674 Yielded sets are cumulative (contain results of previous yields, too). First
2678 omit: Set[LeafID] = set()
2681 length = 4 * line.depth
2682 opening_bracket = None
2683 closing_bracket = None
2684 optional_brackets: Set[LeafID] = set()
2685 inner_brackets: Set[LeafID] = set()
2686 for index, leaf, leaf_length in enumerate_with_length(line, reversed=True):
2687 length += leaf_length
2688 if length > line_length:
2691 has_inline_comment = leaf_length > len(leaf.value) + len(leaf.prefix)
2692 if leaf.type == STANDALONE_COMMENT or has_inline_comment:
2695 optional_brackets.discard(id(leaf))
2697 if leaf is opening_bracket:
2698 opening_bracket = None
2699 elif leaf.type in CLOSING_BRACKETS:
2700 inner_brackets.add(id(leaf))
2701 elif leaf.type in CLOSING_BRACKETS:
2703 optional_brackets.add(id(opening_bracket))
2706 if index > 0 and line.leaves[index - 1].type in OPENING_BRACKETS:
2707 # Empty brackets would fail a split so treat them as "inner"
2708 # brackets (e.g. only add them to the `omit` set if another
2709 # pair of brackets was good enough.
2710 inner_brackets.add(id(leaf))
2713 opening_bracket = leaf.opening_bracket
2715 omit.add(id(closing_bracket))
2716 omit.update(inner_brackets)
2717 inner_brackets.clear()
2719 closing_bracket = leaf
2722 def get_future_imports(node: Node) -> Set[str]:
2723 """Return a set of __future__ imports in the file."""
2725 for child in node.children:
2726 if child.type != syms.simple_stmt:
2728 first_child = child.children[0]
2729 if isinstance(first_child, Leaf):
2730 # Continue looking if we see a docstring; otherwise stop.
2732 len(child.children) == 2
2733 and first_child.type == token.STRING
2734 and child.children[1].type == token.NEWLINE
2739 elif first_child.type == syms.import_from:
2740 module_name = first_child.children[1]
2741 if not isinstance(module_name, Leaf) or module_name.value != "__future__":
2743 for import_from_child in first_child.children[3:]:
2744 if isinstance(import_from_child, Leaf):
2745 if import_from_child.type == token.NAME:
2746 imports.add(import_from_child.value)
2748 assert import_from_child.type == syms.import_as_names
2749 for leaf in import_from_child.children:
2750 if isinstance(leaf, Leaf) and leaf.type == token.NAME:
2751 imports.add(leaf.value)
2757 PYTHON_EXTENSIONS = {".py", ".pyi"}
2758 BLACKLISTED_DIRECTORIES = {
2771 def gen_python_files_in_dir(path: Path) -> Iterator[Path]:
2772 """Generate all files under `path` which aren't under BLACKLISTED_DIRECTORIES
2773 and have one of the PYTHON_EXTENSIONS.
2775 for child in path.iterdir():
2777 if child.name in BLACKLISTED_DIRECTORIES:
2780 yield from gen_python_files_in_dir(child)
2782 elif child.is_file() and child.suffix in PYTHON_EXTENSIONS:
2788 """Provides a reformatting counter. Can be rendered with `str(report)`."""
2791 change_count: int = 0
2793 failure_count: int = 0
2795 def done(self, src: Path, changed: Changed) -> None:
2796 """Increment the counter for successful reformatting. Write out a message."""
2797 if changed is Changed.YES:
2798 reformatted = "would reformat" if self.check else "reformatted"
2800 out(f"{reformatted} {src}")
2801 self.change_count += 1
2804 if changed is Changed.NO:
2805 msg = f"{src} already well formatted, good job."
2807 msg = f"{src} wasn't modified on disk since last run."
2808 out(msg, bold=False)
2809 self.same_count += 1
2811 def failed(self, src: Path, message: str) -> None:
2812 """Increment the counter for failed reformatting. Write out a message."""
2813 err(f"error: cannot format {src}: {message}")
2814 self.failure_count += 1
2817 def return_code(self) -> int:
2818 """Return the exit code that the app should use.
2820 This considers the current state of changed files and failures:
2821 - if there were any failures, return 123;
2822 - if any files were changed and --check is being used, return 1;
2823 - otherwise return 0.
2825 # According to http://tldp.org/LDP/abs/html/exitcodes.html starting with
2826 # 126 we have special returncodes reserved by the shell.
2827 if self.failure_count:
2830 elif self.change_count and self.check:
2835 def __str__(self) -> str:
2836 """Render a color report of the current state.
2838 Use `click.unstyle` to remove colors.
2841 reformatted = "would be reformatted"
2842 unchanged = "would be left unchanged"
2843 failed = "would fail to reformat"
2845 reformatted = "reformatted"
2846 unchanged = "left unchanged"
2847 failed = "failed to reformat"
2849 if self.change_count:
2850 s = "s" if self.change_count > 1 else ""
2852 click.style(f"{self.change_count} file{s} {reformatted}", bold=True)
2855 s = "s" if self.same_count > 1 else ""
2856 report.append(f"{self.same_count} file{s} {unchanged}")
2857 if self.failure_count:
2858 s = "s" if self.failure_count > 1 else ""
2860 click.style(f"{self.failure_count} file{s} {failed}", fg="red")
2862 return ", ".join(report) + "."
2865 def assert_equivalent(src: str, dst: str) -> None:
2866 """Raise AssertionError if `src` and `dst` aren't equivalent."""
2871 def _v(node: ast.AST, depth: int = 0) -> Iterator[str]:
2872 """Simple visitor generating strings to compare ASTs by content."""
2873 yield f"{' ' * depth}{node.__class__.__name__}("
2875 for field in sorted(node._fields):
2877 value = getattr(node, field)
2878 except AttributeError:
2881 yield f"{' ' * (depth+1)}{field}="
2883 if isinstance(value, list):
2885 if isinstance(item, ast.AST):
2886 yield from _v(item, depth + 2)
2888 elif isinstance(value, ast.AST):
2889 yield from _v(value, depth + 2)
2892 yield f"{' ' * (depth+2)}{value!r}, # {value.__class__.__name__}"
2894 yield f"{' ' * depth}) # /{node.__class__.__name__}"
2897 src_ast = ast.parse(src)
2898 except Exception as exc:
2899 major, minor = sys.version_info[:2]
2900 raise AssertionError(
2901 f"cannot use --safe with this file; failed to parse source file "
2902 f"with Python {major}.{minor}'s builtin AST. Re-run with --fast "
2903 f"or stop using deprecated Python 2 syntax. AST error message: {exc}"
2907 dst_ast = ast.parse(dst)
2908 except Exception as exc:
2909 log = dump_to_file("".join(traceback.format_tb(exc.__traceback__)), dst)
2910 raise AssertionError(
2911 f"INTERNAL ERROR: Black produced invalid code: {exc}. "
2912 f"Please report a bug on https://github.com/ambv/black/issues. "
2913 f"This invalid output might be helpful: {log}"
2916 src_ast_str = "\n".join(_v(src_ast))
2917 dst_ast_str = "\n".join(_v(dst_ast))
2918 if src_ast_str != dst_ast_str:
2919 log = dump_to_file(diff(src_ast_str, dst_ast_str, "src", "dst"))
2920 raise AssertionError(
2921 f"INTERNAL ERROR: Black produced code that is not equivalent to "
2923 f"Please report a bug on https://github.com/ambv/black/issues. "
2924 f"This diff might be helpful: {log}"
2929 src: str, dst: str, line_length: int, is_pyi: bool = False, force_py36: bool = False
2931 """Raise AssertionError if `dst` reformats differently the second time."""
2932 newdst = format_str(
2933 dst, line_length=line_length, is_pyi=is_pyi, force_py36=force_py36
2937 diff(src, dst, "source", "first pass"),
2938 diff(dst, newdst, "first pass", "second pass"),
2940 raise AssertionError(
2941 f"INTERNAL ERROR: Black produced different code on the second pass "
2942 f"of the formatter. "
2943 f"Please report a bug on https://github.com/ambv/black/issues. "
2944 f"This diff might be helpful: {log}"
2948 def dump_to_file(*output: str) -> str:
2949 """Dump `output` to a temporary file. Return path to the file."""
2952 with tempfile.NamedTemporaryFile(
2953 mode="w", prefix="blk_", suffix=".log", delete=False, encoding="utf8"
2955 for lines in output:
2957 if lines and lines[-1] != "\n":
2962 def diff(a: str, b: str, a_name: str, b_name: str) -> str:
2963 """Return a unified diff string between strings `a` and `b`."""
2966 a_lines = [line + "\n" for line in a.split("\n")]
2967 b_lines = [line + "\n" for line in b.split("\n")]
2969 difflib.unified_diff(a_lines, b_lines, fromfile=a_name, tofile=b_name, n=5)
2973 def cancel(tasks: Iterable[asyncio.Task]) -> None:
2974 """asyncio signal handler that cancels all `tasks` and reports to stderr."""
2980 def shutdown(loop: BaseEventLoop) -> None:
2981 """Cancel all pending tasks on `loop`, wait for them, and close the loop."""
2983 # This part is borrowed from asyncio/runners.py in Python 3.7b2.
2984 to_cancel = [task for task in asyncio.Task.all_tasks(loop) if not task.done()]
2988 for task in to_cancel:
2990 loop.run_until_complete(
2991 asyncio.gather(*to_cancel, loop=loop, return_exceptions=True)
2994 # `concurrent.futures.Future` objects cannot be cancelled once they
2995 # are already running. There might be some when the `shutdown()` happened.
2996 # Silence their logger's spew about the event loop being closed.
2997 cf_logger = logging.getLogger("concurrent.futures")
2998 cf_logger.setLevel(logging.CRITICAL)
3002 def sub_twice(regex: Pattern[str], replacement: str, original: str) -> str:
3003 """Replace `regex` with `replacement` twice on `original`.
3005 This is used by string normalization to perform replaces on
3006 overlapping matches.
3008 return regex.sub(replacement, regex.sub(replacement, original))
3011 def enumerate_reversed(sequence: Sequence[T]) -> Iterator[Tuple[Index, T]]:
3012 """Like `reversed(enumerate(sequence))` if that were possible."""
3013 index = len(sequence) - 1
3014 for element in reversed(sequence):
3015 yield (index, element)
3019 def enumerate_with_length(
3020 line: Line, reversed: bool = False
3021 ) -> Iterator[Tuple[Index, Leaf, int]]:
3022 """Return an enumeration of leaves with their length.
3024 Stops prematurely on multiline strings and standalone comments.
3027 Callable[[Sequence[Leaf]], Iterator[Tuple[Index, Leaf]]],
3028 enumerate_reversed if reversed else enumerate,
3030 for index, leaf in op(line.leaves):
3031 length = len(leaf.prefix) + len(leaf.value)
3032 if "\n" in leaf.value:
3033 return # Multiline strings, we can't continue.
3035 comment: Optional[Leaf]
3036 for comment in line.comments_after(leaf, index):
3037 length += len(comment.value)
3039 yield index, leaf, length
3042 def is_line_short_enough(line: Line, *, line_length: int, line_str: str = "") -> bool:
3043 """Return True if `line` is no longer than `line_length`.
3045 Uses the provided `line_str` rendering, if any, otherwise computes a new one.
3048 line_str = str(line).strip("\n")
3050 len(line_str) <= line_length
3051 and "\n" not in line_str # multiline strings
3052 and not line.contains_standalone_comments()
3056 def can_omit_invisible_parens(line: Line, line_length: int) -> bool:
3057 """Does `line` have a shape safe to reformat without optional parens around it?
3059 Returns True for only a subset of potentially nice looking formattings but
3060 the point is to not return false positives that end up producing lines that
3063 bt = line.bracket_tracker
3064 if not bt.delimiters:
3065 # Without delimiters the optional parentheses are useless.
3068 max_priority = bt.max_delimiter_priority()
3069 if bt.delimiter_count_with_priority(max_priority) > 1:
3070 # With more than one delimiter of a kind the optional parentheses read better.
3073 if max_priority == DOT_PRIORITY:
3074 # A single stranded method call doesn't require optional parentheses.
3077 assert len(line.leaves) >= 2, "Stranded delimiter"
3079 first = line.leaves[0]
3080 second = line.leaves[1]
3081 penultimate = line.leaves[-2]
3082 last = line.leaves[-1]
3084 # With a single delimiter, omit if the expression starts or ends with
3086 if first.type in OPENING_BRACKETS and second.type not in CLOSING_BRACKETS:
3088 length = 4 * line.depth
3089 for _index, leaf, leaf_length in enumerate_with_length(line):
3090 if leaf.type in CLOSING_BRACKETS and leaf.opening_bracket is first:
3093 length += leaf_length
3094 if length > line_length:
3097 if leaf.type in OPENING_BRACKETS:
3098 # There are brackets we can further split on.
3102 # checked the entire string and line length wasn't exceeded
3103 if len(line.leaves) == _index + 1:
3106 # Note: we are not returning False here because a line might have *both*
3107 # a leading opening bracket and a trailing closing bracket. If the
3108 # opening bracket doesn't match our rule, maybe the closing will.
3111 last.type == token.RPAR
3112 or last.type == token.RBRACE
3114 # don't use indexing for omitting optional parentheses;
3116 last.type == token.RSQB
3118 and last.parent.type != syms.trailer
3121 if penultimate.type in OPENING_BRACKETS:
3122 # Empty brackets don't help.
3125 if is_multiline_string(first):
3126 # Additional wrapping of a multiline string in this situation is
3130 length = 4 * line.depth
3131 seen_other_brackets = False
3132 for _index, leaf, leaf_length in enumerate_with_length(line):
3133 length += leaf_length
3134 if leaf is last.opening_bracket:
3135 if seen_other_brackets or length <= line_length:
3138 elif leaf.type in OPENING_BRACKETS:
3139 # There are brackets we can further split on.
3140 seen_other_brackets = True
3145 def get_cache_file(line_length: int, pyi: bool = False, py36: bool = False) -> Path:
3148 / f"cache.{line_length}{'.pyi' if pyi else ''}{'.py36' if py36 else ''}.pickle"
3152 def read_cache(line_length: int, pyi: bool = False, py36: bool = False) -> Cache:
3153 """Read the cache if it exists and is well formed.
3155 If it is not well formed, the call to write_cache later should resolve the issue.
3157 cache_file = get_cache_file(line_length, pyi, py36)
3158 if not cache_file.exists():
3161 with cache_file.open("rb") as fobj:
3163 cache: Cache = pickle.load(fobj)
3164 except pickle.UnpicklingError:
3170 def get_cache_info(path: Path) -> CacheInfo:
3171 """Return the information used to check if a file is already formatted or not."""
3173 return stat.st_mtime, stat.st_size
3177 cache: Cache, sources: Iterable[Path]
3178 ) -> Tuple[List[Path], List[Path]]:
3179 """Split a list of paths into two.
3181 The first list contains paths of files that modified on disk or are not in the
3182 cache. The other list contains paths to non-modified files.
3187 if cache.get(src) != get_cache_info(src):
3196 sources: List[Path],
3201 """Update the cache file."""
3202 cache_file = get_cache_file(line_length, pyi, py36)
3204 if not CACHE_DIR.exists():
3205 CACHE_DIR.mkdir(parents=True)
3206 new_cache = {**cache, **{src.resolve(): get_cache_info(src) for src in sources}}
3207 with cache_file.open("wb") as fobj:
3208 pickle.dump(new_cache, fobj, protocol=pickle.HIGHEST_PROTOCOL)
3213 if __name__ == "__main__":