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.
2 from asyncio.base_events import BaseEventLoop
3 from concurrent.futures import Executor, ProcessPoolExecutor
4 from datetime import datetime
5 from enum import Enum, Flag
6 from functools import lru_cache, partial, wraps
10 from multiprocessing import Manager
12 from pathlib import Path
38 from appdirs import user_cache_dir
39 from attr import dataclass, Factory
44 from blib2to3.pytree import Node, Leaf, type_repr
45 from blib2to3 import pygram, pytree
46 from blib2to3.pgen2 import driver, token
47 from blib2to3.pgen2.parse import ParseError
50 __version__ = "18.6b4"
51 DEFAULT_LINE_LENGTH = 88
53 r"/(\.git|\.hg|\.mypy_cache|\.tox|\.venv|_build|buck-out|build|dist)/"
55 DEFAULT_INCLUDES = r"\.pyi?$"
56 CACHE_DIR = Path(user_cache_dir("black", version=__version__))
68 LN = Union[Leaf, Node]
69 SplitFunc = Callable[["Line", bool], Iterator["Line"]]
72 CacheInfo = Tuple[Timestamp, FileSize]
73 Cache = Dict[Path, CacheInfo]
74 out = partial(click.secho, bold=True, err=True)
75 err = partial(click.secho, fg="red", err=True)
77 pygram.initialize(CACHE_DIR)
78 syms = pygram.python_symbols
81 class NothingChanged(UserWarning):
82 """Raised by :func:`format_file` when reformatted code is the same as source."""
85 class CannotSplit(Exception):
86 """A readable split that fits the allotted line length is impossible.
88 Raised by :func:`left_hand_split`, :func:`right_hand_split`, and
89 :func:`delimiter_split`.
93 class WriteBack(Enum):
100 def from_configuration(cls, *, check: bool, diff: bool) -> "WriteBack":
101 if check and not diff:
104 return cls.DIFF if diff else cls.YES
113 class FileMode(Flag):
117 NO_STRING_NORMALIZATION = 4
120 def from_configuration(
121 cls, *, py36: bool, pyi: bool, skip_string_normalization: bool
123 mode = cls.AUTO_DETECT
128 if skip_string_normalization:
129 mode |= cls.NO_STRING_NORMALIZATION
133 def read_pyproject_toml(
134 ctx: click.Context, param: click.Parameter, value: Union[str, int, bool, None]
136 """Inject Black configuration from "pyproject.toml" into defaults in `ctx`.
138 Returns the path to a successfully found and read configuration file, None
141 assert not isinstance(value, (int, bool)), "Invalid parameter type passed"
143 root = find_project_root(ctx.params.get("src", ()))
144 path = root / "pyproject.toml"
151 pyproject_toml = toml.load(value)
152 config = pyproject_toml.get("tool", {}).get("black", {})
153 except (toml.TomlDecodeError, OSError) as e:
154 raise click.BadOptionUsage(f"Error reading configuration file: {e}", ctx)
159 if ctx.default_map is None:
161 ctx.default_map.update( # type: ignore # bad types in .pyi
162 {k.replace("--", "").replace("-", "_"): v for k, v in config.items()}
167 @click.command(context_settings=dict(help_option_names=["-h", "--help"]))
172 default=DEFAULT_LINE_LENGTH,
173 help="How many character per line to allow.",
180 "Allow using Python 3.6-only syntax on all input files. This will put "
181 "trailing commas in function signatures and calls also after *args and "
182 "**kwargs. [default: per-file auto-detection]"
189 "Format all input files like typing stubs regardless of file extension "
190 "(useful when piping source on standard input)."
195 "--skip-string-normalization",
197 help="Don't normalize string quotes or prefixes.",
203 "Don't write the files back, just return the status. Return code 0 "
204 "means nothing would change. Return code 1 means some files would be "
205 "reformatted. Return code 123 means there was an internal error."
211 help="Don't write the files back, just output a diff for each file on stdout.",
216 help="If --fast given, skip temporary sanity checks. [default: --safe]",
221 default=DEFAULT_INCLUDES,
223 "A regular expression that matches files and directories that should be "
224 "included on recursive searches. An empty value means all files are "
225 "included regardless of the name. Use forward slashes for directories on "
226 "all platforms (Windows, too). Exclusions are calculated first, inclusions "
234 default=DEFAULT_EXCLUDES,
236 "A regular expression that matches files and directories that should be "
237 "excluded on recursive searches. An empty value means no paths are excluded. "
238 "Use forward slashes for directories on all platforms (Windows, too). "
239 "Exclusions are calculated first, inclusions later."
248 "Don't emit non-error messages to stderr. Errors are still emitted, "
249 "silence those with 2>/dev/null."
257 "Also emit messages to stderr about files that were not changed or were "
258 "ignored due to --exclude=."
261 @click.version_option(version=__version__)
266 exists=True, file_okay=True, dir_okay=True, readable=True, allow_dash=True
273 exists=False, file_okay=True, dir_okay=False, readable=True, allow_dash=False
276 callback=read_pyproject_toml,
277 help="Read configuration from PATH.",
288 skip_string_normalization: bool,
294 config: Optional[str],
296 """The uncompromising code formatter."""
297 write_back = WriteBack.from_configuration(check=check, diff=diff)
298 mode = FileMode.from_configuration(
299 py36=py36, pyi=pyi, skip_string_normalization=skip_string_normalization
301 if config and verbose:
302 out(f"Using configuration from {config}.", bold=False, fg="blue")
304 include_regex = re_compile_maybe_verbose(include)
306 err(f"Invalid regular expression for include given: {include!r}")
309 exclude_regex = re_compile_maybe_verbose(exclude)
311 err(f"Invalid regular expression for exclude given: {exclude!r}")
313 report = Report(check=check, quiet=quiet, verbose=verbose)
314 root = find_project_root(src)
315 sources: Set[Path] = set()
320 gen_python_files_in_dir(p, root, include_regex, exclude_regex, report)
322 elif p.is_file() or s == "-":
323 # if a file was explicitly given, we don't care about its extension
326 err(f"invalid path: {s}")
327 if len(sources) == 0:
328 if verbose or not quiet:
329 out("No paths given. Nothing to do 😴")
332 if len(sources) == 1:
335 line_length=line_length,
337 write_back=write_back,
342 loop = asyncio.get_event_loop()
343 executor = ProcessPoolExecutor(max_workers=os.cpu_count())
345 loop.run_until_complete(
348 line_length=line_length,
350 write_back=write_back,
359 if verbose or not quiet:
360 bang = "💥 💔 💥" if report.return_code else "✨ 🍰 ✨"
361 out(f"All done! {bang}")
362 click.secho(str(report), err=True)
363 ctx.exit(report.return_code)
370 write_back: WriteBack,
374 """Reformat a single file under `src` without spawning child processes.
376 If `quiet` is True, non-error messages are not output. `line_length`,
377 `write_back`, `fast` and `pyi` options are passed to
378 :func:`format_file_in_place` or :func:`format_stdin_to_stdout`.
382 if not src.is_file() and str(src) == "-":
383 if format_stdin_to_stdout(
384 line_length=line_length, fast=fast, write_back=write_back, mode=mode
386 changed = Changed.YES
389 if write_back != WriteBack.DIFF:
390 cache = read_cache(line_length, mode)
391 res_src = src.resolve()
392 if res_src in cache and cache[res_src] == get_cache_info(res_src):
393 changed = Changed.CACHED
394 if changed is not Changed.CACHED and format_file_in_place(
396 line_length=line_length,
398 write_back=write_back,
401 changed = Changed.YES
402 if write_back is WriteBack.YES:
403 should_write = changed is not Changed.CACHED
404 elif write_back is WriteBack.CHECK:
405 should_write = changed is Changed.NO
410 write_cache(cache, [src], line_length, mode)
411 report.done(src, changed)
412 except Exception as exc:
413 report.failed(src, str(exc))
416 async def schedule_formatting(
420 write_back: WriteBack,
426 """Run formatting of `sources` in parallel using the provided `executor`.
428 (Use ProcessPoolExecutors for actual parallelism.)
430 `line_length`, `write_back`, `fast`, and `pyi` options are passed to
431 :func:`format_file_in_place`.
434 if write_back != WriteBack.DIFF:
435 cache = read_cache(line_length, mode)
436 sources, cached = filter_cached(cache, sources)
437 for src in sorted(cached):
438 report.done(src, Changed.CACHED)
443 if write_back == WriteBack.DIFF:
444 # For diff output, we need locks to ensure we don't interleave output
445 # from different processes.
447 lock = manager.Lock()
449 loop.run_in_executor(
451 format_file_in_place,
459 for src in sorted(sources)
461 pending: Iterable[asyncio.Task] = tasks.keys()
463 loop.add_signal_handler(signal.SIGINT, cancel, pending)
464 loop.add_signal_handler(signal.SIGTERM, cancel, pending)
465 except NotImplementedError:
466 # There are no good alternatives for these on Windows
469 done, _ = await asyncio.wait(pending, return_when=asyncio.FIRST_COMPLETED)
471 src = tasks.pop(task)
473 cancelled.append(task)
474 elif task.exception():
475 report.failed(src, str(task.exception()))
477 changed = Changed.YES if task.result() else Changed.NO
478 # In normal mode, write all files to the cache.
479 if write_back is WriteBack.YES:
480 formatted.append(src)
481 # In check mode, write only unchanged files to the cache.
482 elif write_back is WriteBack.CHECK and changed is Changed.NO:
483 formatted.append(src)
484 report.done(src, changed)
486 await asyncio.gather(*cancelled, loop=loop, return_exceptions=True)
487 if write_back in (WriteBack.YES, WriteBack.CHECK) and formatted:
488 write_cache(cache, formatted, line_length, mode)
491 def format_file_in_place(
495 write_back: WriteBack = WriteBack.NO,
496 mode: FileMode = FileMode.AUTO_DETECT,
497 lock: Any = None, # multiprocessing.Manager().Lock() is some crazy proxy
499 """Format file under `src` path. Return True if changed.
501 If `write_back` is DIFF, write a diff to stdout. If it is YES, write reformatted
503 `line_length` and `fast` options are passed to :func:`format_file_contents`.
505 if src.suffix == ".pyi":
508 then = datetime.utcfromtimestamp(src.stat().st_mtime)
509 with open(src, "rb") as buf:
510 src_contents, encoding, newline = decode_bytes(buf.read())
512 dst_contents = format_file_contents(
513 src_contents, line_length=line_length, fast=fast, mode=mode
515 except NothingChanged:
518 if write_back == write_back.YES:
519 with open(src, "w", encoding=encoding, newline=newline) as f:
520 f.write(dst_contents)
521 elif write_back == write_back.DIFF:
522 now = datetime.utcnow()
523 src_name = f"{src}\t{then} +0000"
524 dst_name = f"{src}\t{now} +0000"
525 diff_contents = diff(src_contents, dst_contents, src_name, dst_name)
529 f = io.TextIOWrapper(
535 f.write(diff_contents)
543 def format_stdin_to_stdout(
546 write_back: WriteBack = WriteBack.NO,
547 mode: FileMode = FileMode.AUTO_DETECT,
549 """Format file on stdin. Return True if changed.
551 If `write_back` is YES, write reformatted code back to stdout. If it is DIFF,
552 write a diff to stdout.
553 `line_length`, `fast`, `is_pyi`, and `force_py36` arguments are passed to
554 :func:`format_file_contents`.
556 then = datetime.utcnow()
557 src, encoding, newline = decode_bytes(sys.stdin.buffer.read())
560 dst = format_file_contents(src, line_length=line_length, fast=fast, mode=mode)
563 except NothingChanged:
567 f = io.TextIOWrapper(
568 sys.stdout.buffer, encoding=encoding, newline=newline, write_through=True
570 if write_back == WriteBack.YES:
572 elif write_back == WriteBack.DIFF:
573 now = datetime.utcnow()
574 src_name = f"STDIN\t{then} +0000"
575 dst_name = f"STDOUT\t{now} +0000"
576 f.write(diff(src, dst, src_name, dst_name))
580 def format_file_contents(
585 mode: FileMode = FileMode.AUTO_DETECT,
587 """Reformat contents a file and return new contents.
589 If `fast` is False, additionally confirm that the reformatted code is
590 valid by calling :func:`assert_equivalent` and :func:`assert_stable` on it.
591 `line_length` is passed to :func:`format_str`.
593 if src_contents.strip() == "":
596 dst_contents = format_str(src_contents, line_length=line_length, mode=mode)
597 if src_contents == dst_contents:
601 assert_equivalent(src_contents, dst_contents)
602 assert_stable(src_contents, dst_contents, line_length=line_length, mode=mode)
607 src_contents: str, line_length: int, *, mode: FileMode = FileMode.AUTO_DETECT
609 """Reformat a string and return new contents.
611 `line_length` determines how many characters per line are allowed.
613 src_node = lib2to3_parse(src_contents)
615 future_imports = get_future_imports(src_node)
616 is_pyi = bool(mode & FileMode.PYI)
617 py36 = bool(mode & FileMode.PYTHON36) or is_python36(src_node)
618 normalize_strings = not bool(mode & FileMode.NO_STRING_NORMALIZATION)
619 normalize_fmt_off(src_node)
620 lines = LineGenerator(
621 remove_u_prefix=py36 or "unicode_literals" in future_imports,
623 normalize_strings=normalize_strings,
624 allow_underscores=py36,
626 elt = EmptyLineTracker(is_pyi=is_pyi)
629 for current_line in lines.visit(src_node):
630 for _ in range(after):
631 dst_contents += str(empty_line)
632 before, after = elt.maybe_empty_lines(current_line)
633 for _ in range(before):
634 dst_contents += str(empty_line)
635 for line in split_line(current_line, line_length=line_length, py36=py36):
636 dst_contents += str(line)
640 def decode_bytes(src: bytes) -> Tuple[FileContent, Encoding, NewLine]:
641 """Return a tuple of (decoded_contents, encoding, newline).
643 `newline` is either CRLF or LF but `decoded_contents` is decoded with
644 universal newlines (i.e. only contains LF).
646 srcbuf = io.BytesIO(src)
647 encoding, lines = tokenize.detect_encoding(srcbuf.readline)
649 return "", encoding, "\n"
651 newline = "\r\n" if b"\r\n" == lines[0][-2:] else "\n"
653 with io.TextIOWrapper(srcbuf, encoding) as tiow:
654 return tiow.read(), encoding, newline
658 pygram.python_grammar_no_print_statement_no_exec_statement,
659 pygram.python_grammar_no_print_statement,
660 pygram.python_grammar,
664 def lib2to3_parse(src_txt: str) -> Node:
665 """Given a string with source, return the lib2to3 Node."""
666 grammar = pygram.python_grammar_no_print_statement
667 if src_txt[-1:] != "\n":
669 for grammar in GRAMMARS:
670 drv = driver.Driver(grammar, pytree.convert)
672 result = drv.parse_string(src_txt, True)
675 except ParseError as pe:
676 lineno, column = pe.context[1]
677 lines = src_txt.splitlines()
679 faulty_line = lines[lineno - 1]
681 faulty_line = "<line number missing in source>"
682 exc = ValueError(f"Cannot parse: {lineno}:{column}: {faulty_line}")
686 if isinstance(result, Leaf):
687 result = Node(syms.file_input, [result])
691 def lib2to3_unparse(node: Node) -> str:
692 """Given a lib2to3 node, return its string representation."""
700 class Visitor(Generic[T]):
701 """Basic lib2to3 visitor that yields things of type `T` on `visit()`."""
703 def visit(self, node: LN) -> Iterator[T]:
704 """Main method to visit `node` and its children.
706 It tries to find a `visit_*()` method for the given `node.type`, like
707 `visit_simple_stmt` for Node objects or `visit_INDENT` for Leaf objects.
708 If no dedicated `visit_*()` method is found, chooses `visit_default()`
711 Then yields objects of type `T` from the selected visitor.
714 name = token.tok_name[node.type]
716 name = type_repr(node.type)
717 yield from getattr(self, f"visit_{name}", self.visit_default)(node)
719 def visit_default(self, node: LN) -> Iterator[T]:
720 """Default `visit_*()` implementation. Recurses to children of `node`."""
721 if isinstance(node, Node):
722 for child in node.children:
723 yield from self.visit(child)
727 class DebugVisitor(Visitor[T]):
730 def visit_default(self, node: LN) -> Iterator[T]:
731 indent = " " * (2 * self.tree_depth)
732 if isinstance(node, Node):
733 _type = type_repr(node.type)
734 out(f"{indent}{_type}", fg="yellow")
736 for child in node.children:
737 yield from self.visit(child)
740 out(f"{indent}/{_type}", fg="yellow", bold=False)
742 _type = token.tok_name.get(node.type, str(node.type))
743 out(f"{indent}{_type}", fg="blue", nl=False)
745 # We don't have to handle prefixes for `Node` objects since
746 # that delegates to the first child anyway.
747 out(f" {node.prefix!r}", fg="green", bold=False, nl=False)
748 out(f" {node.value!r}", fg="blue", bold=False)
751 def show(cls, code: Union[str, Leaf, Node]) -> None:
752 """Pretty-print the lib2to3 AST of a given string of `code`.
754 Convenience method for debugging.
756 v: DebugVisitor[None] = DebugVisitor()
757 if isinstance(code, str):
758 code = lib2to3_parse(code)
762 KEYWORDS = set(keyword.kwlist)
763 WHITESPACE = {token.DEDENT, token.INDENT, token.NEWLINE}
764 FLOW_CONTROL = {"return", "raise", "break", "continue"}
775 STANDALONE_COMMENT = 153
776 token.tok_name[STANDALONE_COMMENT] = "STANDALONE_COMMENT"
777 LOGIC_OPERATORS = {"and", "or"}
802 STARS = {token.STAR, token.DOUBLESTAR}
805 syms.argument, # double star in arglist
806 syms.trailer, # single argument to call
808 syms.varargslist, # lambdas
810 UNPACKING_PARENTS = {
811 syms.atom, # single element of a list or set literal
815 syms.testlist_star_expr,
850 COMPREHENSION_PRIORITY = 20
852 TERNARY_PRIORITY = 16
855 COMPARATOR_PRIORITY = 10
866 token.DOUBLESLASH: 4,
876 class BracketTracker:
877 """Keeps track of brackets on a line."""
880 bracket_match: Dict[Tuple[Depth, NodeType], Leaf] = Factory(dict)
881 delimiters: Dict[LeafID, Priority] = Factory(dict)
882 previous: Optional[Leaf] = None
883 _for_loop_variable: int = 0
884 _lambda_arguments: int = 0
886 def mark(self, leaf: Leaf) -> None:
887 """Mark `leaf` with bracket-related metadata. Keep track of delimiters.
889 All leaves receive an int `bracket_depth` field that stores how deep
890 within brackets a given leaf is. 0 means there are no enclosing brackets
891 that started on this line.
893 If a leaf is itself a closing bracket, it receives an `opening_bracket`
894 field that it forms a pair with. This is a one-directional link to
895 avoid reference cycles.
897 If a leaf is a delimiter (a token on which Black can split the line if
898 needed) and it's on depth 0, its `id()` is stored in the tracker's
901 if leaf.type == token.COMMENT:
904 self.maybe_decrement_after_for_loop_variable(leaf)
905 self.maybe_decrement_after_lambda_arguments(leaf)
906 if leaf.type in CLOSING_BRACKETS:
908 opening_bracket = self.bracket_match.pop((self.depth, leaf.type))
909 leaf.opening_bracket = opening_bracket
910 leaf.bracket_depth = self.depth
912 delim = is_split_before_delimiter(leaf, self.previous)
913 if delim and self.previous is not None:
914 self.delimiters[id(self.previous)] = delim
916 delim = is_split_after_delimiter(leaf, self.previous)
918 self.delimiters[id(leaf)] = delim
919 if leaf.type in OPENING_BRACKETS:
920 self.bracket_match[self.depth, BRACKET[leaf.type]] = leaf
923 self.maybe_increment_lambda_arguments(leaf)
924 self.maybe_increment_for_loop_variable(leaf)
926 def any_open_brackets(self) -> bool:
927 """Return True if there is an yet unmatched open bracket on the line."""
928 return bool(self.bracket_match)
930 def max_delimiter_priority(self, exclude: Iterable[LeafID] = ()) -> int:
931 """Return the highest priority of a delimiter found on the line.
933 Values are consistent with what `is_split_*_delimiter()` return.
934 Raises ValueError on no delimiters.
936 return max(v for k, v in self.delimiters.items() if k not in exclude)
938 def delimiter_count_with_priority(self, priority: int = 0) -> int:
939 """Return the number of delimiters with the given `priority`.
941 If no `priority` is passed, defaults to max priority on the line.
943 if not self.delimiters:
946 priority = priority or self.max_delimiter_priority()
947 return sum(1 for p in self.delimiters.values() if p == priority)
949 def maybe_increment_for_loop_variable(self, leaf: Leaf) -> bool:
950 """In a for loop, or comprehension, the variables are often unpacks.
952 To avoid splitting on the comma in this situation, increase the depth of
953 tokens between `for` and `in`.
955 if leaf.type == token.NAME and leaf.value == "for":
957 self._for_loop_variable += 1
962 def maybe_decrement_after_for_loop_variable(self, leaf: Leaf) -> bool:
963 """See `maybe_increment_for_loop_variable` above for explanation."""
964 if self._for_loop_variable and leaf.type == token.NAME and leaf.value == "in":
966 self._for_loop_variable -= 1
971 def maybe_increment_lambda_arguments(self, leaf: Leaf) -> bool:
972 """In a lambda expression, there might be more than one argument.
974 To avoid splitting on the comma in this situation, increase the depth of
975 tokens between `lambda` and `:`.
977 if leaf.type == token.NAME and leaf.value == "lambda":
979 self._lambda_arguments += 1
984 def maybe_decrement_after_lambda_arguments(self, leaf: Leaf) -> bool:
985 """See `maybe_increment_lambda_arguments` above for explanation."""
986 if self._lambda_arguments and leaf.type == token.COLON:
988 self._lambda_arguments -= 1
993 def get_open_lsqb(self) -> Optional[Leaf]:
994 """Return the most recent opening square bracket (if any)."""
995 return self.bracket_match.get((self.depth - 1, token.RSQB))
1000 """Holds leaves and comments. Can be printed with `str(line)`."""
1003 leaves: List[Leaf] = Factory(list)
1004 comments: List[Tuple[Index, Leaf]] = Factory(list)
1005 bracket_tracker: BracketTracker = Factory(BracketTracker)
1006 inside_brackets: bool = False
1007 should_explode: bool = False
1009 def append(self, leaf: Leaf, preformatted: bool = False) -> None:
1010 """Add a new `leaf` to the end of the line.
1012 Unless `preformatted` is True, the `leaf` will receive a new consistent
1013 whitespace prefix and metadata applied by :class:`BracketTracker`.
1014 Trailing commas are maybe removed, unpacked for loop variables are
1015 demoted from being delimiters.
1017 Inline comments are put aside.
1019 has_value = leaf.type in BRACKETS or bool(leaf.value.strip())
1023 if token.COLON == leaf.type and self.is_class_paren_empty:
1024 del self.leaves[-2:]
1025 if self.leaves and not preformatted:
1026 # Note: at this point leaf.prefix should be empty except for
1027 # imports, for which we only preserve newlines.
1028 leaf.prefix += whitespace(
1029 leaf, complex_subscript=self.is_complex_subscript(leaf)
1031 if self.inside_brackets or not preformatted:
1032 self.bracket_tracker.mark(leaf)
1033 self.maybe_remove_trailing_comma(leaf)
1034 if not self.append_comment(leaf):
1035 self.leaves.append(leaf)
1037 def append_safe(self, leaf: Leaf, preformatted: bool = False) -> None:
1038 """Like :func:`append()` but disallow invalid standalone comment structure.
1040 Raises ValueError when any `leaf` is appended after a standalone comment
1041 or when a standalone comment is not the first leaf on the line.
1043 if self.bracket_tracker.depth == 0:
1045 raise ValueError("cannot append to standalone comments")
1047 if self.leaves and leaf.type == STANDALONE_COMMENT:
1049 "cannot append standalone comments to a populated line"
1052 self.append(leaf, preformatted=preformatted)
1055 def is_comment(self) -> bool:
1056 """Is this line a standalone comment?"""
1057 return len(self.leaves) == 1 and self.leaves[0].type == STANDALONE_COMMENT
1060 def is_decorator(self) -> bool:
1061 """Is this line a decorator?"""
1062 return bool(self) and self.leaves[0].type == token.AT
1065 def is_import(self) -> bool:
1066 """Is this an import line?"""
1067 return bool(self) and is_import(self.leaves[0])
1070 def is_class(self) -> bool:
1071 """Is this line a class definition?"""
1074 and self.leaves[0].type == token.NAME
1075 and self.leaves[0].value == "class"
1079 def is_stub_class(self) -> bool:
1080 """Is this line a class definition with a body consisting only of "..."?"""
1081 return self.is_class and self.leaves[-3:] == [
1082 Leaf(token.DOT, ".") for _ in range(3)
1086 def is_def(self) -> bool:
1087 """Is this a function definition? (Also returns True for async defs.)"""
1089 first_leaf = self.leaves[0]
1094 second_leaf: Optional[Leaf] = self.leaves[1]
1097 return (first_leaf.type == token.NAME and first_leaf.value == "def") or (
1098 first_leaf.type == token.ASYNC
1099 and second_leaf is not None
1100 and second_leaf.type == token.NAME
1101 and second_leaf.value == "def"
1105 def is_class_paren_empty(self) -> bool:
1106 """Is this a class with no base classes but using parentheses?
1108 Those are unnecessary and should be removed.
1112 and len(self.leaves) == 4
1114 and self.leaves[2].type == token.LPAR
1115 and self.leaves[2].value == "("
1116 and self.leaves[3].type == token.RPAR
1117 and self.leaves[3].value == ")"
1121 def is_triple_quoted_string(self) -> bool:
1122 """Is the line a triple quoted string?"""
1125 and self.leaves[0].type == token.STRING
1126 and self.leaves[0].value.startswith(('"""', "'''"))
1129 def contains_standalone_comments(self, depth_limit: int = sys.maxsize) -> bool:
1130 """If so, needs to be split before emitting."""
1131 for leaf in self.leaves:
1132 if leaf.type == STANDALONE_COMMENT:
1133 if leaf.bracket_depth <= depth_limit:
1138 def contains_multiline_strings(self) -> bool:
1139 for leaf in self.leaves:
1140 if is_multiline_string(leaf):
1145 def maybe_remove_trailing_comma(self, closing: Leaf) -> bool:
1146 """Remove trailing comma if there is one and it's safe."""
1149 and self.leaves[-1].type == token.COMMA
1150 and closing.type in CLOSING_BRACKETS
1154 if closing.type == token.RBRACE:
1155 self.remove_trailing_comma()
1158 if closing.type == token.RSQB:
1159 comma = self.leaves[-1]
1160 if comma.parent and comma.parent.type == syms.listmaker:
1161 self.remove_trailing_comma()
1164 # For parens let's check if it's safe to remove the comma.
1165 # Imports are always safe.
1167 self.remove_trailing_comma()
1170 # Otheriwsse, if the trailing one is the only one, we might mistakenly
1171 # change a tuple into a different type by removing the comma.
1172 depth = closing.bracket_depth + 1
1174 opening = closing.opening_bracket
1175 for _opening_index, leaf in enumerate(self.leaves):
1182 for leaf in self.leaves[_opening_index + 1 :]:
1186 bracket_depth = leaf.bracket_depth
1187 if bracket_depth == depth and leaf.type == token.COMMA:
1189 if leaf.parent and leaf.parent.type == syms.arglist:
1194 self.remove_trailing_comma()
1199 def append_comment(self, comment: Leaf) -> bool:
1200 """Add an inline or standalone comment to the line."""
1202 comment.type == STANDALONE_COMMENT
1203 and self.bracket_tracker.any_open_brackets()
1208 if comment.type != token.COMMENT:
1211 after = len(self.leaves) - 1
1213 comment.type = STANDALONE_COMMENT
1218 self.comments.append((after, comment))
1221 def comments_after(self, leaf: Leaf, _index: int = -1) -> Iterator[Leaf]:
1222 """Generate comments that should appear directly after `leaf`.
1224 Provide a non-negative leaf `_index` to speed up the function.
1226 if not self.comments:
1230 for _index, _leaf in enumerate(self.leaves):
1237 for index, comment_after in self.comments:
1241 def remove_trailing_comma(self) -> None:
1242 """Remove the trailing comma and moves the comments attached to it."""
1243 comma_index = len(self.leaves) - 1
1244 for i in range(len(self.comments)):
1245 comment_index, comment = self.comments[i]
1246 if comment_index == comma_index:
1247 self.comments[i] = (comma_index - 1, comment)
1250 def is_complex_subscript(self, leaf: Leaf) -> bool:
1251 """Return True iff `leaf` is part of a slice with non-trivial exprs."""
1252 open_lsqb = self.bracket_tracker.get_open_lsqb()
1253 if open_lsqb is None:
1256 subscript_start = open_lsqb.next_sibling
1258 if isinstance(subscript_start, Node):
1259 if subscript_start.type == syms.listmaker:
1262 if subscript_start.type == syms.subscriptlist:
1263 subscript_start = child_towards(subscript_start, leaf)
1264 return subscript_start is not None and any(
1265 n.type in TEST_DESCENDANTS for n in subscript_start.pre_order()
1268 def __str__(self) -> str:
1269 """Render the line."""
1273 indent = " " * self.depth
1274 leaves = iter(self.leaves)
1275 first = next(leaves)
1276 res = f"{first.prefix}{indent}{first.value}"
1279 for _, comment in self.comments:
1283 def __bool__(self) -> bool:
1284 """Return True if the line has leaves or comments."""
1285 return bool(self.leaves or self.comments)
1289 class EmptyLineTracker:
1290 """Provides a stateful method that returns the number of potential extra
1291 empty lines needed before and after the currently processed line.
1293 Note: this tracker works on lines that haven't been split yet. It assumes
1294 the prefix of the first leaf consists of optional newlines. Those newlines
1295 are consumed by `maybe_empty_lines()` and included in the computation.
1298 is_pyi: bool = False
1299 previous_line: Optional[Line] = None
1300 previous_after: int = 0
1301 previous_defs: List[int] = Factory(list)
1303 def maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
1304 """Return the number of extra empty lines before and after the `current_line`.
1306 This is for separating `def`, `async def` and `class` with extra empty
1307 lines (two on module-level).
1309 before, after = self._maybe_empty_lines(current_line)
1310 before -= self.previous_after
1311 self.previous_after = after
1312 self.previous_line = current_line
1313 return before, after
1315 def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
1317 if current_line.depth == 0:
1318 max_allowed = 1 if self.is_pyi else 2
1319 if current_line.leaves:
1320 # Consume the first leaf's extra newlines.
1321 first_leaf = current_line.leaves[0]
1322 before = first_leaf.prefix.count("\n")
1323 before = min(before, max_allowed)
1324 first_leaf.prefix = ""
1327 depth = current_line.depth
1328 while self.previous_defs and self.previous_defs[-1] >= depth:
1329 self.previous_defs.pop()
1331 before = 0 if depth else 1
1333 before = 1 if depth else 2
1334 if current_line.is_decorator or current_line.is_def or current_line.is_class:
1335 return self._maybe_empty_lines_for_class_or_def(current_line, before)
1339 and self.previous_line.is_import
1340 and not current_line.is_import
1341 and depth == self.previous_line.depth
1343 return (before or 1), 0
1347 and self.previous_line.is_class
1348 and current_line.is_triple_quoted_string
1354 def _maybe_empty_lines_for_class_or_def(
1355 self, current_line: Line, before: int
1356 ) -> Tuple[int, int]:
1357 if not current_line.is_decorator:
1358 self.previous_defs.append(current_line.depth)
1359 if self.previous_line is None:
1360 # Don't insert empty lines before the first line in the file.
1363 if self.previous_line.is_decorator:
1366 if self.previous_line.depth < current_line.depth and (
1367 self.previous_line.is_class or self.previous_line.is_def
1372 self.previous_line.is_comment
1373 and self.previous_line.depth == current_line.depth
1379 if self.previous_line.depth > current_line.depth:
1381 elif current_line.is_class or self.previous_line.is_class:
1382 if current_line.is_stub_class and self.previous_line.is_stub_class:
1383 # No blank line between classes with an emty body
1387 elif current_line.is_def and not self.previous_line.is_def:
1388 # Blank line between a block of functions and a block of non-functions
1394 if current_line.depth and newlines:
1400 class LineGenerator(Visitor[Line]):
1401 """Generates reformatted Line objects. Empty lines are not emitted.
1403 Note: destroys the tree it's visiting by mutating prefixes of its leaves
1404 in ways that will no longer stringify to valid Python code on the tree.
1407 is_pyi: bool = False
1408 normalize_strings: bool = True
1409 current_line: Line = Factory(Line)
1410 remove_u_prefix: bool = False
1411 allow_underscores: bool = False
1413 def line(self, indent: int = 0) -> Iterator[Line]:
1416 If the line is empty, only emit if it makes sense.
1417 If the line is too long, split it first and then generate.
1419 If any lines were generated, set up a new current_line.
1421 if not self.current_line:
1422 self.current_line.depth += indent
1423 return # Line is empty, don't emit. Creating a new one unnecessary.
1425 complete_line = self.current_line
1426 self.current_line = Line(depth=complete_line.depth + indent)
1429 def visit_default(self, node: LN) -> Iterator[Line]:
1430 """Default `visit_*()` implementation. Recurses to children of `node`."""
1431 if isinstance(node, Leaf):
1432 any_open_brackets = self.current_line.bracket_tracker.any_open_brackets()
1433 for comment in generate_comments(node):
1434 if any_open_brackets:
1435 # any comment within brackets is subject to splitting
1436 self.current_line.append(comment)
1437 elif comment.type == token.COMMENT:
1438 # regular trailing comment
1439 self.current_line.append(comment)
1440 yield from self.line()
1443 # regular standalone comment
1444 yield from self.line()
1446 self.current_line.append(comment)
1447 yield from self.line()
1449 normalize_prefix(node, inside_brackets=any_open_brackets)
1450 if self.normalize_strings and node.type == token.STRING:
1451 normalize_string_prefix(node, remove_u_prefix=self.remove_u_prefix)
1452 normalize_string_quotes(node)
1453 if node.type == token.NUMBER:
1454 normalize_numeric_literal(node, self.allow_underscores)
1455 if node.type not in WHITESPACE:
1456 self.current_line.append(node)
1457 yield from super().visit_default(node)
1459 def visit_INDENT(self, node: Node) -> Iterator[Line]:
1460 """Increase indentation level, maybe yield a line."""
1461 # In blib2to3 INDENT never holds comments.
1462 yield from self.line(+1)
1463 yield from self.visit_default(node)
1465 def visit_DEDENT(self, node: Node) -> Iterator[Line]:
1466 """Decrease indentation level, maybe yield a line."""
1467 # The current line might still wait for trailing comments. At DEDENT time
1468 # there won't be any (they would be prefixes on the preceding NEWLINE).
1469 # Emit the line then.
1470 yield from self.line()
1472 # While DEDENT has no value, its prefix may contain standalone comments
1473 # that belong to the current indentation level. Get 'em.
1474 yield from self.visit_default(node)
1476 # Finally, emit the dedent.
1477 yield from self.line(-1)
1480 self, node: Node, keywords: Set[str], parens: Set[str]
1481 ) -> Iterator[Line]:
1482 """Visit a statement.
1484 This implementation is shared for `if`, `while`, `for`, `try`, `except`,
1485 `def`, `with`, `class`, `assert` and assignments.
1487 The relevant Python language `keywords` for a given statement will be
1488 NAME leaves within it. This methods puts those on a separate line.
1490 `parens` holds a set of string leaf values immediately after which
1491 invisible parens should be put.
1493 normalize_invisible_parens(node, parens_after=parens)
1494 for child in node.children:
1495 if child.type == token.NAME and child.value in keywords: # type: ignore
1496 yield from self.line()
1498 yield from self.visit(child)
1500 def visit_suite(self, node: Node) -> Iterator[Line]:
1501 """Visit a suite."""
1502 if self.is_pyi and is_stub_suite(node):
1503 yield from self.visit(node.children[2])
1505 yield from self.visit_default(node)
1507 def visit_simple_stmt(self, node: Node) -> Iterator[Line]:
1508 """Visit a statement without nested statements."""
1509 is_suite_like = node.parent and node.parent.type in STATEMENT
1511 if self.is_pyi and is_stub_body(node):
1512 yield from self.visit_default(node)
1514 yield from self.line(+1)
1515 yield from self.visit_default(node)
1516 yield from self.line(-1)
1519 if not self.is_pyi or not node.parent or not is_stub_suite(node.parent):
1520 yield from self.line()
1521 yield from self.visit_default(node)
1523 def visit_async_stmt(self, node: Node) -> Iterator[Line]:
1524 """Visit `async def`, `async for`, `async with`."""
1525 yield from self.line()
1527 children = iter(node.children)
1528 for child in children:
1529 yield from self.visit(child)
1531 if child.type == token.ASYNC:
1534 internal_stmt = next(children)
1535 for child in internal_stmt.children:
1536 yield from self.visit(child)
1538 def visit_decorators(self, node: Node) -> Iterator[Line]:
1539 """Visit decorators."""
1540 for child in node.children:
1541 yield from self.line()
1542 yield from self.visit(child)
1544 def visit_SEMI(self, leaf: Leaf) -> Iterator[Line]:
1545 """Remove a semicolon and put the other statement on a separate line."""
1546 yield from self.line()
1548 def visit_ENDMARKER(self, leaf: Leaf) -> Iterator[Line]:
1549 """End of file. Process outstanding comments and end with a newline."""
1550 yield from self.visit_default(leaf)
1551 yield from self.line()
1553 def visit_STANDALONE_COMMENT(self, leaf: Leaf) -> Iterator[Line]:
1554 if not self.current_line.bracket_tracker.any_open_brackets():
1555 yield from self.line()
1556 yield from self.visit_default(leaf)
1558 def __attrs_post_init__(self) -> None:
1559 """You are in a twisty little maze of passages."""
1562 self.visit_assert_stmt = partial(v, keywords={"assert"}, parens={"assert", ","})
1563 self.visit_if_stmt = partial(
1564 v, keywords={"if", "else", "elif"}, parens={"if", "elif"}
1566 self.visit_while_stmt = partial(v, keywords={"while", "else"}, parens={"while"})
1567 self.visit_for_stmt = partial(v, keywords={"for", "else"}, parens={"for", "in"})
1568 self.visit_try_stmt = partial(
1569 v, keywords={"try", "except", "else", "finally"}, parens=Ø
1571 self.visit_except_clause = partial(v, keywords={"except"}, parens=Ø)
1572 self.visit_with_stmt = partial(v, keywords={"with"}, parens=Ø)
1573 self.visit_funcdef = partial(v, keywords={"def"}, parens=Ø)
1574 self.visit_classdef = partial(v, keywords={"class"}, parens=Ø)
1575 self.visit_expr_stmt = partial(v, keywords=Ø, parens=ASSIGNMENTS)
1576 self.visit_return_stmt = partial(v, keywords={"return"}, parens={"return"})
1577 self.visit_import_from = partial(v, keywords=Ø, parens={"import"})
1578 self.visit_async_funcdef = self.visit_async_stmt
1579 self.visit_decorated = self.visit_decorators
1582 IMPLICIT_TUPLE = {syms.testlist, syms.testlist_star_expr, syms.exprlist}
1583 BRACKET = {token.LPAR: token.RPAR, token.LSQB: token.RSQB, token.LBRACE: token.RBRACE}
1584 OPENING_BRACKETS = set(BRACKET.keys())
1585 CLOSING_BRACKETS = set(BRACKET.values())
1586 BRACKETS = OPENING_BRACKETS | CLOSING_BRACKETS
1587 ALWAYS_NO_SPACE = CLOSING_BRACKETS | {token.COMMA, STANDALONE_COMMENT}
1590 def whitespace(leaf: Leaf, *, complex_subscript: bool) -> str: # noqa C901
1591 """Return whitespace prefix if needed for the given `leaf`.
1593 `complex_subscript` signals whether the given leaf is part of a subscription
1594 which has non-trivial arguments, like arithmetic expressions or function calls.
1602 if t in ALWAYS_NO_SPACE:
1605 if t == token.COMMENT:
1608 assert p is not None, f"INTERNAL ERROR: hand-made leaf without parent: {leaf!r}"
1609 if t == token.COLON and p.type not in {
1616 prev = leaf.prev_sibling
1618 prevp = preceding_leaf(p)
1619 if not prevp or prevp.type in OPENING_BRACKETS:
1622 if t == token.COLON:
1623 if prevp.type == token.COLON:
1626 elif prevp.type != token.COMMA and not complex_subscript:
1631 if prevp.type == token.EQUAL:
1633 if prevp.parent.type in {
1641 elif prevp.parent.type == syms.typedargslist:
1642 # A bit hacky: if the equal sign has whitespace, it means we
1643 # previously found it's a typed argument. So, we're using
1647 elif prevp.type in STARS:
1648 if is_vararg(prevp, within=VARARGS_PARENTS | UNPACKING_PARENTS):
1651 elif prevp.type == token.COLON:
1652 if prevp.parent and prevp.parent.type in {syms.subscript, syms.sliceop}:
1653 return SPACE if complex_subscript else NO
1657 and prevp.parent.type == syms.factor
1658 and prevp.type in MATH_OPERATORS
1663 prevp.type == token.RIGHTSHIFT
1665 and prevp.parent.type == syms.shift_expr
1666 and prevp.prev_sibling
1667 and prevp.prev_sibling.type == token.NAME
1668 and prevp.prev_sibling.value == "print" # type: ignore
1670 # Python 2 print chevron
1673 elif prev.type in OPENING_BRACKETS:
1676 if p.type in {syms.parameters, syms.arglist}:
1677 # untyped function signatures or calls
1678 if not prev or prev.type != token.COMMA:
1681 elif p.type == syms.varargslist:
1683 if prev and prev.type != token.COMMA:
1686 elif p.type == syms.typedargslist:
1687 # typed function signatures
1691 if t == token.EQUAL:
1692 if prev.type != syms.tname:
1695 elif prev.type == token.EQUAL:
1696 # A bit hacky: if the equal sign has whitespace, it means we
1697 # previously found it's a typed argument. So, we're using that, too.
1700 elif prev.type != token.COMMA:
1703 elif p.type == syms.tname:
1706 prevp = preceding_leaf(p)
1707 if not prevp or prevp.type != token.COMMA:
1710 elif p.type == syms.trailer:
1711 # attributes and calls
1712 if t == token.LPAR or t == token.RPAR:
1717 prevp = preceding_leaf(p)
1718 if not prevp or prevp.type != token.NUMBER:
1721 elif t == token.LSQB:
1724 elif prev.type != token.COMMA:
1727 elif p.type == syms.argument:
1729 if t == token.EQUAL:
1733 prevp = preceding_leaf(p)
1734 if not prevp or prevp.type == token.LPAR:
1737 elif prev.type in {token.EQUAL} | STARS:
1740 elif p.type == syms.decorator:
1744 elif p.type == syms.dotted_name:
1748 prevp = preceding_leaf(p)
1749 if not prevp or prevp.type == token.AT or prevp.type == token.DOT:
1752 elif p.type == syms.classdef:
1756 if prev and prev.type == token.LPAR:
1759 elif p.type in {syms.subscript, syms.sliceop}:
1762 assert p.parent is not None, "subscripts are always parented"
1763 if p.parent.type == syms.subscriptlist:
1768 elif not complex_subscript:
1771 elif p.type == syms.atom:
1772 if prev and t == token.DOT:
1773 # dots, but not the first one.
1776 elif p.type == syms.dictsetmaker:
1778 if prev and prev.type == token.DOUBLESTAR:
1781 elif p.type in {syms.factor, syms.star_expr}:
1784 prevp = preceding_leaf(p)
1785 if not prevp or prevp.type in OPENING_BRACKETS:
1788 prevp_parent = prevp.parent
1789 assert prevp_parent is not None
1790 if prevp.type == token.COLON and prevp_parent.type in {
1796 elif prevp.type == token.EQUAL and prevp_parent.type == syms.argument:
1799 elif t in {token.NAME, token.NUMBER, token.STRING}:
1802 elif p.type == syms.import_from:
1804 if prev and prev.type == token.DOT:
1807 elif t == token.NAME:
1811 if prev and prev.type == token.DOT:
1814 elif p.type == syms.sliceop:
1820 def preceding_leaf(node: Optional[LN]) -> Optional[Leaf]:
1821 """Return the first leaf that precedes `node`, if any."""
1823 res = node.prev_sibling
1825 if isinstance(res, Leaf):
1829 return list(res.leaves())[-1]
1838 def child_towards(ancestor: Node, descendant: LN) -> Optional[LN]:
1839 """Return the child of `ancestor` that contains `descendant`."""
1840 node: Optional[LN] = descendant
1841 while node and node.parent != ancestor:
1846 def container_of(leaf: Leaf) -> LN:
1847 """Return `leaf` or one of its ancestors that is the topmost container of it.
1849 By "container" we mean a node where `leaf` is the very first child.
1851 same_prefix = leaf.prefix
1852 container: LN = leaf
1854 parent = container.parent
1858 if parent.children[0].prefix != same_prefix:
1861 if parent.type == syms.file_input:
1864 if parent.prev_sibling is not None and parent.prev_sibling.type in BRACKETS:
1871 def is_split_after_delimiter(leaf: Leaf, previous: Leaf = None) -> int:
1872 """Return the priority of the `leaf` delimiter, given a line break after it.
1874 The delimiter priorities returned here are from those delimiters that would
1875 cause a line break after themselves.
1877 Higher numbers are higher priority.
1879 if leaf.type == token.COMMA:
1880 return COMMA_PRIORITY
1885 def is_split_before_delimiter(leaf: Leaf, previous: Leaf = None) -> int:
1886 """Return the priority of the `leaf` delimiter, given a line before after it.
1888 The delimiter priorities returned here are from those delimiters that would
1889 cause a line break before themselves.
1891 Higher numbers are higher priority.
1893 if is_vararg(leaf, within=VARARGS_PARENTS | UNPACKING_PARENTS):
1894 # * and ** might also be MATH_OPERATORS but in this case they are not.
1895 # Don't treat them as a delimiter.
1899 leaf.type == token.DOT
1901 and leaf.parent.type not in {syms.import_from, syms.dotted_name}
1902 and (previous is None or previous.type in CLOSING_BRACKETS)
1907 leaf.type in MATH_OPERATORS
1909 and leaf.parent.type not in {syms.factor, syms.star_expr}
1911 return MATH_PRIORITIES[leaf.type]
1913 if leaf.type in COMPARATORS:
1914 return COMPARATOR_PRIORITY
1917 leaf.type == token.STRING
1918 and previous is not None
1919 and previous.type == token.STRING
1921 return STRING_PRIORITY
1923 if leaf.type != token.NAME:
1929 and leaf.parent.type in {syms.comp_for, syms.old_comp_for}
1931 return COMPREHENSION_PRIORITY
1936 and leaf.parent.type in {syms.comp_if, syms.old_comp_if}
1938 return COMPREHENSION_PRIORITY
1940 if leaf.value in {"if", "else"} and leaf.parent and leaf.parent.type == syms.test:
1941 return TERNARY_PRIORITY
1943 if leaf.value == "is":
1944 return COMPARATOR_PRIORITY
1949 and leaf.parent.type in {syms.comp_op, syms.comparison}
1951 previous is not None
1952 and previous.type == token.NAME
1953 and previous.value == "not"
1956 return COMPARATOR_PRIORITY
1961 and leaf.parent.type == syms.comp_op
1963 previous is not None
1964 and previous.type == token.NAME
1965 and previous.value == "is"
1968 return COMPARATOR_PRIORITY
1970 if leaf.value in LOGIC_OPERATORS and leaf.parent:
1971 return LOGIC_PRIORITY
1976 FMT_OFF = {"# fmt: off", "# fmt:off", "# yapf: disable"}
1977 FMT_ON = {"# fmt: on", "# fmt:on", "# yapf: enable"}
1980 def generate_comments(leaf: LN) -> Iterator[Leaf]:
1981 """Clean the prefix of the `leaf` and generate comments from it, if any.
1983 Comments in lib2to3 are shoved into the whitespace prefix. This happens
1984 in `pgen2/driver.py:Driver.parse_tokens()`. This was a brilliant implementation
1985 move because it does away with modifying the grammar to include all the
1986 possible places in which comments can be placed.
1988 The sad consequence for us though is that comments don't "belong" anywhere.
1989 This is why this function generates simple parentless Leaf objects for
1990 comments. We simply don't know what the correct parent should be.
1992 No matter though, we can live without this. We really only need to
1993 differentiate between inline and standalone comments. The latter don't
1994 share the line with any code.
1996 Inline comments are emitted as regular token.COMMENT leaves. Standalone
1997 are emitted with a fake STANDALONE_COMMENT token identifier.
1999 for pc in list_comments(leaf.prefix, is_endmarker=leaf.type == token.ENDMARKER):
2000 yield Leaf(pc.type, pc.value, prefix="\n" * pc.newlines)
2005 type: int # token.COMMENT or STANDALONE_COMMENT
2006 value: str # content of the comment
2007 newlines: int # how many newlines before the comment
2008 consumed: int # how many characters of the original leaf's prefix did we consume
2011 @lru_cache(maxsize=4096)
2012 def list_comments(prefix: str, *, is_endmarker: bool) -> List[ProtoComment]:
2013 result: List[ProtoComment] = []
2014 if not prefix or "#" not in prefix:
2019 for index, line in enumerate(prefix.split("\n")):
2020 consumed += len(line) + 1 # adding the length of the split '\n'
2021 line = line.lstrip()
2024 if not line.startswith("#"):
2027 if index == 0 and not is_endmarker:
2028 comment_type = token.COMMENT # simple trailing comment
2030 comment_type = STANDALONE_COMMENT
2031 comment = make_comment(line)
2034 type=comment_type, value=comment, newlines=nlines, consumed=consumed
2041 def make_comment(content: str) -> str:
2042 """Return a consistently formatted comment from the given `content` string.
2044 All comments (except for "##", "#!", "#:") should have a single space between
2045 the hash sign and the content.
2047 If `content` didn't start with a hash sign, one is provided.
2049 content = content.rstrip()
2053 if content[0] == "#":
2054 content = content[1:]
2055 if content and content[0] not in " !:#":
2056 content = " " + content
2057 return "#" + content
2061 line: Line, line_length: int, inner: bool = False, py36: bool = False
2062 ) -> Iterator[Line]:
2063 """Split a `line` into potentially many lines.
2065 They should fit in the allotted `line_length` but might not be able to.
2066 `inner` signifies that there were a pair of brackets somewhere around the
2067 current `line`, possibly transitively. This means we can fallback to splitting
2068 by delimiters if the LHS/RHS don't yield any results.
2070 If `py36` is True, splitting may generate syntax that is only compatible
2071 with Python 3.6 and later.
2077 line_str = str(line).strip("\n")
2078 if not line.should_explode and is_line_short_enough(
2079 line, line_length=line_length, line_str=line_str
2084 split_funcs: List[SplitFunc]
2086 split_funcs = [left_hand_split]
2089 def rhs(line: Line, py36: bool = False) -> Iterator[Line]:
2090 for omit in generate_trailers_to_omit(line, line_length):
2091 lines = list(right_hand_split(line, line_length, py36, omit=omit))
2092 if is_line_short_enough(lines[0], line_length=line_length):
2096 # All splits failed, best effort split with no omits.
2097 # This mostly happens to multiline strings that are by definition
2098 # reported as not fitting a single line.
2099 yield from right_hand_split(line, py36)
2101 if line.inside_brackets:
2102 split_funcs = [delimiter_split, standalone_comment_split, rhs]
2105 for split_func in split_funcs:
2106 # We are accumulating lines in `result` because we might want to abort
2107 # mission and return the original line in the end, or attempt a different
2109 result: List[Line] = []
2111 for l in split_func(line, py36):
2112 if str(l).strip("\n") == line_str:
2113 raise CannotSplit("Split function returned an unchanged result")
2116 split_line(l, line_length=line_length, inner=True, py36=py36)
2118 except CannotSplit as cs:
2129 def left_hand_split(line: Line, py36: bool = False) -> Iterator[Line]:
2130 """Split line into many lines, starting with the first matching bracket pair.
2132 Note: this usually looks weird, only use this for function definitions.
2133 Prefer RHS otherwise. This is why this function is not symmetrical with
2134 :func:`right_hand_split` which also handles optional parentheses.
2136 head = Line(depth=line.depth)
2137 body = Line(depth=line.depth + 1, inside_brackets=True)
2138 tail = Line(depth=line.depth)
2139 tail_leaves: List[Leaf] = []
2140 body_leaves: List[Leaf] = []
2141 head_leaves: List[Leaf] = []
2142 current_leaves = head_leaves
2143 matching_bracket = None
2144 for leaf in line.leaves:
2146 current_leaves is body_leaves
2147 and leaf.type in CLOSING_BRACKETS
2148 and leaf.opening_bracket is matching_bracket
2150 current_leaves = tail_leaves if body_leaves else head_leaves
2151 current_leaves.append(leaf)
2152 if current_leaves is head_leaves:
2153 if leaf.type in OPENING_BRACKETS:
2154 matching_bracket = leaf
2155 current_leaves = body_leaves
2156 # Since body is a new indent level, remove spurious leading whitespace.
2158 normalize_prefix(body_leaves[0], inside_brackets=True)
2159 # Build the new lines.
2160 for result, leaves in (head, head_leaves), (body, body_leaves), (tail, tail_leaves):
2162 result.append(leaf, preformatted=True)
2163 for comment_after in line.comments_after(leaf):
2164 result.append(comment_after, preformatted=True)
2165 bracket_split_succeeded_or_raise(head, body, tail)
2166 for result in (head, body, tail):
2171 def right_hand_split(
2172 line: Line, line_length: int, py36: bool = False, omit: Collection[LeafID] = ()
2173 ) -> Iterator[Line]:
2174 """Split line into many lines, starting with the last matching bracket pair.
2176 If the split was by optional parentheses, attempt splitting without them, too.
2177 `omit` is a collection of closing bracket IDs that shouldn't be considered for
2180 Note: running this function modifies `bracket_depth` on the leaves of `line`.
2182 head = Line(depth=line.depth)
2183 body = Line(depth=line.depth + 1, inside_brackets=True)
2184 tail = Line(depth=line.depth)
2185 tail_leaves: List[Leaf] = []
2186 body_leaves: List[Leaf] = []
2187 head_leaves: List[Leaf] = []
2188 current_leaves = tail_leaves
2189 opening_bracket = None
2190 closing_bracket = None
2191 for leaf in reversed(line.leaves):
2192 if current_leaves is body_leaves:
2193 if leaf is opening_bracket:
2194 current_leaves = head_leaves if body_leaves else tail_leaves
2195 current_leaves.append(leaf)
2196 if current_leaves is tail_leaves:
2197 if leaf.type in CLOSING_BRACKETS and id(leaf) not in omit:
2198 opening_bracket = leaf.opening_bracket
2199 closing_bracket = leaf
2200 current_leaves = body_leaves
2201 tail_leaves.reverse()
2202 body_leaves.reverse()
2203 head_leaves.reverse()
2204 # Since body is a new indent level, remove spurious leading whitespace.
2206 normalize_prefix(body_leaves[0], inside_brackets=True)
2208 # No `head` means the split failed. Either `tail` has all content or
2209 # the matching `opening_bracket` wasn't available on `line` anymore.
2210 raise CannotSplit("No brackets found")
2212 # Build the new lines.
2213 for result, leaves in (head, head_leaves), (body, body_leaves), (tail, tail_leaves):
2215 result.append(leaf, preformatted=True)
2216 for comment_after in line.comments_after(leaf):
2217 result.append(comment_after, preformatted=True)
2218 assert opening_bracket and closing_bracket
2219 body.should_explode = should_explode(body, opening_bracket)
2220 bracket_split_succeeded_or_raise(head, body, tail)
2222 # the body shouldn't be exploded
2223 not body.should_explode
2224 # the opening bracket is an optional paren
2225 and opening_bracket.type == token.LPAR
2226 and not opening_bracket.value
2227 # the closing bracket is an optional paren
2228 and closing_bracket.type == token.RPAR
2229 and not closing_bracket.value
2230 # it's not an import (optional parens are the only thing we can split on
2231 # in this case; attempting a split without them is a waste of time)
2232 and not line.is_import
2233 # there are no standalone comments in the body
2234 and not body.contains_standalone_comments(0)
2235 # and we can actually remove the parens
2236 and can_omit_invisible_parens(body, line_length)
2238 omit = {id(closing_bracket), *omit}
2240 yield from right_hand_split(line, line_length, py36=py36, omit=omit)
2246 or is_line_short_enough(body, line_length=line_length)
2249 "Splitting failed, body is still too long and can't be split."
2252 elif head.contains_multiline_strings() or tail.contains_multiline_strings():
2254 "The current optional pair of parentheses is bound to fail to "
2255 "satisfy the splitting algorithm because the head or the tail "
2256 "contains multiline strings which by definition never fit one "
2260 ensure_visible(opening_bracket)
2261 ensure_visible(closing_bracket)
2262 for result in (head, body, tail):
2267 def bracket_split_succeeded_or_raise(head: Line, body: Line, tail: Line) -> None:
2268 """Raise :exc:`CannotSplit` if the last left- or right-hand split failed.
2270 Do nothing otherwise.
2272 A left- or right-hand split is based on a pair of brackets. Content before
2273 (and including) the opening bracket is left on one line, content inside the
2274 brackets is put on a separate line, and finally content starting with and
2275 following the closing bracket is put on a separate line.
2277 Those are called `head`, `body`, and `tail`, respectively. If the split
2278 produced the same line (all content in `head`) or ended up with an empty `body`
2279 and the `tail` is just the closing bracket, then it's considered failed.
2281 tail_len = len(str(tail).strip())
2284 raise CannotSplit("Splitting brackets produced the same line")
2288 f"Splitting brackets on an empty body to save "
2289 f"{tail_len} characters is not worth it"
2293 def dont_increase_indentation(split_func: SplitFunc) -> SplitFunc:
2294 """Normalize prefix of the first leaf in every line returned by `split_func`.
2296 This is a decorator over relevant split functions.
2300 def split_wrapper(line: Line, py36: bool = False) -> Iterator[Line]:
2301 for l in split_func(line, py36):
2302 normalize_prefix(l.leaves[0], inside_brackets=True)
2305 return split_wrapper
2308 @dont_increase_indentation
2309 def delimiter_split(line: Line, py36: bool = False) -> Iterator[Line]:
2310 """Split according to delimiters of the highest priority.
2312 If `py36` is True, the split will add trailing commas also in function
2313 signatures that contain `*` and `**`.
2316 last_leaf = line.leaves[-1]
2318 raise CannotSplit("Line empty")
2320 bt = line.bracket_tracker
2322 delimiter_priority = bt.max_delimiter_priority(exclude={id(last_leaf)})
2324 raise CannotSplit("No delimiters found")
2326 if delimiter_priority == DOT_PRIORITY:
2327 if bt.delimiter_count_with_priority(delimiter_priority) == 1:
2328 raise CannotSplit("Splitting a single attribute from its owner looks wrong")
2330 current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
2331 lowest_depth = sys.maxsize
2332 trailing_comma_safe = True
2334 def append_to_line(leaf: Leaf) -> Iterator[Line]:
2335 """Append `leaf` to current line or to new line if appending impossible."""
2336 nonlocal current_line
2338 current_line.append_safe(leaf, preformatted=True)
2339 except ValueError as ve:
2342 current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
2343 current_line.append(leaf)
2345 for index, leaf in enumerate(line.leaves):
2346 yield from append_to_line(leaf)
2348 for comment_after in line.comments_after(leaf, index):
2349 yield from append_to_line(comment_after)
2351 lowest_depth = min(lowest_depth, leaf.bracket_depth)
2352 if leaf.bracket_depth == lowest_depth and is_vararg(
2353 leaf, within=VARARGS_PARENTS
2355 trailing_comma_safe = trailing_comma_safe and py36
2356 leaf_priority = bt.delimiters.get(id(leaf))
2357 if leaf_priority == delimiter_priority:
2360 current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
2364 and delimiter_priority == COMMA_PRIORITY
2365 and current_line.leaves[-1].type != token.COMMA
2366 and current_line.leaves[-1].type != STANDALONE_COMMENT
2368 current_line.append(Leaf(token.COMMA, ","))
2372 @dont_increase_indentation
2373 def standalone_comment_split(line: Line, py36: bool = False) -> Iterator[Line]:
2374 """Split standalone comments from the rest of the line."""
2375 if not line.contains_standalone_comments(0):
2376 raise CannotSplit("Line does not have any standalone comments")
2378 current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
2380 def append_to_line(leaf: Leaf) -> Iterator[Line]:
2381 """Append `leaf` to current line or to new line if appending impossible."""
2382 nonlocal current_line
2384 current_line.append_safe(leaf, preformatted=True)
2385 except ValueError as ve:
2388 current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
2389 current_line.append(leaf)
2391 for index, leaf in enumerate(line.leaves):
2392 yield from append_to_line(leaf)
2394 for comment_after in line.comments_after(leaf, index):
2395 yield from append_to_line(comment_after)
2401 def is_import(leaf: Leaf) -> bool:
2402 """Return True if the given leaf starts an import statement."""
2409 (v == "import" and p and p.type == syms.import_name)
2410 or (v == "from" and p and p.type == syms.import_from)
2415 def normalize_prefix(leaf: Leaf, *, inside_brackets: bool) -> None:
2416 """Leave existing extra newlines if not `inside_brackets`. Remove everything
2419 Note: don't use backslashes for formatting or you'll lose your voting rights.
2421 if not inside_brackets:
2422 spl = leaf.prefix.split("#")
2423 if "\\" not in spl[0]:
2424 nl_count = spl[-1].count("\n")
2427 leaf.prefix = "\n" * nl_count
2433 def normalize_string_prefix(leaf: Leaf, remove_u_prefix: bool = False) -> None:
2434 """Make all string prefixes lowercase.
2436 If remove_u_prefix is given, also removes any u prefix from the string.
2438 Note: Mutates its argument.
2440 match = re.match(r"^([furbFURB]*)(.*)$", leaf.value, re.DOTALL)
2441 assert match is not None, f"failed to match string {leaf.value!r}"
2442 orig_prefix = match.group(1)
2443 new_prefix = orig_prefix.lower()
2445 new_prefix = new_prefix.replace("u", "")
2446 leaf.value = f"{new_prefix}{match.group(2)}"
2449 def normalize_string_quotes(leaf: Leaf) -> None:
2450 """Prefer double quotes but only if it doesn't cause more escaping.
2452 Adds or removes backslashes as appropriate. Doesn't parse and fix
2453 strings nested in f-strings (yet).
2455 Note: Mutates its argument.
2457 value = leaf.value.lstrip("furbFURB")
2458 if value[:3] == '"""':
2461 elif value[:3] == "'''":
2464 elif value[0] == '"':
2470 first_quote_pos = leaf.value.find(orig_quote)
2471 if first_quote_pos == -1:
2472 return # There's an internal error
2474 prefix = leaf.value[:first_quote_pos]
2475 unescaped_new_quote = re.compile(rf"(([^\\]|^)(\\\\)*){new_quote}")
2476 escaped_new_quote = re.compile(rf"([^\\]|^)\\((?:\\\\)*){new_quote}")
2477 escaped_orig_quote = re.compile(rf"([^\\]|^)\\((?:\\\\)*){orig_quote}")
2478 body = leaf.value[first_quote_pos + len(orig_quote) : -len(orig_quote)]
2479 if "r" in prefix.casefold():
2480 if unescaped_new_quote.search(body):
2481 # There's at least one unescaped new_quote in this raw string
2482 # so converting is impossible
2485 # Do not introduce or remove backslashes in raw strings
2488 # remove unnecessary escapes
2489 new_body = sub_twice(escaped_new_quote, rf"\1\2{new_quote}", body)
2490 if body != new_body:
2491 # Consider the string without unnecessary escapes as the original
2493 leaf.value = f"{prefix}{orig_quote}{body}{orig_quote}"
2494 new_body = sub_twice(escaped_orig_quote, rf"\1\2{orig_quote}", new_body)
2495 new_body = sub_twice(unescaped_new_quote, rf"\1\\{new_quote}", new_body)
2496 if "f" in prefix.casefold():
2497 matches = re.findall(r"[^{]\{(.*?)\}[^}]", new_body)
2500 # Do not introduce backslashes in interpolated expressions
2502 if new_quote == '"""' and new_body[-1:] == '"':
2504 new_body = new_body[:-1] + '\\"'
2505 orig_escape_count = body.count("\\")
2506 new_escape_count = new_body.count("\\")
2507 if new_escape_count > orig_escape_count:
2508 return # Do not introduce more escaping
2510 if new_escape_count == orig_escape_count and orig_quote == '"':
2511 return # Prefer double quotes
2513 leaf.value = f"{prefix}{new_quote}{new_body}{new_quote}"
2516 def normalize_numeric_literal(leaf: Leaf, allow_underscores: bool) -> None:
2517 """Normalizes numeric (float, int, and complex) literals."""
2518 # We want all letters (e in exponents, j in complex literals, a-f
2519 # in hex literals) to be lowercase.
2520 text = leaf.value.lower()
2521 if text.startswith(("0o", "0x", "0b")):
2522 # Leave octal, hex, and binary literals alone for now.
2525 before, after = text.split("e")
2526 if after.startswith("-"):
2529 elif after.startswith("+"):
2534 before = format_float_or_int_string(before, allow_underscores)
2535 after = format_int_string(after, allow_underscores)
2536 text = f"{before}e{sign}{after}"
2537 # Complex numbers and Python 2 longs
2538 elif "j" in text or "l" in text:
2541 text = f"{format_float_or_int_string(number, allow_underscores)}{suffix}"
2543 text = format_float_or_int_string(text, allow_underscores)
2547 def format_float_or_int_string(text: str, allow_underscores: bool) -> str:
2548 """Formats a float string like "1.0"."""
2550 return format_int_string(text, allow_underscores)
2551 before, after = text.split(".")
2552 before = format_int_string(before, allow_underscores) if before else "0"
2553 after = format_int_string(after, allow_underscores) if after else "0"
2554 return f"{before}.{after}"
2557 def format_int_string(text: str, allow_underscores: bool) -> str:
2558 """Normalizes underscores in a string to e.g. 1_000_000.
2560 Input must be a string consisting only of digits and underscores.
2562 if not allow_underscores:
2564 text = text.replace("_", "")
2566 # No underscores for numbers <= 6 digits long.
2568 return format(int(text), "3_")
2571 def normalize_invisible_parens(node: Node, parens_after: Set[str]) -> None:
2572 """Make existing optional parentheses invisible or create new ones.
2574 `parens_after` is a set of string leaf values immeditely after which parens
2577 Standardizes on visible parentheses for single-element tuples, and keeps
2578 existing visible parentheses for other tuples and generator expressions.
2580 for pc in list_comments(node.prefix, is_endmarker=False):
2581 if pc.value in FMT_OFF:
2582 # This `node` has a prefix with `# fmt: off`, don't mess with parens.
2586 for index, child in enumerate(list(node.children)):
2588 if child.type == syms.atom:
2589 maybe_make_parens_invisible_in_atom(child)
2590 elif is_one_tuple(child):
2591 # wrap child in visible parentheses
2592 lpar = Leaf(token.LPAR, "(")
2593 rpar = Leaf(token.RPAR, ")")
2595 node.insert_child(index, Node(syms.atom, [lpar, child, rpar]))
2596 elif node.type == syms.import_from:
2597 # "import from" nodes store parentheses directly as part of
2599 if child.type == token.LPAR:
2600 # make parentheses invisible
2601 child.value = "" # type: ignore
2602 node.children[-1].value = "" # type: ignore
2603 elif child.type != token.STAR:
2604 # insert invisible parentheses
2605 node.insert_child(index, Leaf(token.LPAR, ""))
2606 node.append_child(Leaf(token.RPAR, ""))
2609 elif not (isinstance(child, Leaf) and is_multiline_string(child)):
2610 # wrap child in invisible parentheses
2611 lpar = Leaf(token.LPAR, "")
2612 rpar = Leaf(token.RPAR, "")
2613 index = child.remove() or 0
2614 node.insert_child(index, Node(syms.atom, [lpar, child, rpar]))
2616 check_lpar = isinstance(child, Leaf) and child.value in parens_after
2619 def normalize_fmt_off(node: Node) -> None:
2620 """Convert content between `# fmt: off`/`# fmt: on` into standalone comments."""
2623 try_again = convert_one_fmt_off_pair(node)
2626 def convert_one_fmt_off_pair(node: Node) -> bool:
2627 """Convert content of a single `# fmt: off`/`# fmt: on` into a standalone comment.
2629 Returns True if a pair was converted.
2631 for leaf in node.leaves():
2632 previous_consumed = 0
2633 for comment in list_comments(leaf.prefix, is_endmarker=False):
2634 if comment.value in FMT_OFF:
2635 # We only want standalone comments. If there's no previous leaf or
2636 # the previous leaf is indentation, it's a standalone comment in
2638 if comment.type != STANDALONE_COMMENT:
2639 prev = preceding_leaf(leaf)
2640 if prev and prev.type not in WHITESPACE:
2643 ignored_nodes = list(generate_ignored_nodes(leaf))
2644 if not ignored_nodes:
2647 first = ignored_nodes[0] # Can be a container node with the `leaf`.
2648 parent = first.parent
2649 prefix = first.prefix
2650 first.prefix = prefix[comment.consumed :]
2652 comment.value + "\n" + "".join(str(n) for n in ignored_nodes)
2654 if hidden_value.endswith("\n"):
2655 # That happens when one of the `ignored_nodes` ended with a NEWLINE
2656 # leaf (possibly followed by a DEDENT).
2657 hidden_value = hidden_value[:-1]
2659 for ignored in ignored_nodes:
2660 index = ignored.remove()
2661 if first_idx is None:
2663 assert parent is not None, "INTERNAL ERROR: fmt: on/off handling (1)"
2664 assert first_idx is not None, "INTERNAL ERROR: fmt: on/off handling (2)"
2665 parent.insert_child(
2670 prefix=prefix[:previous_consumed] + "\n" * comment.newlines,
2675 previous_consumed = comment.consumed
2680 def generate_ignored_nodes(leaf: Leaf) -> Iterator[LN]:
2681 """Starting from the container of `leaf`, generate all leaves until `# fmt: on`.
2683 Stops at the end of the block.
2685 container: Optional[LN] = container_of(leaf)
2686 while container is not None and container.type != token.ENDMARKER:
2687 for comment in list_comments(container.prefix, is_endmarker=False):
2688 if comment.value in FMT_ON:
2693 container = container.next_sibling
2696 def maybe_make_parens_invisible_in_atom(node: LN) -> bool:
2697 """If it's safe, make the parens in the atom `node` invisible, recursively."""
2699 node.type != syms.atom
2700 or is_empty_tuple(node)
2701 or is_one_tuple(node)
2703 or max_delimiter_priority_in_atom(node) >= COMMA_PRIORITY
2707 first = node.children[0]
2708 last = node.children[-1]
2709 if first.type == token.LPAR and last.type == token.RPAR:
2710 # make parentheses invisible
2711 first.value = "" # type: ignore
2712 last.value = "" # type: ignore
2713 if len(node.children) > 1:
2714 maybe_make_parens_invisible_in_atom(node.children[1])
2720 def is_empty_tuple(node: LN) -> bool:
2721 """Return True if `node` holds an empty tuple."""
2723 node.type == syms.atom
2724 and len(node.children) == 2
2725 and node.children[0].type == token.LPAR
2726 and node.children[1].type == token.RPAR
2730 def is_one_tuple(node: LN) -> bool:
2731 """Return True if `node` holds a tuple with one element, with or without parens."""
2732 if node.type == syms.atom:
2733 if len(node.children) != 3:
2736 lpar, gexp, rpar = node.children
2738 lpar.type == token.LPAR
2739 and gexp.type == syms.testlist_gexp
2740 and rpar.type == token.RPAR
2744 return len(gexp.children) == 2 and gexp.children[1].type == token.COMMA
2747 node.type in IMPLICIT_TUPLE
2748 and len(node.children) == 2
2749 and node.children[1].type == token.COMMA
2753 def is_yield(node: LN) -> bool:
2754 """Return True if `node` holds a `yield` or `yield from` expression."""
2755 if node.type == syms.yield_expr:
2758 if node.type == token.NAME and node.value == "yield": # type: ignore
2761 if node.type != syms.atom:
2764 if len(node.children) != 3:
2767 lpar, expr, rpar = node.children
2768 if lpar.type == token.LPAR and rpar.type == token.RPAR:
2769 return is_yield(expr)
2774 def is_vararg(leaf: Leaf, within: Set[NodeType]) -> bool:
2775 """Return True if `leaf` is a star or double star in a vararg or kwarg.
2777 If `within` includes VARARGS_PARENTS, this applies to function signatures.
2778 If `within` includes UNPACKING_PARENTS, it applies to right hand-side
2779 extended iterable unpacking (PEP 3132) and additional unpacking
2780 generalizations (PEP 448).
2782 if leaf.type not in STARS or not leaf.parent:
2786 if p.type == syms.star_expr:
2787 # Star expressions are also used as assignment targets in extended
2788 # iterable unpacking (PEP 3132). See what its parent is instead.
2794 return p.type in within
2797 def is_multiline_string(leaf: Leaf) -> bool:
2798 """Return True if `leaf` is a multiline string that actually spans many lines."""
2799 value = leaf.value.lstrip("furbFURB")
2800 return value[:3] in {'"""', "'''"} and "\n" in value
2803 def is_stub_suite(node: Node) -> bool:
2804 """Return True if `node` is a suite with a stub body."""
2806 len(node.children) != 4
2807 or node.children[0].type != token.NEWLINE
2808 or node.children[1].type != token.INDENT
2809 or node.children[3].type != token.DEDENT
2813 return is_stub_body(node.children[2])
2816 def is_stub_body(node: LN) -> bool:
2817 """Return True if `node` is a simple statement containing an ellipsis."""
2818 if not isinstance(node, Node) or node.type != syms.simple_stmt:
2821 if len(node.children) != 2:
2824 child = node.children[0]
2826 child.type == syms.atom
2827 and len(child.children) == 3
2828 and all(leaf == Leaf(token.DOT, ".") for leaf in child.children)
2832 def max_delimiter_priority_in_atom(node: LN) -> int:
2833 """Return maximum delimiter priority inside `node`.
2835 This is specific to atoms with contents contained in a pair of parentheses.
2836 If `node` isn't an atom or there are no enclosing parentheses, returns 0.
2838 if node.type != syms.atom:
2841 first = node.children[0]
2842 last = node.children[-1]
2843 if not (first.type == token.LPAR and last.type == token.RPAR):
2846 bt = BracketTracker()
2847 for c in node.children[1:-1]:
2848 if isinstance(c, Leaf):
2851 for leaf in c.leaves():
2854 return bt.max_delimiter_priority()
2860 def ensure_visible(leaf: Leaf) -> None:
2861 """Make sure parentheses are visible.
2863 They could be invisible as part of some statements (see
2864 :func:`normalize_invible_parens` and :func:`visit_import_from`).
2866 if leaf.type == token.LPAR:
2868 elif leaf.type == token.RPAR:
2872 def should_explode(line: Line, opening_bracket: Leaf) -> bool:
2873 """Should `line` immediately be split with `delimiter_split()` after RHS?"""
2875 opening_bracket.parent
2876 and opening_bracket.parent.type in {syms.atom, syms.import_from}
2877 and opening_bracket.value in "[{("
2882 last_leaf = line.leaves[-1]
2883 exclude = {id(last_leaf)} if last_leaf.type == token.COMMA else set()
2884 max_priority = line.bracket_tracker.max_delimiter_priority(exclude=exclude)
2885 except (IndexError, ValueError):
2888 return max_priority == COMMA_PRIORITY
2891 def is_python36(node: Node) -> bool:
2892 """Return True if the current file is using Python 3.6+ features.
2894 Currently looking for:
2896 - trailing commas after * or ** in function signatures and calls.
2898 for n in node.pre_order():
2899 if n.type == token.STRING:
2900 value_head = n.value[:2] # type: ignore
2901 if value_head in {'f"', 'F"', "f'", "F'", "rf", "fr", "RF", "FR"}:
2905 n.type in {syms.typedargslist, syms.arglist}
2907 and n.children[-1].type == token.COMMA
2909 for ch in n.children:
2910 if ch.type in STARS:
2913 if ch.type == syms.argument:
2914 for argch in ch.children:
2915 if argch.type in STARS:
2921 def generate_trailers_to_omit(line: Line, line_length: int) -> Iterator[Set[LeafID]]:
2922 """Generate sets of closing bracket IDs that should be omitted in a RHS.
2924 Brackets can be omitted if the entire trailer up to and including
2925 a preceding closing bracket fits in one line.
2927 Yielded sets are cumulative (contain results of previous yields, too). First
2931 omit: Set[LeafID] = set()
2934 length = 4 * line.depth
2935 opening_bracket = None
2936 closing_bracket = None
2937 optional_brackets: Set[LeafID] = set()
2938 inner_brackets: Set[LeafID] = set()
2939 for index, leaf, leaf_length in enumerate_with_length(line, reversed=True):
2940 length += leaf_length
2941 if length > line_length:
2944 has_inline_comment = leaf_length > len(leaf.value) + len(leaf.prefix)
2945 if leaf.type == STANDALONE_COMMENT or has_inline_comment:
2948 optional_brackets.discard(id(leaf))
2950 if leaf is opening_bracket:
2951 opening_bracket = None
2952 elif leaf.type in CLOSING_BRACKETS:
2953 inner_brackets.add(id(leaf))
2954 elif leaf.type in CLOSING_BRACKETS:
2956 optional_brackets.add(id(opening_bracket))
2959 if index > 0 and line.leaves[index - 1].type in OPENING_BRACKETS:
2960 # Empty brackets would fail a split so treat them as "inner"
2961 # brackets (e.g. only add them to the `omit` set if another
2962 # pair of brackets was good enough.
2963 inner_brackets.add(id(leaf))
2966 opening_bracket = leaf.opening_bracket
2968 omit.add(id(closing_bracket))
2969 omit.update(inner_brackets)
2970 inner_brackets.clear()
2972 closing_bracket = leaf
2975 def get_future_imports(node: Node) -> Set[str]:
2976 """Return a set of __future__ imports in the file."""
2977 imports: Set[str] = set()
2979 def get_imports_from_children(children: List[LN]) -> Generator[str, None, None]:
2980 for child in children:
2981 if isinstance(child, Leaf):
2982 if child.type == token.NAME:
2984 elif child.type == syms.import_as_name:
2985 orig_name = child.children[0]
2986 assert isinstance(orig_name, Leaf), "Invalid syntax parsing imports"
2987 assert orig_name.type == token.NAME, "Invalid syntax parsing imports"
2988 yield orig_name.value
2989 elif child.type == syms.import_as_names:
2990 yield from get_imports_from_children(child.children)
2992 assert False, "Invalid syntax parsing imports"
2994 for child in node.children:
2995 if child.type != syms.simple_stmt:
2997 first_child = child.children[0]
2998 if isinstance(first_child, Leaf):
2999 # Continue looking if we see a docstring; otherwise stop.
3001 len(child.children) == 2
3002 and first_child.type == token.STRING
3003 and child.children[1].type == token.NEWLINE
3008 elif first_child.type == syms.import_from:
3009 module_name = first_child.children[1]
3010 if not isinstance(module_name, Leaf) or module_name.value != "__future__":
3012 imports |= set(get_imports_from_children(first_child.children[3:]))
3018 def gen_python_files_in_dir(
3021 include: Pattern[str],
3022 exclude: Pattern[str],
3024 ) -> Iterator[Path]:
3025 """Generate all files under `path` whose paths are not excluded by the
3026 `exclude` regex, but are included by the `include` regex.
3028 Symbolic links pointing outside of the `root` directory are ignored.
3030 `report` is where output about exclusions goes.
3032 assert root.is_absolute(), f"INTERNAL ERROR: `root` must be absolute but is {root}"
3033 for child in path.iterdir():
3035 normalized_path = "/" + child.resolve().relative_to(root).as_posix()
3037 if child.is_symlink():
3038 report.path_ignored(
3039 child, f"is a symbolic link that points outside {root}"
3046 normalized_path += "/"
3047 exclude_match = exclude.search(normalized_path)
3048 if exclude_match and exclude_match.group(0):
3049 report.path_ignored(child, f"matches the --exclude regular expression")
3053 yield from gen_python_files_in_dir(child, root, include, exclude, report)
3055 elif child.is_file():
3056 include_match = include.search(normalized_path)
3062 def find_project_root(srcs: Iterable[str]) -> Path:
3063 """Return a directory containing .git, .hg, or pyproject.toml.
3065 That directory can be one of the directories passed in `srcs` or their
3068 If no directory in the tree contains a marker that would specify it's the
3069 project root, the root of the file system is returned.
3072 return Path("/").resolve()
3074 common_base = min(Path(src).resolve() for src in srcs)
3075 if common_base.is_dir():
3076 # Append a fake file so `parents` below returns `common_base_dir`, too.
3077 common_base /= "fake-file"
3078 for directory in common_base.parents:
3079 if (directory / ".git").is_dir():
3082 if (directory / ".hg").is_dir():
3085 if (directory / "pyproject.toml").is_file():
3093 """Provides a reformatting counter. Can be rendered with `str(report)`."""
3097 verbose: bool = False
3098 change_count: int = 0
3100 failure_count: int = 0
3102 def done(self, src: Path, changed: Changed) -> None:
3103 """Increment the counter for successful reformatting. Write out a message."""
3104 if changed is Changed.YES:
3105 reformatted = "would reformat" if self.check else "reformatted"
3106 if self.verbose or not self.quiet:
3107 out(f"{reformatted} {src}")
3108 self.change_count += 1
3111 if changed is Changed.NO:
3112 msg = f"{src} already well formatted, good job."
3114 msg = f"{src} wasn't modified on disk since last run."
3115 out(msg, bold=False)
3116 self.same_count += 1
3118 def failed(self, src: Path, message: str) -> None:
3119 """Increment the counter for failed reformatting. Write out a message."""
3120 err(f"error: cannot format {src}: {message}")
3121 self.failure_count += 1
3123 def path_ignored(self, path: Path, message: str) -> None:
3125 out(f"{path} ignored: {message}", bold=False)
3128 def return_code(self) -> int:
3129 """Return the exit code that the app should use.
3131 This considers the current state of changed files and failures:
3132 - if there were any failures, return 123;
3133 - if any files were changed and --check is being used, return 1;
3134 - otherwise return 0.
3136 # According to http://tldp.org/LDP/abs/html/exitcodes.html starting with
3137 # 126 we have special returncodes reserved by the shell.
3138 if self.failure_count:
3141 elif self.change_count and self.check:
3146 def __str__(self) -> str:
3147 """Render a color report of the current state.
3149 Use `click.unstyle` to remove colors.
3152 reformatted = "would be reformatted"
3153 unchanged = "would be left unchanged"
3154 failed = "would fail to reformat"
3156 reformatted = "reformatted"
3157 unchanged = "left unchanged"
3158 failed = "failed to reformat"
3160 if self.change_count:
3161 s = "s" if self.change_count > 1 else ""
3163 click.style(f"{self.change_count} file{s} {reformatted}", bold=True)
3166 s = "s" if self.same_count > 1 else ""
3167 report.append(f"{self.same_count} file{s} {unchanged}")
3168 if self.failure_count:
3169 s = "s" if self.failure_count > 1 else ""
3171 click.style(f"{self.failure_count} file{s} {failed}", fg="red")
3173 return ", ".join(report) + "."
3176 def assert_equivalent(src: str, dst: str) -> None:
3177 """Raise AssertionError if `src` and `dst` aren't equivalent."""
3182 def _v(node: ast.AST, depth: int = 0) -> Iterator[str]:
3183 """Simple visitor generating strings to compare ASTs by content."""
3184 yield f"{' ' * depth}{node.__class__.__name__}("
3186 for field in sorted(node._fields):
3188 value = getattr(node, field)
3189 except AttributeError:
3192 yield f"{' ' * (depth+1)}{field}="
3194 if isinstance(value, list):
3196 if isinstance(item, ast.AST):
3197 yield from _v(item, depth + 2)
3199 elif isinstance(value, ast.AST):
3200 yield from _v(value, depth + 2)
3203 yield f"{' ' * (depth+2)}{value!r}, # {value.__class__.__name__}"
3205 yield f"{' ' * depth}) # /{node.__class__.__name__}"
3208 src_ast = ast.parse(src)
3209 except Exception as exc:
3210 major, minor = sys.version_info[:2]
3211 raise AssertionError(
3212 f"cannot use --safe with this file; failed to parse source file "
3213 f"with Python {major}.{minor}'s builtin AST. Re-run with --fast "
3214 f"or stop using deprecated Python 2 syntax. AST error message: {exc}"
3218 dst_ast = ast.parse(dst)
3219 except Exception as exc:
3220 log = dump_to_file("".join(traceback.format_tb(exc.__traceback__)), dst)
3221 raise AssertionError(
3222 f"INTERNAL ERROR: Black produced invalid code: {exc}. "
3223 f"Please report a bug on https://github.com/ambv/black/issues. "
3224 f"This invalid output might be helpful: {log}"
3227 src_ast_str = "\n".join(_v(src_ast))
3228 dst_ast_str = "\n".join(_v(dst_ast))
3229 if src_ast_str != dst_ast_str:
3230 log = dump_to_file(diff(src_ast_str, dst_ast_str, "src", "dst"))
3231 raise AssertionError(
3232 f"INTERNAL ERROR: Black produced code that is not equivalent to "
3234 f"Please report a bug on https://github.com/ambv/black/issues. "
3235 f"This diff might be helpful: {log}"
3240 src: str, dst: str, line_length: int, mode: FileMode = FileMode.AUTO_DETECT
3242 """Raise AssertionError if `dst` reformats differently the second time."""
3243 newdst = format_str(dst, line_length=line_length, mode=mode)
3246 diff(src, dst, "source", "first pass"),
3247 diff(dst, newdst, "first pass", "second pass"),
3249 raise AssertionError(
3250 f"INTERNAL ERROR: Black produced different code on the second pass "
3251 f"of the formatter. "
3252 f"Please report a bug on https://github.com/ambv/black/issues. "
3253 f"This diff might be helpful: {log}"
3257 def dump_to_file(*output: str) -> str:
3258 """Dump `output` to a temporary file. Return path to the file."""
3261 with tempfile.NamedTemporaryFile(
3262 mode="w", prefix="blk_", suffix=".log", delete=False, encoding="utf8"
3264 for lines in output:
3266 if lines and lines[-1] != "\n":
3271 def diff(a: str, b: str, a_name: str, b_name: str) -> str:
3272 """Return a unified diff string between strings `a` and `b`."""
3275 a_lines = [line + "\n" for line in a.split("\n")]
3276 b_lines = [line + "\n" for line in b.split("\n")]
3278 difflib.unified_diff(a_lines, b_lines, fromfile=a_name, tofile=b_name, n=5)
3282 def cancel(tasks: Iterable[asyncio.Task]) -> None:
3283 """asyncio signal handler that cancels all `tasks` and reports to stderr."""
3289 def shutdown(loop: BaseEventLoop) -> None:
3290 """Cancel all pending tasks on `loop`, wait for them, and close the loop."""
3292 # This part is borrowed from asyncio/runners.py in Python 3.7b2.
3293 to_cancel = [task for task in asyncio.Task.all_tasks(loop) if not task.done()]
3297 for task in to_cancel:
3299 loop.run_until_complete(
3300 asyncio.gather(*to_cancel, loop=loop, return_exceptions=True)
3303 # `concurrent.futures.Future` objects cannot be cancelled once they
3304 # are already running. There might be some when the `shutdown()` happened.
3305 # Silence their logger's spew about the event loop being closed.
3306 cf_logger = logging.getLogger("concurrent.futures")
3307 cf_logger.setLevel(logging.CRITICAL)
3311 def sub_twice(regex: Pattern[str], replacement: str, original: str) -> str:
3312 """Replace `regex` with `replacement` twice on `original`.
3314 This is used by string normalization to perform replaces on
3315 overlapping matches.
3317 return regex.sub(replacement, regex.sub(replacement, original))
3320 def re_compile_maybe_verbose(regex: str) -> Pattern[str]:
3321 """Compile a regular expression string in `regex`.
3323 If it contains newlines, use verbose mode.
3326 regex = "(?x)" + regex
3327 return re.compile(regex)
3330 def enumerate_reversed(sequence: Sequence[T]) -> Iterator[Tuple[Index, T]]:
3331 """Like `reversed(enumerate(sequence))` if that were possible."""
3332 index = len(sequence) - 1
3333 for element in reversed(sequence):
3334 yield (index, element)
3338 def enumerate_with_length(
3339 line: Line, reversed: bool = False
3340 ) -> Iterator[Tuple[Index, Leaf, int]]:
3341 """Return an enumeration of leaves with their length.
3343 Stops prematurely on multiline strings and standalone comments.
3346 Callable[[Sequence[Leaf]], Iterator[Tuple[Index, Leaf]]],
3347 enumerate_reversed if reversed else enumerate,
3349 for index, leaf in op(line.leaves):
3350 length = len(leaf.prefix) + len(leaf.value)
3351 if "\n" in leaf.value:
3352 return # Multiline strings, we can't continue.
3354 comment: Optional[Leaf]
3355 for comment in line.comments_after(leaf, index):
3356 length += len(comment.value)
3358 yield index, leaf, length
3361 def is_line_short_enough(line: Line, *, line_length: int, line_str: str = "") -> bool:
3362 """Return True if `line` is no longer than `line_length`.
3364 Uses the provided `line_str` rendering, if any, otherwise computes a new one.
3367 line_str = str(line).strip("\n")
3369 len(line_str) <= line_length
3370 and "\n" not in line_str # multiline strings
3371 and not line.contains_standalone_comments()
3375 def can_be_split(line: Line) -> bool:
3376 """Return False if the line cannot be split *for sure*.
3378 This is not an exhaustive search but a cheap heuristic that we can use to
3379 avoid some unfortunate formattings (mostly around wrapping unsplittable code
3380 in unnecessary parentheses).
3382 leaves = line.leaves
3386 if leaves[0].type == token.STRING and leaves[1].type == token.DOT:
3390 for leaf in leaves[-2::-1]:
3391 if leaf.type in OPENING_BRACKETS:
3392 if next.type not in CLOSING_BRACKETS:
3396 elif leaf.type == token.DOT:
3398 elif leaf.type == token.NAME:
3399 if not (next.type == token.DOT or next.type in OPENING_BRACKETS):
3402 elif leaf.type not in CLOSING_BRACKETS:
3405 if dot_count > 1 and call_count > 1:
3411 def can_omit_invisible_parens(line: Line, line_length: int) -> bool:
3412 """Does `line` have a shape safe to reformat without optional parens around it?
3414 Returns True for only a subset of potentially nice looking formattings but
3415 the point is to not return false positives that end up producing lines that
3418 bt = line.bracket_tracker
3419 if not bt.delimiters:
3420 # Without delimiters the optional parentheses are useless.
3423 max_priority = bt.max_delimiter_priority()
3424 if bt.delimiter_count_with_priority(max_priority) > 1:
3425 # With more than one delimiter of a kind the optional parentheses read better.
3428 if max_priority == DOT_PRIORITY:
3429 # A single stranded method call doesn't require optional parentheses.
3432 assert len(line.leaves) >= 2, "Stranded delimiter"
3434 first = line.leaves[0]
3435 second = line.leaves[1]
3436 penultimate = line.leaves[-2]
3437 last = line.leaves[-1]
3439 # With a single delimiter, omit if the expression starts or ends with
3441 if first.type in OPENING_BRACKETS and second.type not in CLOSING_BRACKETS:
3443 length = 4 * line.depth
3444 for _index, leaf, leaf_length in enumerate_with_length(line):
3445 if leaf.type in CLOSING_BRACKETS and leaf.opening_bracket is first:
3448 length += leaf_length
3449 if length > line_length:
3452 if leaf.type in OPENING_BRACKETS:
3453 # There are brackets we can further split on.
3457 # checked the entire string and line length wasn't exceeded
3458 if len(line.leaves) == _index + 1:
3461 # Note: we are not returning False here because a line might have *both*
3462 # a leading opening bracket and a trailing closing bracket. If the
3463 # opening bracket doesn't match our rule, maybe the closing will.
3466 last.type == token.RPAR
3467 or last.type == token.RBRACE
3469 # don't use indexing for omitting optional parentheses;
3471 last.type == token.RSQB
3473 and last.parent.type != syms.trailer
3476 if penultimate.type in OPENING_BRACKETS:
3477 # Empty brackets don't help.
3480 if is_multiline_string(first):
3481 # Additional wrapping of a multiline string in this situation is
3485 length = 4 * line.depth
3486 seen_other_brackets = False
3487 for _index, leaf, leaf_length in enumerate_with_length(line):
3488 length += leaf_length
3489 if leaf is last.opening_bracket:
3490 if seen_other_brackets or length <= line_length:
3493 elif leaf.type in OPENING_BRACKETS:
3494 # There are brackets we can further split on.
3495 seen_other_brackets = True
3500 def get_cache_file(line_length: int, mode: FileMode) -> Path:
3501 return CACHE_DIR / f"cache.{line_length}.{mode.value}.pickle"
3504 def read_cache(line_length: int, mode: FileMode) -> Cache:
3505 """Read the cache if it exists and is well formed.
3507 If it is not well formed, the call to write_cache later should resolve the issue.
3509 cache_file = get_cache_file(line_length, mode)
3510 if not cache_file.exists():
3513 with cache_file.open("rb") as fobj:
3515 cache: Cache = pickle.load(fobj)
3516 except pickle.UnpicklingError:
3522 def get_cache_info(path: Path) -> CacheInfo:
3523 """Return the information used to check if a file is already formatted or not."""
3525 return stat.st_mtime, stat.st_size
3528 def filter_cached(cache: Cache, sources: Iterable[Path]) -> Tuple[Set[Path], Set[Path]]:
3529 """Split an iterable of paths in `sources` into two sets.
3531 The first contains paths of files that modified on disk or are not in the
3532 cache. The other contains paths to non-modified files.
3534 todo, done = set(), set()
3537 if cache.get(src) != get_cache_info(src):
3545 cache: Cache, sources: Iterable[Path], line_length: int, mode: FileMode
3547 """Update the cache file."""
3548 cache_file = get_cache_file(line_length, mode)
3550 if not CACHE_DIR.exists():
3551 CACHE_DIR.mkdir(parents=True)
3552 new_cache = {**cache, **{src.resolve(): get_cache_info(src) for src in sources}}
3553 with cache_file.open("wb") as fobj:
3554 pickle.dump(new_cache, fobj, protocol=pickle.HIGHEST_PROTOCOL)
3559 def patch_click() -> None:
3560 """Make Click not crash.
3562 On certain misconfigured environments, Python 3 selects the ASCII encoding as the
3563 default which restricts paths that it can access during the lifetime of the
3564 application. Click refuses to work in this scenario by raising a RuntimeError.
3566 In case of Black the likelihood that non-ASCII characters are going to be used in
3567 file paths is minimal since it's Python source code. Moreover, this crash was
3568 spurious on Python 3.7 thanks to PEP 538 and PEP 540.
3571 from click import core
3572 from click import _unicodefun # type: ignore
3573 except ModuleNotFoundError:
3576 for module in (core, _unicodefun):
3577 if hasattr(module, "_verify_python3_env"):
3578 module._verify_python3_env = lambda: None
3581 if __name__ == "__main__":