]> git.madduck.net Git - etc/vim.git/blob - black.py

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

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.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Remove nonsensical grammar from blib2to3
[etc/vim.git] / black.py
1 #!/usr/bin/env python3
2
3 import asyncio
4 import pickle
5 from asyncio.base_events import BaseEventLoop
6 from concurrent.futures import Executor, ProcessPoolExecutor
7 from enum import Enum
8 from functools import partial, wraps
9 import keyword
10 import logging
11 from multiprocessing import Manager
12 import os
13 from pathlib import Path
14 import re
15 import tokenize
16 import signal
17 import sys
18 from typing import (
19     Any,
20     Callable,
21     Collection,
22     Dict,
23     Generic,
24     Iterable,
25     Iterator,
26     List,
27     Optional,
28     Pattern,
29     Set,
30     Tuple,
31     Type,
32     TypeVar,
33     Union,
34 )
35
36 from appdirs import user_cache_dir
37 from attr import dataclass, Factory
38 import click
39
40 # lib2to3 fork
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
45
46 __version__ = "18.4a2"
47 DEFAULT_LINE_LENGTH = 88
48 # types
49 syms = pygram.python_symbols
50 FileContent = str
51 Encoding = str
52 Depth = int
53 NodeType = int
54 LeafID = int
55 Priority = int
56 Index = int
57 LN = Union[Leaf, Node]
58 SplitFunc = Callable[["Line", bool], Iterator["Line"]]
59 Timestamp = float
60 FileSize = int
61 CacheInfo = Tuple[Timestamp, FileSize]
62 Cache = Dict[Path, CacheInfo]
63 out = partial(click.secho, bold=True, err=True)
64 err = partial(click.secho, fg="red", err=True)
65
66
67 class NothingChanged(UserWarning):
68     """Raised by :func:`format_file` when reformatted code is the same as source."""
69
70
71 class CannotSplit(Exception):
72     """A readable split that fits the allotted line length is impossible.
73
74     Raised by :func:`left_hand_split`, :func:`right_hand_split`, and
75     :func:`delimiter_split`.
76     """
77
78
79 class FormatError(Exception):
80     """Base exception for `# fmt: on` and `# fmt: off` handling.
81
82     It holds the number of bytes of the prefix consumed before the format
83     control comment appeared.
84     """
85
86     def __init__(self, consumed: int) -> None:
87         super().__init__(consumed)
88         self.consumed = consumed
89
90     def trim_prefix(self, leaf: Leaf) -> None:
91         leaf.prefix = leaf.prefix[self.consumed:]
92
93     def leaf_from_consumed(self, leaf: Leaf) -> Leaf:
94         """Returns a new Leaf from the consumed part of the prefix."""
95         unformatted_prefix = leaf.prefix[:self.consumed]
96         return Leaf(token.NEWLINE, unformatted_prefix)
97
98
99 class FormatOn(FormatError):
100     """Found a comment like `# fmt: on` in the file."""
101
102
103 class FormatOff(FormatError):
104     """Found a comment like `# fmt: off` in the file."""
105
106
107 class WriteBack(Enum):
108     NO = 0
109     YES = 1
110     DIFF = 2
111
112
113 class Changed(Enum):
114     NO = 0
115     CACHED = 1
116     YES = 2
117
118
119 @click.command()
120 @click.option(
121     "-l",
122     "--line-length",
123     type=int,
124     default=DEFAULT_LINE_LENGTH,
125     help="How many character per line to allow.",
126     show_default=True,
127 )
128 @click.option(
129     "--check",
130     is_flag=True,
131     help=(
132         "Don't write the files back, just return the status.  Return code 0 "
133         "means nothing would change.  Return code 1 means some files would be "
134         "reformatted.  Return code 123 means there was an internal error."
135     ),
136 )
137 @click.option(
138     "--diff",
139     is_flag=True,
140     help="Don't write the files back, just output a diff for each file on stdout.",
141 )
142 @click.option(
143     "--fast/--safe",
144     is_flag=True,
145     help="If --fast given, skip temporary sanity checks. [default: --safe]",
146 )
147 @click.option(
148     "-q",
149     "--quiet",
150     is_flag=True,
151     help=(
152         "Don't emit non-error messages to stderr. Errors are still emitted, "
153         "silence those with 2>/dev/null."
154     ),
155 )
156 @click.version_option(version=__version__)
157 @click.argument(
158     "src",
159     nargs=-1,
160     type=click.Path(
161         exists=True, file_okay=True, dir_okay=True, readable=True, allow_dash=True
162     ),
163 )
164 @click.pass_context
165 def main(
166     ctx: click.Context,
167     line_length: int,
168     check: bool,
169     diff: bool,
170     fast: bool,
171     quiet: bool,
172     src: List[str],
173 ) -> None:
174     """The uncompromising code formatter."""
175     sources: List[Path] = []
176     for s in src:
177         p = Path(s)
178         if p.is_dir():
179             sources.extend(gen_python_files_in_dir(p))
180         elif p.is_file():
181             # if a file was explicitly given, we don't care about its extension
182             sources.append(p)
183         elif s == "-":
184             sources.append(Path("-"))
185         else:
186             err(f"invalid path: {s}")
187
188     if check and not diff:
189         write_back = WriteBack.NO
190     elif diff:
191         write_back = WriteBack.DIFF
192     else:
193         write_back = WriteBack.YES
194     report = Report(check=check, quiet=quiet)
195     if len(sources) == 0:
196         ctx.exit(0)
197         return
198
199     elif len(sources) == 1:
200         reformat_one(sources[0], line_length, fast, write_back, report)
201     else:
202         loop = asyncio.get_event_loop()
203         executor = ProcessPoolExecutor(max_workers=os.cpu_count())
204         try:
205             loop.run_until_complete(
206                 schedule_formatting(
207                     sources, line_length, fast, write_back, report, loop, executor
208                 )
209             )
210         finally:
211             shutdown(loop)
212         if not quiet:
213             out("All done! ✨ 🍰 ✨")
214             click.echo(str(report))
215     ctx.exit(report.return_code)
216
217
218 def reformat_one(
219     src: Path, line_length: int, fast: bool, write_back: WriteBack, report: "Report"
220 ) -> None:
221     """Reformat a single file under `src` without spawning child processes.
222
223     If `quiet` is True, non-error messages are not output. `line_length`,
224     `write_back`, and `fast` options are passed to :func:`format_file_in_place`.
225     """
226     try:
227         changed = Changed.NO
228         if not src.is_file() and str(src) == "-":
229             if format_stdin_to_stdout(
230                 line_length=line_length, fast=fast, write_back=write_back
231             ):
232                 changed = Changed.YES
233         else:
234             cache: Cache = {}
235             if write_back != WriteBack.DIFF:
236                 cache = read_cache()
237                 src = src.resolve()
238                 if src in cache and cache[src] == get_cache_info(src):
239                     changed = Changed.CACHED
240             if (
241                 changed is not Changed.CACHED
242                 and format_file_in_place(
243                     src, line_length=line_length, fast=fast, write_back=write_back
244                 )
245             ):
246                 changed = Changed.YES
247             if write_back != WriteBack.DIFF and changed is not Changed.NO:
248                 write_cache(cache, [src])
249         report.done(src, changed)
250     except Exception as exc:
251         report.failed(src, str(exc))
252
253
254 async def schedule_formatting(
255     sources: List[Path],
256     line_length: int,
257     fast: bool,
258     write_back: WriteBack,
259     report: "Report",
260     loop: BaseEventLoop,
261     executor: Executor,
262 ) -> None:
263     """Run formatting of `sources` in parallel using the provided `executor`.
264
265     (Use ProcessPoolExecutors for actual parallelism.)
266
267     `line_length`, `write_back`, and `fast` options are passed to
268     :func:`format_file_in_place`.
269     """
270     cache: Cache = {}
271     if write_back != WriteBack.DIFF:
272         cache = read_cache()
273         sources, cached = filter_cached(cache, sources)
274         for src in cached:
275             report.done(src, Changed.CACHED)
276     cancelled = []
277     formatted = []
278     if sources:
279         lock = None
280         if write_back == WriteBack.DIFF:
281             # For diff output, we need locks to ensure we don't interleave output
282             # from different processes.
283             manager = Manager()
284             lock = manager.Lock()
285         tasks = {
286             src: loop.run_in_executor(
287                 executor, format_file_in_place, src, line_length, fast, write_back, lock
288             )
289             for src in sources
290         }
291         _task_values = list(tasks.values())
292         try:
293             loop.add_signal_handler(signal.SIGINT, cancel, _task_values)
294             loop.add_signal_handler(signal.SIGTERM, cancel, _task_values)
295         except NotImplementedError:
296             # There are no good alternatives for these on Windows
297             pass
298         await asyncio.wait(_task_values)
299         for src, task in tasks.items():
300             if not task.done():
301                 report.failed(src, "timed out, cancelling")
302                 task.cancel()
303                 cancelled.append(task)
304             elif task.cancelled():
305                 cancelled.append(task)
306             elif task.exception():
307                 report.failed(src, str(task.exception()))
308             else:
309                 formatted.append(src)
310                 report.done(src, Changed.YES if task.result() else Changed.NO)
311
312     if cancelled:
313         await asyncio.gather(*cancelled, loop=loop, return_exceptions=True)
314     if write_back != WriteBack.DIFF and formatted:
315         write_cache(cache, formatted)
316
317
318 def format_file_in_place(
319     src: Path,
320     line_length: int,
321     fast: bool,
322     write_back: WriteBack = WriteBack.NO,
323     lock: Any = None,  # multiprocessing.Manager().Lock() is some crazy proxy
324 ) -> bool:
325     """Format file under `src` path. Return True if changed.
326
327     If `write_back` is True, write reformatted code back to stdout.
328     `line_length` and `fast` options are passed to :func:`format_file_contents`.
329     """
330
331     with tokenize.open(src) as src_buffer:
332         src_contents = src_buffer.read()
333     try:
334         dst_contents = format_file_contents(
335             src_contents, line_length=line_length, fast=fast
336         )
337     except NothingChanged:
338         return False
339
340     if write_back == write_back.YES:
341         with open(src, "w", encoding=src_buffer.encoding) as f:
342             f.write(dst_contents)
343     elif write_back == write_back.DIFF:
344         src_name = f"{src}  (original)"
345         dst_name = f"{src}  (formatted)"
346         diff_contents = diff(src_contents, dst_contents, src_name, dst_name)
347         if lock:
348             lock.acquire()
349         try:
350             sys.stdout.write(diff_contents)
351         finally:
352             if lock:
353                 lock.release()
354     return True
355
356
357 def format_stdin_to_stdout(
358     line_length: int, fast: bool, write_back: WriteBack = WriteBack.NO
359 ) -> bool:
360     """Format file on stdin. Return True if changed.
361
362     If `write_back` is True, write reformatted code back to stdout.
363     `line_length` and `fast` arguments are passed to :func:`format_file_contents`.
364     """
365     src = sys.stdin.read()
366     dst = src
367     try:
368         dst = format_file_contents(src, line_length=line_length, fast=fast)
369         return True
370
371     except NothingChanged:
372         return False
373
374     finally:
375         if write_back == WriteBack.YES:
376             sys.stdout.write(dst)
377         elif write_back == WriteBack.DIFF:
378             src_name = "<stdin>  (original)"
379             dst_name = "<stdin>  (formatted)"
380             sys.stdout.write(diff(src, dst, src_name, dst_name))
381
382
383 def format_file_contents(
384     src_contents: str, line_length: int, fast: bool
385 ) -> FileContent:
386     """Reformat contents a file and return new contents.
387
388     If `fast` is False, additionally confirm that the reformatted code is
389     valid by calling :func:`assert_equivalent` and :func:`assert_stable` on it.
390     `line_length` is passed to :func:`format_str`.
391     """
392     if src_contents.strip() == "":
393         raise NothingChanged
394
395     dst_contents = format_str(src_contents, line_length=line_length)
396     if src_contents == dst_contents:
397         raise NothingChanged
398
399     if not fast:
400         assert_equivalent(src_contents, dst_contents)
401         assert_stable(src_contents, dst_contents, line_length=line_length)
402     return dst_contents
403
404
405 def format_str(src_contents: str, line_length: int) -> FileContent:
406     """Reformat a string and return new contents.
407
408     `line_length` determines how many characters per line are allowed.
409     """
410     src_node = lib2to3_parse(src_contents)
411     dst_contents = ""
412     lines = LineGenerator()
413     elt = EmptyLineTracker()
414     py36 = is_python36(src_node)
415     empty_line = Line()
416     after = 0
417     for current_line in lines.visit(src_node):
418         for _ in range(after):
419             dst_contents += str(empty_line)
420         before, after = elt.maybe_empty_lines(current_line)
421         for _ in range(before):
422             dst_contents += str(empty_line)
423         for line in split_line(current_line, line_length=line_length, py36=py36):
424             dst_contents += str(line)
425     return dst_contents
426
427
428 GRAMMARS = [
429     pygram.python_grammar_no_print_statement_no_exec_statement,
430     pygram.python_grammar_no_print_statement,
431     pygram.python_grammar,
432 ]
433
434
435 def lib2to3_parse(src_txt: str) -> Node:
436     """Given a string with source, return the lib2to3 Node."""
437     grammar = pygram.python_grammar_no_print_statement
438     if src_txt[-1] != "\n":
439         nl = "\r\n" if "\r\n" in src_txt[:1024] else "\n"
440         src_txt += nl
441     for grammar in GRAMMARS:
442         drv = driver.Driver(grammar, pytree.convert)
443         try:
444             result = drv.parse_string(src_txt, True)
445             break
446
447         except ParseError as pe:
448             lineno, column = pe.context[1]
449             lines = src_txt.splitlines()
450             try:
451                 faulty_line = lines[lineno - 1]
452             except IndexError:
453                 faulty_line = "<line number missing in source>"
454             exc = ValueError(f"Cannot parse: {lineno}:{column}: {faulty_line}")
455     else:
456         raise exc from None
457
458     if isinstance(result, Leaf):
459         result = Node(syms.file_input, [result])
460     return result
461
462
463 def lib2to3_unparse(node: Node) -> str:
464     """Given a lib2to3 node, return its string representation."""
465     code = str(node)
466     return code
467
468
469 T = TypeVar("T")
470
471
472 class Visitor(Generic[T]):
473     """Basic lib2to3 visitor that yields things of type `T` on `visit()`."""
474
475     def visit(self, node: LN) -> Iterator[T]:
476         """Main method to visit `node` and its children.
477
478         It tries to find a `visit_*()` method for the given `node.type`, like
479         `visit_simple_stmt` for Node objects or `visit_INDENT` for Leaf objects.
480         If no dedicated `visit_*()` method is found, chooses `visit_default()`
481         instead.
482
483         Then yields objects of type `T` from the selected visitor.
484         """
485         if node.type < 256:
486             name = token.tok_name[node.type]
487         else:
488             name = type_repr(node.type)
489         yield from getattr(self, f"visit_{name}", self.visit_default)(node)
490
491     def visit_default(self, node: LN) -> Iterator[T]:
492         """Default `visit_*()` implementation. Recurses to children of `node`."""
493         if isinstance(node, Node):
494             for child in node.children:
495                 yield from self.visit(child)
496
497
498 @dataclass
499 class DebugVisitor(Visitor[T]):
500     tree_depth: int = 0
501
502     def visit_default(self, node: LN) -> Iterator[T]:
503         indent = " " * (2 * self.tree_depth)
504         if isinstance(node, Node):
505             _type = type_repr(node.type)
506             out(f"{indent}{_type}", fg="yellow")
507             self.tree_depth += 1
508             for child in node.children:
509                 yield from self.visit(child)
510
511             self.tree_depth -= 1
512             out(f"{indent}/{_type}", fg="yellow", bold=False)
513         else:
514             _type = token.tok_name.get(node.type, str(node.type))
515             out(f"{indent}{_type}", fg="blue", nl=False)
516             if node.prefix:
517                 # We don't have to handle prefixes for `Node` objects since
518                 # that delegates to the first child anyway.
519                 out(f" {node.prefix!r}", fg="green", bold=False, nl=False)
520             out(f" {node.value!r}", fg="blue", bold=False)
521
522     @classmethod
523     def show(cls, code: str) -> None:
524         """Pretty-print the lib2to3 AST of a given string of `code`.
525
526         Convenience method for debugging.
527         """
528         v: DebugVisitor[None] = DebugVisitor()
529         list(v.visit(lib2to3_parse(code)))
530
531
532 KEYWORDS = set(keyword.kwlist)
533 WHITESPACE = {token.DEDENT, token.INDENT, token.NEWLINE}
534 FLOW_CONTROL = {"return", "raise", "break", "continue"}
535 STATEMENT = {
536     syms.if_stmt,
537     syms.while_stmt,
538     syms.for_stmt,
539     syms.try_stmt,
540     syms.except_clause,
541     syms.with_stmt,
542     syms.funcdef,
543     syms.classdef,
544 }
545 STANDALONE_COMMENT = 153
546 LOGIC_OPERATORS = {"and", "or"}
547 COMPARATORS = {
548     token.LESS,
549     token.GREATER,
550     token.EQEQUAL,
551     token.NOTEQUAL,
552     token.LESSEQUAL,
553     token.GREATEREQUAL,
554 }
555 MATH_OPERATORS = {
556     token.PLUS,
557     token.MINUS,
558     token.STAR,
559     token.SLASH,
560     token.VBAR,
561     token.AMPER,
562     token.PERCENT,
563     token.CIRCUMFLEX,
564     token.TILDE,
565     token.LEFTSHIFT,
566     token.RIGHTSHIFT,
567     token.DOUBLESTAR,
568     token.DOUBLESLASH,
569 }
570 STARS = {token.STAR, token.DOUBLESTAR}
571 VARARGS_PARENTS = {
572     syms.arglist,
573     syms.argument,  # double star in arglist
574     syms.trailer,  # single argument to call
575     syms.typedargslist,
576     syms.varargslist,  # lambdas
577 }
578 UNPACKING_PARENTS = {
579     syms.atom,  # single element of a list or set literal
580     syms.dictsetmaker,
581     syms.listmaker,
582     syms.testlist_gexp,
583 }
584 COMPREHENSION_PRIORITY = 20
585 COMMA_PRIORITY = 10
586 LOGIC_PRIORITY = 5
587 STRING_PRIORITY = 4
588 COMPARATOR_PRIORITY = 3
589 MATH_PRIORITY = 1
590
591
592 @dataclass
593 class BracketTracker:
594     """Keeps track of brackets on a line."""
595
596     depth: int = 0
597     bracket_match: Dict[Tuple[Depth, NodeType], Leaf] = Factory(dict)
598     delimiters: Dict[LeafID, Priority] = Factory(dict)
599     previous: Optional[Leaf] = None
600     _for_loop_variable: bool = False
601     _lambda_arguments: bool = False
602
603     def mark(self, leaf: Leaf) -> None:
604         """Mark `leaf` with bracket-related metadata. Keep track of delimiters.
605
606         All leaves receive an int `bracket_depth` field that stores how deep
607         within brackets a given leaf is. 0 means there are no enclosing brackets
608         that started on this line.
609
610         If a leaf is itself a closing bracket, it receives an `opening_bracket`
611         field that it forms a pair with. This is a one-directional link to
612         avoid reference cycles.
613
614         If a leaf is a delimiter (a token on which Black can split the line if
615         needed) and it's on depth 0, its `id()` is stored in the tracker's
616         `delimiters` field.
617         """
618         if leaf.type == token.COMMENT:
619             return
620
621         self.maybe_decrement_after_for_loop_variable(leaf)
622         self.maybe_decrement_after_lambda_arguments(leaf)
623         if leaf.type in CLOSING_BRACKETS:
624             self.depth -= 1
625             opening_bracket = self.bracket_match.pop((self.depth, leaf.type))
626             leaf.opening_bracket = opening_bracket
627         leaf.bracket_depth = self.depth
628         if self.depth == 0:
629             delim = is_split_before_delimiter(leaf, self.previous)
630             if delim and self.previous is not None:
631                 self.delimiters[id(self.previous)] = delim
632             else:
633                 delim = is_split_after_delimiter(leaf, self.previous)
634                 if delim:
635                     self.delimiters[id(leaf)] = delim
636         if leaf.type in OPENING_BRACKETS:
637             self.bracket_match[self.depth, BRACKET[leaf.type]] = leaf
638             self.depth += 1
639         self.previous = leaf
640         self.maybe_increment_lambda_arguments(leaf)
641         self.maybe_increment_for_loop_variable(leaf)
642
643     def any_open_brackets(self) -> bool:
644         """Return True if there is an yet unmatched open bracket on the line."""
645         return bool(self.bracket_match)
646
647     def max_delimiter_priority(self, exclude: Iterable[LeafID] = ()) -> int:
648         """Return the highest priority of a delimiter found on the line.
649
650         Values are consistent with what `is_split_*_delimiter()` return.
651         Raises ValueError on no delimiters.
652         """
653         return max(v for k, v in self.delimiters.items() if k not in exclude)
654
655     def maybe_increment_for_loop_variable(self, leaf: Leaf) -> bool:
656         """In a for loop, or comprehension, the variables are often unpacks.
657
658         To avoid splitting on the comma in this situation, increase the depth of
659         tokens between `for` and `in`.
660         """
661         if leaf.type == token.NAME and leaf.value == "for":
662             self.depth += 1
663             self._for_loop_variable = True
664             return True
665
666         return False
667
668     def maybe_decrement_after_for_loop_variable(self, leaf: Leaf) -> bool:
669         """See `maybe_increment_for_loop_variable` above for explanation."""
670         if self._for_loop_variable and leaf.type == token.NAME and leaf.value == "in":
671             self.depth -= 1
672             self._for_loop_variable = False
673             return True
674
675         return False
676
677     def maybe_increment_lambda_arguments(self, leaf: Leaf) -> bool:
678         """In a lambda expression, there might be more than one argument.
679
680         To avoid splitting on the comma in this situation, increase the depth of
681         tokens between `lambda` and `:`.
682         """
683         if leaf.type == token.NAME and leaf.value == "lambda":
684             self.depth += 1
685             self._lambda_arguments = True
686             return True
687
688         return False
689
690     def maybe_decrement_after_lambda_arguments(self, leaf: Leaf) -> bool:
691         """See `maybe_increment_lambda_arguments` above for explanation."""
692         if self._lambda_arguments and leaf.type == token.COLON:
693             self.depth -= 1
694             self._lambda_arguments = False
695             return True
696
697         return False
698
699
700 @dataclass
701 class Line:
702     """Holds leaves and comments. Can be printed with `str(line)`."""
703
704     depth: int = 0
705     leaves: List[Leaf] = Factory(list)
706     comments: List[Tuple[Index, Leaf]] = Factory(list)
707     bracket_tracker: BracketTracker = Factory(BracketTracker)
708     inside_brackets: bool = False
709
710     def append(self, leaf: Leaf, preformatted: bool = False) -> None:
711         """Add a new `leaf` to the end of the line.
712
713         Unless `preformatted` is True, the `leaf` will receive a new consistent
714         whitespace prefix and metadata applied by :class:`BracketTracker`.
715         Trailing commas are maybe removed, unpacked for loop variables are
716         demoted from being delimiters.
717
718         Inline comments are put aside.
719         """
720         has_value = leaf.type in BRACKETS or bool(leaf.value.strip())
721         if not has_value:
722             return
723
724         if self.leaves and not preformatted:
725             # Note: at this point leaf.prefix should be empty except for
726             # imports, for which we only preserve newlines.
727             leaf.prefix += whitespace(leaf)
728         if self.inside_brackets or not preformatted:
729             self.bracket_tracker.mark(leaf)
730             self.maybe_remove_trailing_comma(leaf)
731
732         if not self.append_comment(leaf):
733             self.leaves.append(leaf)
734
735     def append_safe(self, leaf: Leaf, preformatted: bool = False) -> None:
736         """Like :func:`append()` but disallow invalid standalone comment structure.
737
738         Raises ValueError when any `leaf` is appended after a standalone comment
739         or when a standalone comment is not the first leaf on the line.
740         """
741         if self.bracket_tracker.depth == 0:
742             if self.is_comment:
743                 raise ValueError("cannot append to standalone comments")
744
745             if self.leaves and leaf.type == STANDALONE_COMMENT:
746                 raise ValueError(
747                     "cannot append standalone comments to a populated line"
748                 )
749
750         self.append(leaf, preformatted=preformatted)
751
752     @property
753     def is_comment(self) -> bool:
754         """Is this line a standalone comment?"""
755         return len(self.leaves) == 1 and self.leaves[0].type == STANDALONE_COMMENT
756
757     @property
758     def is_decorator(self) -> bool:
759         """Is this line a decorator?"""
760         return bool(self) and self.leaves[0].type == token.AT
761
762     @property
763     def is_import(self) -> bool:
764         """Is this an import line?"""
765         return bool(self) and is_import(self.leaves[0])
766
767     @property
768     def is_class(self) -> bool:
769         """Is this line a class definition?"""
770         return (
771             bool(self)
772             and self.leaves[0].type == token.NAME
773             and self.leaves[0].value == "class"
774         )
775
776     @property
777     def is_def(self) -> bool:
778         """Is this a function definition? (Also returns True for async defs.)"""
779         try:
780             first_leaf = self.leaves[0]
781         except IndexError:
782             return False
783
784         try:
785             second_leaf: Optional[Leaf] = self.leaves[1]
786         except IndexError:
787             second_leaf = None
788         return (
789             (first_leaf.type == token.NAME and first_leaf.value == "def")
790             or (
791                 first_leaf.type == token.ASYNC
792                 and second_leaf is not None
793                 and second_leaf.type == token.NAME
794                 and second_leaf.value == "def"
795             )
796         )
797
798     @property
799     def is_flow_control(self) -> bool:
800         """Is this line a flow control statement?
801
802         Those are `return`, `raise`, `break`, and `continue`.
803         """
804         return (
805             bool(self)
806             and self.leaves[0].type == token.NAME
807             and self.leaves[0].value in FLOW_CONTROL
808         )
809
810     @property
811     def is_yield(self) -> bool:
812         """Is this line a yield statement?"""
813         return (
814             bool(self)
815             and self.leaves[0].type == token.NAME
816             and self.leaves[0].value == "yield"
817         )
818
819     def contains_standalone_comments(self, depth_limit: int = sys.maxsize) -> bool:
820         """If so, needs to be split before emitting."""
821         for leaf in self.leaves:
822             if leaf.type == STANDALONE_COMMENT:
823                 if leaf.bracket_depth <= depth_limit:
824                     return True
825
826         return False
827
828     def maybe_remove_trailing_comma(self, closing: Leaf) -> bool:
829         """Remove trailing comma if there is one and it's safe."""
830         if not (
831             self.leaves
832             and self.leaves[-1].type == token.COMMA
833             and closing.type in CLOSING_BRACKETS
834         ):
835             return False
836
837         if closing.type == token.RBRACE:
838             self.remove_trailing_comma()
839             return True
840
841         if closing.type == token.RSQB:
842             comma = self.leaves[-1]
843             if comma.parent and comma.parent.type == syms.listmaker:
844                 self.remove_trailing_comma()
845                 return True
846
847         # For parens let's check if it's safe to remove the comma.  If the
848         # trailing one is the only one, we might mistakenly change a tuple
849         # into a different type by removing the comma.
850         depth = closing.bracket_depth + 1
851         commas = 0
852         opening = closing.opening_bracket
853         for _opening_index, leaf in enumerate(self.leaves):
854             if leaf is opening:
855                 break
856
857         else:
858             return False
859
860         for leaf in self.leaves[_opening_index + 1:]:
861             if leaf is closing:
862                 break
863
864             bracket_depth = leaf.bracket_depth
865             if bracket_depth == depth and leaf.type == token.COMMA:
866                 commas += 1
867                 if leaf.parent and leaf.parent.type == syms.arglist:
868                     commas += 1
869                     break
870
871         if commas > 1:
872             self.remove_trailing_comma()
873             return True
874
875         return False
876
877     def append_comment(self, comment: Leaf) -> bool:
878         """Add an inline or standalone comment to the line."""
879         if (
880             comment.type == STANDALONE_COMMENT
881             and self.bracket_tracker.any_open_brackets()
882         ):
883             comment.prefix = ""
884             return False
885
886         if comment.type != token.COMMENT:
887             return False
888
889         after = len(self.leaves) - 1
890         if after == -1:
891             comment.type = STANDALONE_COMMENT
892             comment.prefix = ""
893             return False
894
895         else:
896             self.comments.append((after, comment))
897             return True
898
899     def comments_after(self, leaf: Leaf) -> Iterator[Leaf]:
900         """Generate comments that should appear directly after `leaf`."""
901         for _leaf_index, _leaf in enumerate(self.leaves):
902             if leaf is _leaf:
903                 break
904
905         else:
906             return
907
908         for index, comment_after in self.comments:
909             if _leaf_index == index:
910                 yield comment_after
911
912     def remove_trailing_comma(self) -> None:
913         """Remove the trailing comma and moves the comments attached to it."""
914         comma_index = len(self.leaves) - 1
915         for i in range(len(self.comments)):
916             comment_index, comment = self.comments[i]
917             if comment_index == comma_index:
918                 self.comments[i] = (comma_index - 1, comment)
919         self.leaves.pop()
920
921     def __str__(self) -> str:
922         """Render the line."""
923         if not self:
924             return "\n"
925
926         indent = "    " * self.depth
927         leaves = iter(self.leaves)
928         first = next(leaves)
929         res = f"{first.prefix}{indent}{first.value}"
930         for leaf in leaves:
931             res += str(leaf)
932         for _, comment in self.comments:
933             res += str(comment)
934         return res + "\n"
935
936     def __bool__(self) -> bool:
937         """Return True if the line has leaves or comments."""
938         return bool(self.leaves or self.comments)
939
940
941 class UnformattedLines(Line):
942     """Just like :class:`Line` but stores lines which aren't reformatted."""
943
944     def append(self, leaf: Leaf, preformatted: bool = True) -> None:
945         """Just add a new `leaf` to the end of the lines.
946
947         The `preformatted` argument is ignored.
948
949         Keeps track of indentation `depth`, which is useful when the user
950         says `# fmt: on`. Otherwise, doesn't do anything with the `leaf`.
951         """
952         try:
953             list(generate_comments(leaf))
954         except FormatOn as f_on:
955             self.leaves.append(f_on.leaf_from_consumed(leaf))
956             raise
957
958         self.leaves.append(leaf)
959         if leaf.type == token.INDENT:
960             self.depth += 1
961         elif leaf.type == token.DEDENT:
962             self.depth -= 1
963
964     def __str__(self) -> str:
965         """Render unformatted lines from leaves which were added with `append()`.
966
967         `depth` is not used for indentation in this case.
968         """
969         if not self:
970             return "\n"
971
972         res = ""
973         for leaf in self.leaves:
974             res += str(leaf)
975         return res
976
977     def append_comment(self, comment: Leaf) -> bool:
978         """Not implemented in this class. Raises `NotImplementedError`."""
979         raise NotImplementedError("Unformatted lines don't store comments separately.")
980
981     def maybe_remove_trailing_comma(self, closing: Leaf) -> bool:
982         """Does nothing and returns False."""
983         return False
984
985     def maybe_increment_for_loop_variable(self, leaf: Leaf) -> bool:
986         """Does nothing and returns False."""
987         return False
988
989
990 @dataclass
991 class EmptyLineTracker:
992     """Provides a stateful method that returns the number of potential extra
993     empty lines needed before and after the currently processed line.
994
995     Note: this tracker works on lines that haven't been split yet.  It assumes
996     the prefix of the first leaf consists of optional newlines.  Those newlines
997     are consumed by `maybe_empty_lines()` and included in the computation.
998     """
999     previous_line: Optional[Line] = None
1000     previous_after: int = 0
1001     previous_defs: List[int] = Factory(list)
1002
1003     def maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
1004         """Return the number of extra empty lines before and after the `current_line`.
1005
1006         This is for separating `def`, `async def` and `class` with extra empty
1007         lines (two on module-level), as well as providing an extra empty line
1008         after flow control keywords to make them more prominent.
1009         """
1010         if isinstance(current_line, UnformattedLines):
1011             return 0, 0
1012
1013         before, after = self._maybe_empty_lines(current_line)
1014         before -= self.previous_after
1015         self.previous_after = after
1016         self.previous_line = current_line
1017         return before, after
1018
1019     def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
1020         max_allowed = 1
1021         if current_line.depth == 0:
1022             max_allowed = 2
1023         if current_line.leaves:
1024             # Consume the first leaf's extra newlines.
1025             first_leaf = current_line.leaves[0]
1026             before = first_leaf.prefix.count("\n")
1027             before = min(before, max_allowed)
1028             first_leaf.prefix = ""
1029         else:
1030             before = 0
1031         depth = current_line.depth
1032         while self.previous_defs and self.previous_defs[-1] >= depth:
1033             self.previous_defs.pop()
1034             before = 1 if depth else 2
1035         is_decorator = current_line.is_decorator
1036         if is_decorator or current_line.is_def or current_line.is_class:
1037             if not is_decorator:
1038                 self.previous_defs.append(depth)
1039             if self.previous_line is None:
1040                 # Don't insert empty lines before the first line in the file.
1041                 return 0, 0
1042
1043             if self.previous_line and self.previous_line.is_decorator:
1044                 # Don't insert empty lines between decorators.
1045                 return 0, 0
1046
1047             newlines = 2
1048             if current_line.depth:
1049                 newlines -= 1
1050             return newlines, 0
1051
1052         if current_line.is_flow_control:
1053             return before, 1
1054
1055         if (
1056             self.previous_line
1057             and self.previous_line.is_import
1058             and not current_line.is_import
1059             and depth == self.previous_line.depth
1060         ):
1061             return (before or 1), 0
1062
1063         if (
1064             self.previous_line
1065             and self.previous_line.is_yield
1066             and (not current_line.is_yield or depth != self.previous_line.depth)
1067         ):
1068             return (before or 1), 0
1069
1070         return before, 0
1071
1072
1073 @dataclass
1074 class LineGenerator(Visitor[Line]):
1075     """Generates reformatted Line objects.  Empty lines are not emitted.
1076
1077     Note: destroys the tree it's visiting by mutating prefixes of its leaves
1078     in ways that will no longer stringify to valid Python code on the tree.
1079     """
1080     current_line: Line = Factory(Line)
1081
1082     def line(self, indent: int = 0, type: Type[Line] = Line) -> Iterator[Line]:
1083         """Generate a line.
1084
1085         If the line is empty, only emit if it makes sense.
1086         If the line is too long, split it first and then generate.
1087
1088         If any lines were generated, set up a new current_line.
1089         """
1090         if not self.current_line:
1091             if self.current_line.__class__ == type:
1092                 self.current_line.depth += indent
1093             else:
1094                 self.current_line = type(depth=self.current_line.depth + indent)
1095             return  # Line is empty, don't emit. Creating a new one unnecessary.
1096
1097         complete_line = self.current_line
1098         self.current_line = type(depth=complete_line.depth + indent)
1099         yield complete_line
1100
1101     def visit(self, node: LN) -> Iterator[Line]:
1102         """Main method to visit `node` and its children.
1103
1104         Yields :class:`Line` objects.
1105         """
1106         if isinstance(self.current_line, UnformattedLines):
1107             # File contained `# fmt: off`
1108             yield from self.visit_unformatted(node)
1109
1110         else:
1111             yield from super().visit(node)
1112
1113     def visit_default(self, node: LN) -> Iterator[Line]:
1114         """Default `visit_*()` implementation. Recurses to children of `node`."""
1115         if isinstance(node, Leaf):
1116             any_open_brackets = self.current_line.bracket_tracker.any_open_brackets()
1117             try:
1118                 for comment in generate_comments(node):
1119                     if any_open_brackets:
1120                         # any comment within brackets is subject to splitting
1121                         self.current_line.append(comment)
1122                     elif comment.type == token.COMMENT:
1123                         # regular trailing comment
1124                         self.current_line.append(comment)
1125                         yield from self.line()
1126
1127                     else:
1128                         # regular standalone comment
1129                         yield from self.line()
1130
1131                         self.current_line.append(comment)
1132                         yield from self.line()
1133
1134             except FormatOff as f_off:
1135                 f_off.trim_prefix(node)
1136                 yield from self.line(type=UnformattedLines)
1137                 yield from self.visit(node)
1138
1139             except FormatOn as f_on:
1140                 # This only happens here if somebody says "fmt: on" multiple
1141                 # times in a row.
1142                 f_on.trim_prefix(node)
1143                 yield from self.visit_default(node)
1144
1145             else:
1146                 normalize_prefix(node, inside_brackets=any_open_brackets)
1147                 if node.type == token.STRING:
1148                     normalize_string_quotes(node)
1149                 if node.type not in WHITESPACE:
1150                     self.current_line.append(node)
1151         yield from super().visit_default(node)
1152
1153     def visit_INDENT(self, node: Node) -> Iterator[Line]:
1154         """Increase indentation level, maybe yield a line."""
1155         # In blib2to3 INDENT never holds comments.
1156         yield from self.line(+1)
1157         yield from self.visit_default(node)
1158
1159     def visit_DEDENT(self, node: Node) -> Iterator[Line]:
1160         """Decrease indentation level, maybe yield a line."""
1161         # DEDENT has no value. Additionally, in blib2to3 it never holds comments.
1162         yield from self.line(-1)
1163
1164     def visit_stmt(
1165         self, node: Node, keywords: Set[str], parens: Set[str]
1166     ) -> Iterator[Line]:
1167         """Visit a statement.
1168
1169         This implementation is shared for `if`, `while`, `for`, `try`, `except`,
1170         `def`, `with`, `class`, and `assert`.
1171
1172         The relevant Python language `keywords` for a given statement will be
1173         NAME leaves within it. This methods puts those on a separate line.
1174
1175         `parens` holds pairs of nodes where invisible parentheses should be put.
1176         Keys hold nodes after which opening parentheses should be put, values
1177         hold nodes before which closing parentheses should be put.
1178         """
1179         normalize_invisible_parens(node, parens_after=parens)
1180         for child in node.children:
1181             if child.type == token.NAME and child.value in keywords:  # type: ignore
1182                 yield from self.line()
1183
1184             yield from self.visit(child)
1185
1186     def visit_simple_stmt(self, node: Node) -> Iterator[Line]:
1187         """Visit a statement without nested statements."""
1188         is_suite_like = node.parent and node.parent.type in STATEMENT
1189         if is_suite_like:
1190             yield from self.line(+1)
1191             yield from self.visit_default(node)
1192             yield from self.line(-1)
1193
1194         else:
1195             yield from self.line()
1196             yield from self.visit_default(node)
1197
1198     def visit_async_stmt(self, node: Node) -> Iterator[Line]:
1199         """Visit `async def`, `async for`, `async with`."""
1200         yield from self.line()
1201
1202         children = iter(node.children)
1203         for child in children:
1204             yield from self.visit(child)
1205
1206             if child.type == token.ASYNC:
1207                 break
1208
1209         internal_stmt = next(children)
1210         for child in internal_stmt.children:
1211             yield from self.visit(child)
1212
1213     def visit_decorators(self, node: Node) -> Iterator[Line]:
1214         """Visit decorators."""
1215         for child in node.children:
1216             yield from self.line()
1217             yield from self.visit(child)
1218
1219     def visit_import_from(self, node: Node) -> Iterator[Line]:
1220         """Visit import_from and maybe put invisible parentheses.
1221
1222         This is separate from `visit_stmt` because import statements don't
1223         support arbitrary atoms and thus handling of parentheses is custom.
1224         """
1225         check_lpar = False
1226         for index, child in enumerate(node.children):
1227             if check_lpar:
1228                 if child.type == token.LPAR:
1229                     # make parentheses invisible
1230                     child.value = ""  # type: ignore
1231                     node.children[-1].value = ""  # type: ignore
1232                 else:
1233                     # insert invisible parentheses
1234                     node.insert_child(index, Leaf(token.LPAR, ""))
1235                     node.append_child(Leaf(token.RPAR, ""))
1236                 break
1237
1238             check_lpar = (
1239                 child.type == token.NAME and child.value == "import"  # type: ignore
1240             )
1241
1242         for child in node.children:
1243             yield from self.visit(child)
1244
1245     def visit_SEMI(self, leaf: Leaf) -> Iterator[Line]:
1246         """Remove a semicolon and put the other statement on a separate line."""
1247         yield from self.line()
1248
1249     def visit_ENDMARKER(self, leaf: Leaf) -> Iterator[Line]:
1250         """End of file. Process outstanding comments and end with a newline."""
1251         yield from self.visit_default(leaf)
1252         yield from self.line()
1253
1254     def visit_unformatted(self, node: LN) -> Iterator[Line]:
1255         """Used when file contained a `# fmt: off`."""
1256         if isinstance(node, Node):
1257             for child in node.children:
1258                 yield from self.visit(child)
1259
1260         else:
1261             try:
1262                 self.current_line.append(node)
1263             except FormatOn as f_on:
1264                 f_on.trim_prefix(node)
1265                 yield from self.line()
1266                 yield from self.visit(node)
1267
1268             if node.type == token.ENDMARKER:
1269                 # somebody decided not to put a final `# fmt: on`
1270                 yield from self.line()
1271
1272     def __attrs_post_init__(self) -> None:
1273         """You are in a twisty little maze of passages."""
1274         v = self.visit_stmt
1275         Ø: Set[str] = set()
1276         self.visit_assert_stmt = partial(v, keywords={"assert"}, parens={"assert", ","})
1277         self.visit_if_stmt = partial(v, keywords={"if", "else", "elif"}, parens={"if"})
1278         self.visit_while_stmt = partial(v, keywords={"while", "else"}, parens={"while"})
1279         self.visit_for_stmt = partial(v, keywords={"for", "else"}, parens={"for", "in"})
1280         self.visit_try_stmt = partial(
1281             v, keywords={"try", "except", "else", "finally"}, parens=Ø
1282         )
1283         self.visit_except_clause = partial(v, keywords={"except"}, parens=Ø)
1284         self.visit_with_stmt = partial(v, keywords={"with"}, parens=Ø)
1285         self.visit_funcdef = partial(v, keywords={"def"}, parens=Ø)
1286         self.visit_classdef = partial(v, keywords={"class"}, parens=Ø)
1287         self.visit_async_funcdef = self.visit_async_stmt
1288         self.visit_decorated = self.visit_decorators
1289
1290
1291 IMPLICIT_TUPLE = {syms.testlist, syms.testlist_star_expr, syms.exprlist}
1292 BRACKET = {token.LPAR: token.RPAR, token.LSQB: token.RSQB, token.LBRACE: token.RBRACE}
1293 OPENING_BRACKETS = set(BRACKET.keys())
1294 CLOSING_BRACKETS = set(BRACKET.values())
1295 BRACKETS = OPENING_BRACKETS | CLOSING_BRACKETS
1296 ALWAYS_NO_SPACE = CLOSING_BRACKETS | {token.COMMA, STANDALONE_COMMENT}
1297
1298
1299 def whitespace(leaf: Leaf) -> str:  # noqa C901
1300     """Return whitespace prefix if needed for the given `leaf`."""
1301     NO = ""
1302     SPACE = " "
1303     DOUBLESPACE = "  "
1304     t = leaf.type
1305     p = leaf.parent
1306     v = leaf.value
1307     if t in ALWAYS_NO_SPACE:
1308         return NO
1309
1310     if t == token.COMMENT:
1311         return DOUBLESPACE
1312
1313     assert p is not None, f"INTERNAL ERROR: hand-made leaf without parent: {leaf!r}"
1314     if t == token.COLON and p.type not in {syms.subscript, syms.subscriptlist}:
1315         return NO
1316
1317     prev = leaf.prev_sibling
1318     if not prev:
1319         prevp = preceding_leaf(p)
1320         if not prevp or prevp.type in OPENING_BRACKETS:
1321             return NO
1322
1323         if t == token.COLON:
1324             return SPACE if prevp.type == token.COMMA else NO
1325
1326         if prevp.type == token.EQUAL:
1327             if prevp.parent:
1328                 if prevp.parent.type in {
1329                     syms.arglist, syms.argument, syms.parameters, syms.varargslist
1330                 }:
1331                     return NO
1332
1333                 elif prevp.parent.type == syms.typedargslist:
1334                     # A bit hacky: if the equal sign has whitespace, it means we
1335                     # previously found it's a typed argument.  So, we're using
1336                     # that, too.
1337                     return prevp.prefix
1338
1339         elif prevp.type in STARS:
1340             if is_vararg(prevp, within=VARARGS_PARENTS | UNPACKING_PARENTS):
1341                 return NO
1342
1343         elif prevp.type == token.COLON:
1344             if prevp.parent and prevp.parent.type in {syms.subscript, syms.sliceop}:
1345                 return NO
1346
1347         elif (
1348             prevp.parent
1349             and prevp.parent.type == syms.factor
1350             and prevp.type in MATH_OPERATORS
1351         ):
1352             return NO
1353
1354         elif (
1355             prevp.type == token.RIGHTSHIFT
1356             and prevp.parent
1357             and prevp.parent.type == syms.shift_expr
1358             and prevp.prev_sibling
1359             and prevp.prev_sibling.type == token.NAME
1360             and prevp.prev_sibling.value == "print"  # type: ignore
1361         ):
1362             # Python 2 print chevron
1363             return NO
1364
1365     elif prev.type in OPENING_BRACKETS:
1366         return NO
1367
1368     if p.type in {syms.parameters, syms.arglist}:
1369         # untyped function signatures or calls
1370         if not prev or prev.type != token.COMMA:
1371             return NO
1372
1373     elif p.type == syms.varargslist:
1374         # lambdas
1375         if prev and prev.type != token.COMMA:
1376             return NO
1377
1378     elif p.type == syms.typedargslist:
1379         # typed function signatures
1380         if not prev:
1381             return NO
1382
1383         if t == token.EQUAL:
1384             if prev.type != syms.tname:
1385                 return NO
1386
1387         elif prev.type == token.EQUAL:
1388             # A bit hacky: if the equal sign has whitespace, it means we
1389             # previously found it's a typed argument.  So, we're using that, too.
1390             return prev.prefix
1391
1392         elif prev.type != token.COMMA:
1393             return NO
1394
1395     elif p.type == syms.tname:
1396         # type names
1397         if not prev:
1398             prevp = preceding_leaf(p)
1399             if not prevp or prevp.type != token.COMMA:
1400                 return NO
1401
1402     elif p.type == syms.trailer:
1403         # attributes and calls
1404         if t == token.LPAR or t == token.RPAR:
1405             return NO
1406
1407         if not prev:
1408             if t == token.DOT:
1409                 prevp = preceding_leaf(p)
1410                 if not prevp or prevp.type != token.NUMBER:
1411                     return NO
1412
1413             elif t == token.LSQB:
1414                 return NO
1415
1416         elif prev.type != token.COMMA:
1417             return NO
1418
1419     elif p.type == syms.argument:
1420         # single argument
1421         if t == token.EQUAL:
1422             return NO
1423
1424         if not prev:
1425             prevp = preceding_leaf(p)
1426             if not prevp or prevp.type == token.LPAR:
1427                 return NO
1428
1429         elif prev.type in {token.EQUAL} | STARS:
1430             return NO
1431
1432     elif p.type == syms.decorator:
1433         # decorators
1434         return NO
1435
1436     elif p.type == syms.dotted_name:
1437         if prev:
1438             return NO
1439
1440         prevp = preceding_leaf(p)
1441         if not prevp or prevp.type == token.AT or prevp.type == token.DOT:
1442             return NO
1443
1444     elif p.type == syms.classdef:
1445         if t == token.LPAR:
1446             return NO
1447
1448         if prev and prev.type == token.LPAR:
1449             return NO
1450
1451     elif p.type == syms.subscript:
1452         # indexing
1453         if not prev:
1454             assert p.parent is not None, "subscripts are always parented"
1455             if p.parent.type == syms.subscriptlist:
1456                 return SPACE
1457
1458             return NO
1459
1460         else:
1461             return NO
1462
1463     elif p.type == syms.atom:
1464         if prev and t == token.DOT:
1465             # dots, but not the first one.
1466             return NO
1467
1468     elif p.type == syms.dictsetmaker:
1469         # dict unpacking
1470         if prev and prev.type == token.DOUBLESTAR:
1471             return NO
1472
1473     elif p.type in {syms.factor, syms.star_expr}:
1474         # unary ops
1475         if not prev:
1476             prevp = preceding_leaf(p)
1477             if not prevp or prevp.type in OPENING_BRACKETS:
1478                 return NO
1479
1480             prevp_parent = prevp.parent
1481             assert prevp_parent is not None
1482             if (
1483                 prevp.type == token.COLON
1484                 and prevp_parent.type in {syms.subscript, syms.sliceop}
1485             ):
1486                 return NO
1487
1488             elif prevp.type == token.EQUAL and prevp_parent.type == syms.argument:
1489                 return NO
1490
1491         elif t == token.NAME or t == token.NUMBER:
1492             return NO
1493
1494     elif p.type == syms.import_from:
1495         if t == token.DOT:
1496             if prev and prev.type == token.DOT:
1497                 return NO
1498
1499         elif t == token.NAME:
1500             if v == "import":
1501                 return SPACE
1502
1503             if prev and prev.type == token.DOT:
1504                 return NO
1505
1506     elif p.type == syms.sliceop:
1507         return NO
1508
1509     return SPACE
1510
1511
1512 def preceding_leaf(node: Optional[LN]) -> Optional[Leaf]:
1513     """Return the first leaf that precedes `node`, if any."""
1514     while node:
1515         res = node.prev_sibling
1516         if res:
1517             if isinstance(res, Leaf):
1518                 return res
1519
1520             try:
1521                 return list(res.leaves())[-1]
1522
1523             except IndexError:
1524                 return None
1525
1526         node = node.parent
1527     return None
1528
1529
1530 def is_split_after_delimiter(leaf: Leaf, previous: Leaf = None) -> int:
1531     """Return the priority of the `leaf` delimiter, given a line break after it.
1532
1533     The delimiter priorities returned here are from those delimiters that would
1534     cause a line break after themselves.
1535
1536     Higher numbers are higher priority.
1537     """
1538     if leaf.type == token.COMMA:
1539         return COMMA_PRIORITY
1540
1541     return 0
1542
1543
1544 def is_split_before_delimiter(leaf: Leaf, previous: Leaf = None) -> int:
1545     """Return the priority of the `leaf` delimiter, given a line before after it.
1546
1547     The delimiter priorities returned here are from those delimiters that would
1548     cause a line break before themselves.
1549
1550     Higher numbers are higher priority.
1551     """
1552     if is_vararg(leaf, within=VARARGS_PARENTS | UNPACKING_PARENTS):
1553         # * and ** might also be MATH_OPERATORS but in this case they are not.
1554         # Don't treat them as a delimiter.
1555         return 0
1556
1557     if (
1558         leaf.type in MATH_OPERATORS
1559         and leaf.parent
1560         and leaf.parent.type not in {syms.factor, syms.star_expr}
1561     ):
1562         return MATH_PRIORITY
1563
1564     if leaf.type in COMPARATORS:
1565         return COMPARATOR_PRIORITY
1566
1567     if (
1568         leaf.type == token.STRING
1569         and previous is not None
1570         and previous.type == token.STRING
1571     ):
1572         return STRING_PRIORITY
1573
1574     if (
1575         leaf.type == token.NAME
1576         and leaf.value == "for"
1577         and leaf.parent
1578         and leaf.parent.type in {syms.comp_for, syms.old_comp_for}
1579     ):
1580         return COMPREHENSION_PRIORITY
1581
1582     if (
1583         leaf.type == token.NAME
1584         and leaf.value == "if"
1585         and leaf.parent
1586         and leaf.parent.type in {syms.comp_if, syms.old_comp_if}
1587     ):
1588         return COMPREHENSION_PRIORITY
1589
1590     if leaf.type == token.NAME and leaf.value in LOGIC_OPERATORS and leaf.parent:
1591         return LOGIC_PRIORITY
1592
1593     return 0
1594
1595
1596 def generate_comments(leaf: Leaf) -> Iterator[Leaf]:
1597     """Clean the prefix of the `leaf` and generate comments from it, if any.
1598
1599     Comments in lib2to3 are shoved into the whitespace prefix.  This happens
1600     in `pgen2/driver.py:Driver.parse_tokens()`.  This was a brilliant implementation
1601     move because it does away with modifying the grammar to include all the
1602     possible places in which comments can be placed.
1603
1604     The sad consequence for us though is that comments don't "belong" anywhere.
1605     This is why this function generates simple parentless Leaf objects for
1606     comments.  We simply don't know what the correct parent should be.
1607
1608     No matter though, we can live without this.  We really only need to
1609     differentiate between inline and standalone comments.  The latter don't
1610     share the line with any code.
1611
1612     Inline comments are emitted as regular token.COMMENT leaves.  Standalone
1613     are emitted with a fake STANDALONE_COMMENT token identifier.
1614     """
1615     p = leaf.prefix
1616     if not p:
1617         return
1618
1619     if "#" not in p:
1620         return
1621
1622     consumed = 0
1623     nlines = 0
1624     for index, line in enumerate(p.split("\n")):
1625         consumed += len(line) + 1  # adding the length of the split '\n'
1626         line = line.lstrip()
1627         if not line:
1628             nlines += 1
1629         if not line.startswith("#"):
1630             continue
1631
1632         if index == 0 and leaf.type != token.ENDMARKER:
1633             comment_type = token.COMMENT  # simple trailing comment
1634         else:
1635             comment_type = STANDALONE_COMMENT
1636         comment = make_comment(line)
1637         yield Leaf(comment_type, comment, prefix="\n" * nlines)
1638
1639         if comment in {"# fmt: on", "# yapf: enable"}:
1640             raise FormatOn(consumed)
1641
1642         if comment in {"# fmt: off", "# yapf: disable"}:
1643             if comment_type == STANDALONE_COMMENT:
1644                 raise FormatOff(consumed)
1645
1646             prev = preceding_leaf(leaf)
1647             if not prev or prev.type in WHITESPACE:  # standalone comment in disguise
1648                 raise FormatOff(consumed)
1649
1650         nlines = 0
1651
1652
1653 def make_comment(content: str) -> str:
1654     """Return a consistently formatted comment from the given `content` string.
1655
1656     All comments (except for "##", "#!", "#:") should have a single space between
1657     the hash sign and the content.
1658
1659     If `content` didn't start with a hash sign, one is provided.
1660     """
1661     content = content.rstrip()
1662     if not content:
1663         return "#"
1664
1665     if content[0] == "#":
1666         content = content[1:]
1667     if content and content[0] not in " !:#":
1668         content = " " + content
1669     return "#" + content
1670
1671
1672 def split_line(
1673     line: Line, line_length: int, inner: bool = False, py36: bool = False
1674 ) -> Iterator[Line]:
1675     """Split a `line` into potentially many lines.
1676
1677     They should fit in the allotted `line_length` but might not be able to.
1678     `inner` signifies that there were a pair of brackets somewhere around the
1679     current `line`, possibly transitively. This means we can fallback to splitting
1680     by delimiters if the LHS/RHS don't yield any results.
1681
1682     If `py36` is True, splitting may generate syntax that is only compatible
1683     with Python 3.6 and later.
1684     """
1685     if isinstance(line, UnformattedLines) or line.is_comment:
1686         yield line
1687         return
1688
1689     line_str = str(line).strip("\n")
1690     if (
1691         len(line_str) <= line_length
1692         and "\n" not in line_str  # multiline strings
1693         and not line.contains_standalone_comments()
1694     ):
1695         yield line
1696         return
1697
1698     split_funcs: List[SplitFunc]
1699     if line.is_def:
1700         split_funcs = [left_hand_split]
1701     elif line.inside_brackets:
1702         split_funcs = [delimiter_split, standalone_comment_split, right_hand_split]
1703     else:
1704         split_funcs = [right_hand_split]
1705     for split_func in split_funcs:
1706         # We are accumulating lines in `result` because we might want to abort
1707         # mission and return the original line in the end, or attempt a different
1708         # split altogether.
1709         result: List[Line] = []
1710         try:
1711             for l in split_func(line, py36):
1712                 if str(l).strip("\n") == line_str:
1713                     raise CannotSplit("Split function returned an unchanged result")
1714
1715                 result.extend(
1716                     split_line(l, line_length=line_length, inner=True, py36=py36)
1717                 )
1718         except CannotSplit as cs:
1719             continue
1720
1721         else:
1722             yield from result
1723             break
1724
1725     else:
1726         yield line
1727
1728
1729 def left_hand_split(line: Line, py36: bool = False) -> Iterator[Line]:
1730     """Split line into many lines, starting with the first matching bracket pair.
1731
1732     Note: this usually looks weird, only use this for function definitions.
1733     Prefer RHS otherwise.
1734     """
1735     head = Line(depth=line.depth)
1736     body = Line(depth=line.depth + 1, inside_brackets=True)
1737     tail = Line(depth=line.depth)
1738     tail_leaves: List[Leaf] = []
1739     body_leaves: List[Leaf] = []
1740     head_leaves: List[Leaf] = []
1741     current_leaves = head_leaves
1742     matching_bracket = None
1743     for leaf in line.leaves:
1744         if (
1745             current_leaves is body_leaves
1746             and leaf.type in CLOSING_BRACKETS
1747             and leaf.opening_bracket is matching_bracket
1748         ):
1749             current_leaves = tail_leaves if body_leaves else head_leaves
1750         current_leaves.append(leaf)
1751         if current_leaves is head_leaves:
1752             if leaf.type in OPENING_BRACKETS:
1753                 matching_bracket = leaf
1754                 current_leaves = body_leaves
1755     # Since body is a new indent level, remove spurious leading whitespace.
1756     if body_leaves:
1757         normalize_prefix(body_leaves[0], inside_brackets=True)
1758     # Build the new lines.
1759     for result, leaves in (head, head_leaves), (body, body_leaves), (tail, tail_leaves):
1760         for leaf in leaves:
1761             result.append(leaf, preformatted=True)
1762             for comment_after in line.comments_after(leaf):
1763                 result.append(comment_after, preformatted=True)
1764     bracket_split_succeeded_or_raise(head, body, tail)
1765     for result in (head, body, tail):
1766         if result:
1767             yield result
1768
1769
1770 def right_hand_split(
1771     line: Line, py36: bool = False, omit: Collection[LeafID] = ()
1772 ) -> Iterator[Line]:
1773     """Split line into many lines, starting with the last matching bracket pair."""
1774     head = Line(depth=line.depth)
1775     body = Line(depth=line.depth + 1, inside_brackets=True)
1776     tail = Line(depth=line.depth)
1777     tail_leaves: List[Leaf] = []
1778     body_leaves: List[Leaf] = []
1779     head_leaves: List[Leaf] = []
1780     current_leaves = tail_leaves
1781     opening_bracket = None
1782     closing_bracket = None
1783     for leaf in reversed(line.leaves):
1784         if current_leaves is body_leaves:
1785             if leaf is opening_bracket:
1786                 current_leaves = head_leaves if body_leaves else tail_leaves
1787         current_leaves.append(leaf)
1788         if current_leaves is tail_leaves:
1789             if leaf.type in CLOSING_BRACKETS and id(leaf) not in omit:
1790                 opening_bracket = leaf.opening_bracket
1791                 closing_bracket = leaf
1792                 current_leaves = body_leaves
1793     tail_leaves.reverse()
1794     body_leaves.reverse()
1795     head_leaves.reverse()
1796     # Since body is a new indent level, remove spurious leading whitespace.
1797     if body_leaves:
1798         normalize_prefix(body_leaves[0], inside_brackets=True)
1799     elif not head_leaves:
1800         # No `head` and no `body` means the split failed. `tail` has all content.
1801         raise CannotSplit("No brackets found")
1802
1803     # Build the new lines.
1804     for result, leaves in (head, head_leaves), (body, body_leaves), (tail, tail_leaves):
1805         for leaf in leaves:
1806             result.append(leaf, preformatted=True)
1807             for comment_after in line.comments_after(leaf):
1808                 result.append(comment_after, preformatted=True)
1809     bracket_split_succeeded_or_raise(head, body, tail)
1810     assert opening_bracket and closing_bracket
1811     if (
1812         opening_bracket.type == token.LPAR
1813         and not opening_bracket.value
1814         and closing_bracket.type == token.RPAR
1815         and not closing_bracket.value
1816     ):
1817         # These parens were optional. If there aren't any delimiters or standalone
1818         # comments in the body, they were unnecessary and another split without
1819         # them should be attempted.
1820         if not (
1821             body.bracket_tracker.delimiters or line.contains_standalone_comments(0)
1822         ):
1823             omit = {id(closing_bracket), *omit}
1824             yield from right_hand_split(line, py36=py36, omit=omit)
1825             return
1826
1827     ensure_visible(opening_bracket)
1828     ensure_visible(closing_bracket)
1829     for result in (head, body, tail):
1830         if result:
1831             yield result
1832
1833
1834 def bracket_split_succeeded_or_raise(head: Line, body: Line, tail: Line) -> None:
1835     """Raise :exc:`CannotSplit` if the last left- or right-hand split failed.
1836
1837     Do nothing otherwise.
1838
1839     A left- or right-hand split is based on a pair of brackets. Content before
1840     (and including) the opening bracket is left on one line, content inside the
1841     brackets is put on a separate line, and finally content starting with and
1842     following the closing bracket is put on a separate line.
1843
1844     Those are called `head`, `body`, and `tail`, respectively. If the split
1845     produced the same line (all content in `head`) or ended up with an empty `body`
1846     and the `tail` is just the closing bracket, then it's considered failed.
1847     """
1848     tail_len = len(str(tail).strip())
1849     if not body:
1850         if tail_len == 0:
1851             raise CannotSplit("Splitting brackets produced the same line")
1852
1853         elif tail_len < 3:
1854             raise CannotSplit(
1855                 f"Splitting brackets on an empty body to save "
1856                 f"{tail_len} characters is not worth it"
1857             )
1858
1859
1860 def dont_increase_indentation(split_func: SplitFunc) -> SplitFunc:
1861     """Normalize prefix of the first leaf in every line returned by `split_func`.
1862
1863     This is a decorator over relevant split functions.
1864     """
1865
1866     @wraps(split_func)
1867     def split_wrapper(line: Line, py36: bool = False) -> Iterator[Line]:
1868         for l in split_func(line, py36):
1869             normalize_prefix(l.leaves[0], inside_brackets=True)
1870             yield l
1871
1872     return split_wrapper
1873
1874
1875 @dont_increase_indentation
1876 def delimiter_split(line: Line, py36: bool = False) -> Iterator[Line]:
1877     """Split according to delimiters of the highest priority.
1878
1879     If `py36` is True, the split will add trailing commas also in function
1880     signatures that contain `*` and `**`.
1881     """
1882     try:
1883         last_leaf = line.leaves[-1]
1884     except IndexError:
1885         raise CannotSplit("Line empty")
1886
1887     delimiters = line.bracket_tracker.delimiters
1888     try:
1889         delimiter_priority = line.bracket_tracker.max_delimiter_priority(
1890             exclude={id(last_leaf)}
1891         )
1892     except ValueError:
1893         raise CannotSplit("No delimiters found")
1894
1895     current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
1896     lowest_depth = sys.maxsize
1897     trailing_comma_safe = True
1898
1899     def append_to_line(leaf: Leaf) -> Iterator[Line]:
1900         """Append `leaf` to current line or to new line if appending impossible."""
1901         nonlocal current_line
1902         try:
1903             current_line.append_safe(leaf, preformatted=True)
1904         except ValueError as ve:
1905             yield current_line
1906
1907             current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
1908             current_line.append(leaf)
1909
1910     for leaf in line.leaves:
1911         yield from append_to_line(leaf)
1912
1913         for comment_after in line.comments_after(leaf):
1914             yield from append_to_line(comment_after)
1915
1916         lowest_depth = min(lowest_depth, leaf.bracket_depth)
1917         if (
1918             leaf.bracket_depth == lowest_depth
1919             and is_vararg(leaf, within=VARARGS_PARENTS)
1920         ):
1921             trailing_comma_safe = trailing_comma_safe and py36
1922         leaf_priority = delimiters.get(id(leaf))
1923         if leaf_priority == delimiter_priority:
1924             yield current_line
1925
1926             current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
1927     if current_line:
1928         if (
1929             trailing_comma_safe
1930             and delimiter_priority == COMMA_PRIORITY
1931             and current_line.leaves[-1].type != token.COMMA
1932             and current_line.leaves[-1].type != STANDALONE_COMMENT
1933         ):
1934             current_line.append(Leaf(token.COMMA, ","))
1935         yield current_line
1936
1937
1938 @dont_increase_indentation
1939 def standalone_comment_split(line: Line, py36: bool = False) -> Iterator[Line]:
1940     """Split standalone comments from the rest of the line."""
1941     if not line.contains_standalone_comments(0):
1942         raise CannotSplit("Line does not have any standalone comments")
1943
1944     current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
1945
1946     def append_to_line(leaf: Leaf) -> Iterator[Line]:
1947         """Append `leaf` to current line or to new line if appending impossible."""
1948         nonlocal current_line
1949         try:
1950             current_line.append_safe(leaf, preformatted=True)
1951         except ValueError as ve:
1952             yield current_line
1953
1954             current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
1955             current_line.append(leaf)
1956
1957     for leaf in line.leaves:
1958         yield from append_to_line(leaf)
1959
1960         for comment_after in line.comments_after(leaf):
1961             yield from append_to_line(comment_after)
1962
1963     if current_line:
1964         yield current_line
1965
1966
1967 def is_import(leaf: Leaf) -> bool:
1968     """Return True if the given leaf starts an import statement."""
1969     p = leaf.parent
1970     t = leaf.type
1971     v = leaf.value
1972     return bool(
1973         t == token.NAME
1974         and (
1975             (v == "import" and p and p.type == syms.import_name)
1976             or (v == "from" and p and p.type == syms.import_from)
1977         )
1978     )
1979
1980
1981 def normalize_prefix(leaf: Leaf, *, inside_brackets: bool) -> None:
1982     """Leave existing extra newlines if not `inside_brackets`. Remove everything
1983     else.
1984
1985     Note: don't use backslashes for formatting or you'll lose your voting rights.
1986     """
1987     if not inside_brackets:
1988         spl = leaf.prefix.split("#")
1989         if "\\" not in spl[0]:
1990             nl_count = spl[-1].count("\n")
1991             if len(spl) > 1:
1992                 nl_count -= 1
1993             leaf.prefix = "\n" * nl_count
1994             return
1995
1996     leaf.prefix = ""
1997
1998
1999 def normalize_string_quotes(leaf: Leaf) -> None:
2000     """Prefer double quotes but only if it doesn't cause more escaping.
2001
2002     Adds or removes backslashes as appropriate. Doesn't parse and fix
2003     strings nested in f-strings (yet).
2004
2005     Note: Mutates its argument.
2006     """
2007     value = leaf.value.lstrip("furbFURB")
2008     if value[:3] == '"""':
2009         return
2010
2011     elif value[:3] == "'''":
2012         orig_quote = "'''"
2013         new_quote = '"""'
2014     elif value[0] == '"':
2015         orig_quote = '"'
2016         new_quote = "'"
2017     else:
2018         orig_quote = "'"
2019         new_quote = '"'
2020     first_quote_pos = leaf.value.find(orig_quote)
2021     if first_quote_pos == -1:
2022         return  # There's an internal error
2023
2024     prefix = leaf.value[:first_quote_pos]
2025     unescaped_new_quote = re.compile(rf"(([^\\]|^)(\\\\)*){new_quote}")
2026     escaped_new_quote = re.compile(rf"([^\\]|^)\\(\\\\)*{new_quote}")
2027     escaped_orig_quote = re.compile(rf"([^\\]|^)\\(\\\\)*{orig_quote}")
2028     body = leaf.value[first_quote_pos + len(orig_quote):-len(orig_quote)]
2029     if "r" in prefix.casefold():
2030         if unescaped_new_quote.search(body):
2031             # There's at least one unescaped new_quote in this raw string
2032             # so converting is impossible
2033             return
2034
2035         # Do not introduce or remove backslashes in raw strings
2036         new_body = body
2037     else:
2038         # remove unnecessary quotes
2039         new_body = sub_twice(escaped_new_quote, rf"\1\2{new_quote}", body)
2040         if body != new_body:
2041             # Consider the string without unnecessary quotes as the original
2042             body = new_body
2043             leaf.value = f"{prefix}{orig_quote}{body}{orig_quote}"
2044         new_body = sub_twice(escaped_orig_quote, rf"\1\2{orig_quote}", new_body)
2045         new_body = sub_twice(unescaped_new_quote, rf"\1\\{new_quote}", new_body)
2046     if new_quote == '"""' and new_body[-1] == '"':
2047         # edge case:
2048         new_body = new_body[:-1] + '\\"'
2049     orig_escape_count = body.count("\\")
2050     new_escape_count = new_body.count("\\")
2051     if new_escape_count > orig_escape_count:
2052         return  # Do not introduce more escaping
2053
2054     if new_escape_count == orig_escape_count and orig_quote == '"':
2055         return  # Prefer double quotes
2056
2057     leaf.value = f"{prefix}{new_quote}{new_body}{new_quote}"
2058
2059
2060 def normalize_invisible_parens(node: Node, parens_after: Set[str]) -> None:
2061     """Make existing optional parentheses invisible or create new ones.
2062
2063     Standardizes on visible parentheses for single-element tuples, and keeps
2064     existing visible parentheses for other tuples and generator expressions.
2065     """
2066     check_lpar = False
2067     for child in list(node.children):
2068         if check_lpar:
2069             if child.type == syms.atom:
2070                 if not (
2071                     is_empty_tuple(child)
2072                     or is_one_tuple(child)
2073                     or max_delimiter_priority_in_atom(child) >= COMMA_PRIORITY
2074                 ):
2075                     first = child.children[0]
2076                     last = child.children[-1]
2077                     if first.type == token.LPAR and last.type == token.RPAR:
2078                         # make parentheses invisible
2079                         first.value = ""  # type: ignore
2080                         last.value = ""  # type: ignore
2081             elif is_one_tuple(child):
2082                 # wrap child in visible parentheses
2083                 lpar = Leaf(token.LPAR, "(")
2084                 rpar = Leaf(token.RPAR, ")")
2085                 index = child.remove() or 0
2086                 node.insert_child(index, Node(syms.atom, [lpar, child, rpar]))
2087             else:
2088                 # wrap child in invisible parentheses
2089                 lpar = Leaf(token.LPAR, "")
2090                 rpar = Leaf(token.RPAR, "")
2091                 index = child.remove() or 0
2092                 node.insert_child(index, Node(syms.atom, [lpar, child, rpar]))
2093
2094         check_lpar = isinstance(child, Leaf) and child.value in parens_after
2095
2096
2097 def is_empty_tuple(node: LN) -> bool:
2098     """Return True if `node` holds an empty tuple."""
2099     return (
2100         node.type == syms.atom
2101         and len(node.children) == 2
2102         and node.children[0].type == token.LPAR
2103         and node.children[1].type == token.RPAR
2104     )
2105
2106
2107 def is_one_tuple(node: LN) -> bool:
2108     """Return True if `node` holds a tuple with one element, with or without parens."""
2109     if node.type == syms.atom:
2110         if len(node.children) != 3:
2111             return False
2112
2113         lpar, gexp, rpar = node.children
2114         if not (
2115             lpar.type == token.LPAR
2116             and gexp.type == syms.testlist_gexp
2117             and rpar.type == token.RPAR
2118         ):
2119             return False
2120
2121         return len(gexp.children) == 2 and gexp.children[1].type == token.COMMA
2122
2123     return (
2124         node.type in IMPLICIT_TUPLE
2125         and len(node.children) == 2
2126         and node.children[1].type == token.COMMA
2127     )
2128
2129
2130 def is_vararg(leaf: Leaf, within: Set[NodeType]) -> bool:
2131     """Return True if `leaf` is a star or double star in a vararg or kwarg.
2132
2133     If `within` includes VARARGS_PARENTS, this applies to function signatures.
2134     If `within` includes COLLECTION_LIBERALS_PARENTS, it applies to right
2135     hand-side extended iterable unpacking (PEP 3132) and additional unpacking
2136     generalizations (PEP 448).
2137     """
2138     if leaf.type not in STARS or not leaf.parent:
2139         return False
2140
2141     p = leaf.parent
2142     if p.type == syms.star_expr:
2143         # Star expressions are also used as assignment targets in extended
2144         # iterable unpacking (PEP 3132).  See what its parent is instead.
2145         if not p.parent:
2146             return False
2147
2148         p = p.parent
2149
2150     return p.type in within
2151
2152
2153 def max_delimiter_priority_in_atom(node: LN) -> int:
2154     """Return maximum delimiter priority inside `node`.
2155
2156     This is specific to atoms with contents contained in a pair of parentheses.
2157     If `node` isn't an atom or there are no enclosing parentheses, returns 0.
2158     """
2159     if node.type != syms.atom:
2160         return 0
2161
2162     first = node.children[0]
2163     last = node.children[-1]
2164     if not (first.type == token.LPAR and last.type == token.RPAR):
2165         return 0
2166
2167     bt = BracketTracker()
2168     for c in node.children[1:-1]:
2169         if isinstance(c, Leaf):
2170             bt.mark(c)
2171         else:
2172             for leaf in c.leaves():
2173                 bt.mark(leaf)
2174     try:
2175         return bt.max_delimiter_priority()
2176
2177     except ValueError:
2178         return 0
2179
2180
2181 def ensure_visible(leaf: Leaf) -> None:
2182     """Make sure parentheses are visible.
2183
2184     They could be invisible as part of some statements (see
2185     :func:`normalize_invible_parens` and :func:`visit_import_from`).
2186     """
2187     if leaf.type == token.LPAR:
2188         leaf.value = "("
2189     elif leaf.type == token.RPAR:
2190         leaf.value = ")"
2191
2192
2193 def is_python36(node: Node) -> bool:
2194     """Return True if the current file is using Python 3.6+ features.
2195
2196     Currently looking for:
2197     - f-strings; and
2198     - trailing commas after * or ** in function signatures.
2199     """
2200     for n in node.pre_order():
2201         if n.type == token.STRING:
2202             value_head = n.value[:2]  # type: ignore
2203             if value_head in {'f"', 'F"', "f'", "F'", "rf", "fr", "RF", "FR"}:
2204                 return True
2205
2206         elif (
2207             n.type == syms.typedargslist
2208             and n.children
2209             and n.children[-1].type == token.COMMA
2210         ):
2211             for ch in n.children:
2212                 if ch.type in STARS:
2213                     return True
2214
2215     return False
2216
2217
2218 PYTHON_EXTENSIONS = {".py"}
2219 BLACKLISTED_DIRECTORIES = {
2220     "build", "buck-out", "dist", "_build", ".git", ".hg", ".mypy_cache", ".tox", ".venv"
2221 }
2222
2223
2224 def gen_python_files_in_dir(path: Path) -> Iterator[Path]:
2225     """Generate all files under `path` which aren't under BLACKLISTED_DIRECTORIES
2226     and have one of the PYTHON_EXTENSIONS.
2227     """
2228     for child in path.iterdir():
2229         if child.is_dir():
2230             if child.name in BLACKLISTED_DIRECTORIES:
2231                 continue
2232
2233             yield from gen_python_files_in_dir(child)
2234
2235         elif child.suffix in PYTHON_EXTENSIONS:
2236             yield child
2237
2238
2239 @dataclass
2240 class Report:
2241     """Provides a reformatting counter. Can be rendered with `str(report)`."""
2242     check: bool = False
2243     quiet: bool = False
2244     change_count: int = 0
2245     same_count: int = 0
2246     failure_count: int = 0
2247
2248     def done(self, src: Path, changed: Changed) -> None:
2249         """Increment the counter for successful reformatting. Write out a message."""
2250         if changed is Changed.YES:
2251             reformatted = "would reformat" if self.check else "reformatted"
2252             if not self.quiet:
2253                 out(f"{reformatted} {src}")
2254             self.change_count += 1
2255         else:
2256             if not self.quiet:
2257                 if changed is Changed.NO:
2258                     msg = f"{src} already well formatted, good job."
2259                 else:
2260                     msg = f"{src} wasn't modified on disk since last run."
2261                 out(msg, bold=False)
2262             self.same_count += 1
2263
2264     def failed(self, src: Path, message: str) -> None:
2265         """Increment the counter for failed reformatting. Write out a message."""
2266         err(f"error: cannot format {src}: {message}")
2267         self.failure_count += 1
2268
2269     @property
2270     def return_code(self) -> int:
2271         """Return the exit code that the app should use.
2272
2273         This considers the current state of changed files and failures:
2274         - if there were any failures, return 123;
2275         - if any files were changed and --check is being used, return 1;
2276         - otherwise return 0.
2277         """
2278         # According to http://tldp.org/LDP/abs/html/exitcodes.html starting with
2279         # 126 we have special returncodes reserved by the shell.
2280         if self.failure_count:
2281             return 123
2282
2283         elif self.change_count and self.check:
2284             return 1
2285
2286         return 0
2287
2288     def __str__(self) -> str:
2289         """Render a color report of the current state.
2290
2291         Use `click.unstyle` to remove colors.
2292         """
2293         if self.check:
2294             reformatted = "would be reformatted"
2295             unchanged = "would be left unchanged"
2296             failed = "would fail to reformat"
2297         else:
2298             reformatted = "reformatted"
2299             unchanged = "left unchanged"
2300             failed = "failed to reformat"
2301         report = []
2302         if self.change_count:
2303             s = "s" if self.change_count > 1 else ""
2304             report.append(
2305                 click.style(f"{self.change_count} file{s} {reformatted}", bold=True)
2306             )
2307         if self.same_count:
2308             s = "s" if self.same_count > 1 else ""
2309             report.append(f"{self.same_count} file{s} {unchanged}")
2310         if self.failure_count:
2311             s = "s" if self.failure_count > 1 else ""
2312             report.append(
2313                 click.style(f"{self.failure_count} file{s} {failed}", fg="red")
2314             )
2315         return ", ".join(report) + "."
2316
2317
2318 def assert_equivalent(src: str, dst: str) -> None:
2319     """Raise AssertionError if `src` and `dst` aren't equivalent."""
2320
2321     import ast
2322     import traceback
2323
2324     def _v(node: ast.AST, depth: int = 0) -> Iterator[str]:
2325         """Simple visitor generating strings to compare ASTs by content."""
2326         yield f"{'  ' * depth}{node.__class__.__name__}("
2327
2328         for field in sorted(node._fields):
2329             try:
2330                 value = getattr(node, field)
2331             except AttributeError:
2332                 continue
2333
2334             yield f"{'  ' * (depth+1)}{field}="
2335
2336             if isinstance(value, list):
2337                 for item in value:
2338                     if isinstance(item, ast.AST):
2339                         yield from _v(item, depth + 2)
2340
2341             elif isinstance(value, ast.AST):
2342                 yield from _v(value, depth + 2)
2343
2344             else:
2345                 yield f"{'  ' * (depth+2)}{value!r},  # {value.__class__.__name__}"
2346
2347         yield f"{'  ' * depth})  # /{node.__class__.__name__}"
2348
2349     try:
2350         src_ast = ast.parse(src)
2351     except Exception as exc:
2352         major, minor = sys.version_info[:2]
2353         raise AssertionError(
2354             f"cannot use --safe with this file; failed to parse source file "
2355             f"with Python {major}.{minor}'s builtin AST. Re-run with --fast "
2356             f"or stop using deprecated Python 2 syntax. AST error message: {exc}"
2357         )
2358
2359     try:
2360         dst_ast = ast.parse(dst)
2361     except Exception as exc:
2362         log = dump_to_file("".join(traceback.format_tb(exc.__traceback__)), dst)
2363         raise AssertionError(
2364             f"INTERNAL ERROR: Black produced invalid code: {exc}. "
2365             f"Please report a bug on https://github.com/ambv/black/issues.  "
2366             f"This invalid output might be helpful: {log}"
2367         ) from None
2368
2369     src_ast_str = "\n".join(_v(src_ast))
2370     dst_ast_str = "\n".join(_v(dst_ast))
2371     if src_ast_str != dst_ast_str:
2372         log = dump_to_file(diff(src_ast_str, dst_ast_str, "src", "dst"))
2373         raise AssertionError(
2374             f"INTERNAL ERROR: Black produced code that is not equivalent to "
2375             f"the source.  "
2376             f"Please report a bug on https://github.com/ambv/black/issues.  "
2377             f"This diff might be helpful: {log}"
2378         ) from None
2379
2380
2381 def assert_stable(src: str, dst: str, line_length: int) -> None:
2382     """Raise AssertionError if `dst` reformats differently the second time."""
2383     newdst = format_str(dst, line_length=line_length)
2384     if dst != newdst:
2385         log = dump_to_file(
2386             diff(src, dst, "source", "first pass"),
2387             diff(dst, newdst, "first pass", "second pass"),
2388         )
2389         raise AssertionError(
2390             f"INTERNAL ERROR: Black produced different code on the second pass "
2391             f"of the formatter.  "
2392             f"Please report a bug on https://github.com/ambv/black/issues.  "
2393             f"This diff might be helpful: {log}"
2394         ) from None
2395
2396
2397 def dump_to_file(*output: str) -> str:
2398     """Dump `output` to a temporary file. Return path to the file."""
2399     import tempfile
2400
2401     with tempfile.NamedTemporaryFile(
2402         mode="w", prefix="blk_", suffix=".log", delete=False, encoding="utf8"
2403     ) as f:
2404         for lines in output:
2405             f.write(lines)
2406             if lines and lines[-1] != "\n":
2407                 f.write("\n")
2408     return f.name
2409
2410
2411 def diff(a: str, b: str, a_name: str, b_name: str) -> str:
2412     """Return a unified diff string between strings `a` and `b`."""
2413     import difflib
2414
2415     a_lines = [line + "\n" for line in a.split("\n")]
2416     b_lines = [line + "\n" for line in b.split("\n")]
2417     return "".join(
2418         difflib.unified_diff(a_lines, b_lines, fromfile=a_name, tofile=b_name, n=5)
2419     )
2420
2421
2422 def cancel(tasks: List[asyncio.Task]) -> None:
2423     """asyncio signal handler that cancels all `tasks` and reports to stderr."""
2424     err("Aborted!")
2425     for task in tasks:
2426         task.cancel()
2427
2428
2429 def shutdown(loop: BaseEventLoop) -> None:
2430     """Cancel all pending tasks on `loop`, wait for them, and close the loop."""
2431     try:
2432         # This part is borrowed from asyncio/runners.py in Python 3.7b2.
2433         to_cancel = [task for task in asyncio.Task.all_tasks(loop) if not task.done()]
2434         if not to_cancel:
2435             return
2436
2437         for task in to_cancel:
2438             task.cancel()
2439         loop.run_until_complete(
2440             asyncio.gather(*to_cancel, loop=loop, return_exceptions=True)
2441         )
2442     finally:
2443         # `concurrent.futures.Future` objects cannot be cancelled once they
2444         # are already running. There might be some when the `shutdown()` happened.
2445         # Silence their logger's spew about the event loop being closed.
2446         cf_logger = logging.getLogger("concurrent.futures")
2447         cf_logger.setLevel(logging.CRITICAL)
2448         loop.close()
2449
2450
2451 def sub_twice(regex: Pattern[str], replacement: str, original: str) -> str:
2452     """Replace `regex` with `replacement` twice on `original`.
2453
2454     This is used by string normalization to perform replaces on
2455     overlapping matches.
2456     """
2457     return regex.sub(replacement, regex.sub(replacement, original))
2458
2459
2460 CACHE_DIR = Path(user_cache_dir("black", version=__version__))
2461 CACHE_FILE = CACHE_DIR / "cache.pickle"
2462
2463
2464 def read_cache() -> Cache:
2465     """Read the cache if it exists and is well formed.
2466
2467     If it is not well formed, the call to write_cache later should resolve the issue.
2468     """
2469     if not CACHE_FILE.exists():
2470         return {}
2471
2472     with CACHE_FILE.open("rb") as fobj:
2473         try:
2474             cache: Cache = pickle.load(fobj)
2475         except pickle.UnpicklingError:
2476             return {}
2477
2478     return cache
2479
2480
2481 def get_cache_info(path: Path) -> CacheInfo:
2482     """Return the information used to check if a file is already formatted or not."""
2483     stat = path.stat()
2484     return stat.st_mtime, stat.st_size
2485
2486
2487 def filter_cached(
2488     cache: Cache, sources: Iterable[Path]
2489 ) -> Tuple[List[Path], List[Path]]:
2490     """Split a list of paths into two.
2491
2492     The first list contains paths of files that modified on disk or are not in the
2493     cache. The other list contains paths to non-modified files.
2494     """
2495     todo, done = [], []
2496     for src in sources:
2497         src = src.resolve()
2498         if cache.get(src) != get_cache_info(src):
2499             todo.append(src)
2500         else:
2501             done.append(src)
2502     return todo, done
2503
2504
2505 def write_cache(cache: Cache, sources: List[Path]) -> None:
2506     """Update the cache file."""
2507     try:
2508         if not CACHE_DIR.exists():
2509             CACHE_DIR.mkdir(parents=True)
2510         new_cache = {**cache, **{src.resolve(): get_cache_info(src) for src in sources}}
2511         with CACHE_FILE.open("wb") as fobj:
2512             pickle.dump(new_cache, fobj, protocol=pickle.HIGHEST_PROTOCOL)
2513     except OSError:
2514         pass
2515
2516
2517 if __name__ == "__main__":
2518     main()