]> 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:

52096819e76676a2e0be8c41ddb000a88bb54b01
[etc/vim.git] / black.py
1 import ast
2 import asyncio
3 from concurrent.futures import Executor, ProcessPoolExecutor
4 from contextlib import contextmanager
5 from datetime import datetime
6 from enum import Enum
7 from functools import lru_cache, partial, wraps
8 import io
9 import itertools
10 import logging
11 from multiprocessing import Manager, freeze_support
12 import os
13 from pathlib import Path
14 import pickle
15 import regex as re
16 import signal
17 import sys
18 import tempfile
19 import tokenize
20 import traceback
21 from typing import (
22     Any,
23     Callable,
24     Collection,
25     Dict,
26     Generator,
27     Generic,
28     Iterable,
29     Iterator,
30     List,
31     Optional,
32     Pattern,
33     Sequence,
34     Set,
35     Tuple,
36     TypeVar,
37     Union,
38     cast,
39 )
40 from typing_extensions import Final
41 from mypy_extensions import mypyc_attr
42
43 from appdirs import user_cache_dir
44 from dataclasses import dataclass, field, replace
45 import click
46 import toml
47 from typed_ast import ast3, ast27
48 from pathspec import PathSpec
49
50 # lib2to3 fork
51 from blib2to3.pytree import Node, Leaf, type_repr
52 from blib2to3 import pygram, pytree
53 from blib2to3.pgen2 import driver, token
54 from blib2to3.pgen2.grammar import Grammar
55 from blib2to3.pgen2.parse import ParseError
56
57 from _black_version import version as __version__
58
59 DEFAULT_LINE_LENGTH = 88
60 DEFAULT_EXCLUDES = r"/(\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|\.svn|_build|buck-out|build|dist)/"  # noqa: B950
61 DEFAULT_INCLUDES = r"\.pyi?$"
62 CACHE_DIR = Path(user_cache_dir("black", version=__version__))
63
64
65 # types
66 FileContent = str
67 Encoding = str
68 NewLine = str
69 Depth = int
70 NodeType = int
71 LeafID = int
72 Priority = int
73 Index = int
74 LN = Union[Leaf, Node]
75 SplitFunc = Callable[["Line", Collection["Feature"]], Iterator["Line"]]
76 Timestamp = float
77 FileSize = int
78 CacheInfo = Tuple[Timestamp, FileSize]
79 Cache = Dict[Path, CacheInfo]
80 out = partial(click.secho, bold=True, err=True)
81 err = partial(click.secho, fg="red", err=True)
82
83 pygram.initialize(CACHE_DIR)
84 syms = pygram.python_symbols
85
86
87 class NothingChanged(UserWarning):
88     """Raised when reformatted code is the same as source."""
89
90
91 class CannotSplit(Exception):
92     """A readable split that fits the allotted line length is impossible."""
93
94
95 class InvalidInput(ValueError):
96     """Raised when input source code fails all parse attempts."""
97
98
99 class WriteBack(Enum):
100     NO = 0
101     YES = 1
102     DIFF = 2
103     CHECK = 3
104
105     @classmethod
106     def from_configuration(cls, *, check: bool, diff: bool) -> "WriteBack":
107         if check and not diff:
108             return cls.CHECK
109
110         return cls.DIFF if diff else cls.YES
111
112
113 class Changed(Enum):
114     NO = 0
115     CACHED = 1
116     YES = 2
117
118
119 class TargetVersion(Enum):
120     PY27 = 2
121     PY33 = 3
122     PY34 = 4
123     PY35 = 5
124     PY36 = 6
125     PY37 = 7
126     PY38 = 8
127
128     def is_python2(self) -> bool:
129         return self is TargetVersion.PY27
130
131
132 PY36_VERSIONS = {TargetVersion.PY36, TargetVersion.PY37, TargetVersion.PY38}
133
134
135 class Feature(Enum):
136     # All string literals are unicode
137     UNICODE_LITERALS = 1
138     F_STRINGS = 2
139     NUMERIC_UNDERSCORES = 3
140     TRAILING_COMMA_IN_CALL = 4
141     TRAILING_COMMA_IN_DEF = 5
142     # The following two feature-flags are mutually exclusive, and exactly one should be
143     # set for every version of python.
144     ASYNC_IDENTIFIERS = 6
145     ASYNC_KEYWORDS = 7
146     ASSIGNMENT_EXPRESSIONS = 8
147     POS_ONLY_ARGUMENTS = 9
148
149
150 VERSION_TO_FEATURES: Dict[TargetVersion, Set[Feature]] = {
151     TargetVersion.PY27: {Feature.ASYNC_IDENTIFIERS},
152     TargetVersion.PY33: {Feature.UNICODE_LITERALS, Feature.ASYNC_IDENTIFIERS},
153     TargetVersion.PY34: {Feature.UNICODE_LITERALS, Feature.ASYNC_IDENTIFIERS},
154     TargetVersion.PY35: {
155         Feature.UNICODE_LITERALS,
156         Feature.TRAILING_COMMA_IN_CALL,
157         Feature.ASYNC_IDENTIFIERS,
158     },
159     TargetVersion.PY36: {
160         Feature.UNICODE_LITERALS,
161         Feature.F_STRINGS,
162         Feature.NUMERIC_UNDERSCORES,
163         Feature.TRAILING_COMMA_IN_CALL,
164         Feature.TRAILING_COMMA_IN_DEF,
165         Feature.ASYNC_IDENTIFIERS,
166     },
167     TargetVersion.PY37: {
168         Feature.UNICODE_LITERALS,
169         Feature.F_STRINGS,
170         Feature.NUMERIC_UNDERSCORES,
171         Feature.TRAILING_COMMA_IN_CALL,
172         Feature.TRAILING_COMMA_IN_DEF,
173         Feature.ASYNC_KEYWORDS,
174     },
175     TargetVersion.PY38: {
176         Feature.UNICODE_LITERALS,
177         Feature.F_STRINGS,
178         Feature.NUMERIC_UNDERSCORES,
179         Feature.TRAILING_COMMA_IN_CALL,
180         Feature.TRAILING_COMMA_IN_DEF,
181         Feature.ASYNC_KEYWORDS,
182         Feature.ASSIGNMENT_EXPRESSIONS,
183         Feature.POS_ONLY_ARGUMENTS,
184     },
185 }
186
187
188 @dataclass
189 class FileMode:
190     target_versions: Set[TargetVersion] = field(default_factory=set)
191     line_length: int = DEFAULT_LINE_LENGTH
192     string_normalization: bool = True
193     is_pyi: bool = False
194
195     def get_cache_key(self) -> str:
196         if self.target_versions:
197             version_str = ",".join(
198                 str(version.value)
199                 for version in sorted(self.target_versions, key=lambda v: v.value)
200             )
201         else:
202             version_str = "-"
203         parts = [
204             version_str,
205             str(self.line_length),
206             str(int(self.string_normalization)),
207             str(int(self.is_pyi)),
208         ]
209         return ".".join(parts)
210
211
212 def supports_feature(target_versions: Set[TargetVersion], feature: Feature) -> bool:
213     return all(feature in VERSION_TO_FEATURES[version] for version in target_versions)
214
215
216 def find_pyproject_toml(path_search_start: str) -> Optional[str]:
217     """Find the absolute filepath to a pyproject.toml if it exists"""
218     path_project_root = find_project_root(path_search_start)
219     path_pyproject_toml = path_project_root / "pyproject.toml"
220     return str(path_pyproject_toml) if path_pyproject_toml.is_file() else None
221
222
223 def parse_pyproject_toml(path_config: str) -> Dict[str, Any]:
224     """Parse a pyproject toml file, pulling out relevant parts for Black
225
226     If parsing fails, will raise a toml.TomlDecodeError
227     """
228     pyproject_toml = toml.load(path_config)
229     config = pyproject_toml.get("tool", {}).get("black", {})
230     return {k.replace("--", "").replace("-", "_"): v for k, v in config.items()}
231
232
233 def read_pyproject_toml(
234     ctx: click.Context, param: click.Parameter, value: Union[str, int, bool, None]
235 ) -> Optional[str]:
236     """Inject Black configuration from "pyproject.toml" into defaults in `ctx`.
237
238     Returns the path to a successfully found and read configuration file, None
239     otherwise.
240     """
241     assert not isinstance(value, (int, bool)), "Invalid parameter type passed"
242     if not value:
243         value = find_pyproject_toml(ctx.params.get("src", ()))
244         if value is None:
245             return None
246
247     try:
248         config = parse_pyproject_toml(value)
249     except (toml.TomlDecodeError, OSError) as e:
250         raise click.FileError(
251             filename=value, hint=f"Error reading configuration file: {e}"
252         )
253
254     if not config:
255         return None
256
257     if ctx.default_map is None:
258         ctx.default_map = {}
259     ctx.default_map.update(config)  # type: ignore  # bad types in .pyi
260     return value
261
262
263 def target_version_option_callback(
264     c: click.Context, p: Union[click.Option, click.Parameter], v: Tuple[str, ...]
265 ) -> List[TargetVersion]:
266     """Compute the target versions from a --target-version flag.
267
268     This is its own function because mypy couldn't infer the type correctly
269     when it was a lambda, causing mypyc trouble.
270     """
271     return [TargetVersion[val.upper()] for val in v]
272
273
274 @click.command(context_settings=dict(help_option_names=["-h", "--help"]))
275 @click.option("-c", "--code", type=str, help="Format the code passed in as a string.")
276 @click.option(
277     "-l",
278     "--line-length",
279     type=int,
280     default=DEFAULT_LINE_LENGTH,
281     help="How many characters per line to allow.",
282     show_default=True,
283 )
284 @click.option(
285     "-t",
286     "--target-version",
287     type=click.Choice([v.name.lower() for v in TargetVersion]),
288     callback=target_version_option_callback,
289     multiple=True,
290     help=(
291         "Python versions that should be supported by Black's output. [default: "
292         "per-file auto-detection]"
293     ),
294 )
295 @click.option(
296     "--py36",
297     is_flag=True,
298     help=(
299         "Allow using Python 3.6-only syntax on all input files.  This will put "
300         "trailing commas in function signatures and calls also after *args and "
301         "**kwargs. Deprecated; use --target-version instead. "
302         "[default: per-file auto-detection]"
303     ),
304 )
305 @click.option(
306     "--pyi",
307     is_flag=True,
308     help=(
309         "Format all input files like typing stubs regardless of file extension "
310         "(useful when piping source on standard input)."
311     ),
312 )
313 @click.option(
314     "-S",
315     "--skip-string-normalization",
316     is_flag=True,
317     help="Don't normalize string quotes or prefixes.",
318 )
319 @click.option(
320     "--check",
321     is_flag=True,
322     help=(
323         "Don't write the files back, just return the status.  Return code 0 "
324         "means nothing would change.  Return code 1 means some files would be "
325         "reformatted.  Return code 123 means there was an internal error."
326     ),
327 )
328 @click.option(
329     "--diff",
330     is_flag=True,
331     help="Don't write the files back, just output a diff for each file on stdout.",
332 )
333 @click.option(
334     "--fast/--safe",
335     is_flag=True,
336     help="If --fast given, skip temporary sanity checks. [default: --safe]",
337 )
338 @click.option(
339     "--include",
340     type=str,
341     default=DEFAULT_INCLUDES,
342     help=(
343         "A regular expression that matches files and directories that should be "
344         "included on recursive searches.  An empty value means all files are "
345         "included regardless of the name.  Use forward slashes for directories on "
346         "all platforms (Windows, too).  Exclusions are calculated first, inclusions "
347         "later."
348     ),
349     show_default=True,
350 )
351 @click.option(
352     "--exclude",
353     type=str,
354     default=DEFAULT_EXCLUDES,
355     help=(
356         "A regular expression that matches files and directories that should be "
357         "excluded on recursive searches.  An empty value means no paths are excluded. "
358         "Use forward slashes for directories on all platforms (Windows, too).  "
359         "Exclusions are calculated first, inclusions later."
360     ),
361     show_default=True,
362 )
363 @click.option(
364     "-q",
365     "--quiet",
366     is_flag=True,
367     help=(
368         "Don't emit non-error messages to stderr. Errors are still emitted; "
369         "silence those with 2>/dev/null."
370     ),
371 )
372 @click.option(
373     "-v",
374     "--verbose",
375     is_flag=True,
376     help=(
377         "Also emit messages to stderr about files that were not changed or were "
378         "ignored due to --exclude=."
379     ),
380 )
381 @click.version_option(version=__version__)
382 @click.argument(
383     "src",
384     nargs=-1,
385     type=click.Path(
386         exists=True, file_okay=True, dir_okay=True, readable=True, allow_dash=True
387     ),
388     is_eager=True,
389 )
390 @click.option(
391     "--config",
392     type=click.Path(
393         exists=False, file_okay=True, dir_okay=False, readable=True, allow_dash=False
394     ),
395     is_eager=True,
396     callback=read_pyproject_toml,
397     help="Read configuration from PATH.",
398 )
399 @click.pass_context
400 def main(
401     ctx: click.Context,
402     code: Optional[str],
403     line_length: int,
404     target_version: List[TargetVersion],
405     check: bool,
406     diff: bool,
407     fast: bool,
408     pyi: bool,
409     py36: bool,
410     skip_string_normalization: bool,
411     quiet: bool,
412     verbose: bool,
413     include: str,
414     exclude: str,
415     src: Tuple[str, ...],
416     config: Optional[str],
417 ) -> None:
418     """The uncompromising code formatter."""
419     write_back = WriteBack.from_configuration(check=check, diff=diff)
420     if target_version:
421         if py36:
422             err(f"Cannot use both --target-version and --py36")
423             ctx.exit(2)
424         else:
425             versions = set(target_version)
426     elif py36:
427         err(
428             "--py36 is deprecated and will be removed in a future version. "
429             "Use --target-version py36 instead."
430         )
431         versions = PY36_VERSIONS
432     else:
433         # We'll autodetect later.
434         versions = set()
435     mode = FileMode(
436         target_versions=versions,
437         line_length=line_length,
438         is_pyi=pyi,
439         string_normalization=not skip_string_normalization,
440     )
441     if config and verbose:
442         out(f"Using configuration from {config}.", bold=False, fg="blue")
443     if code is not None:
444         print(format_str(code, mode=mode))
445         ctx.exit(0)
446     try:
447         include_regex = re_compile_maybe_verbose(include)
448     except re.error:
449         err(f"Invalid regular expression for include given: {include!r}")
450         ctx.exit(2)
451     try:
452         exclude_regex = re_compile_maybe_verbose(exclude)
453     except re.error:
454         err(f"Invalid regular expression for exclude given: {exclude!r}")
455         ctx.exit(2)
456     report = Report(check=check, diff=diff, quiet=quiet, verbose=verbose)
457     root = find_project_root(src)
458     sources: Set[Path] = set()
459     path_empty(src, quiet, verbose, ctx)
460     for s in src:
461         p = Path(s)
462         if p.is_dir():
463             sources.update(
464                 gen_python_files_in_dir(
465                     p, root, include_regex, exclude_regex, report, get_gitignore(root)
466                 )
467             )
468         elif p.is_file() or s == "-":
469             # if a file was explicitly given, we don't care about its extension
470             sources.add(p)
471         else:
472             err(f"invalid path: {s}")
473     if len(sources) == 0:
474         if verbose or not quiet:
475             out("No Python files are present to be formatted. Nothing to do 😴")
476         ctx.exit(0)
477
478     if len(sources) == 1:
479         reformat_one(
480             src=sources.pop(),
481             fast=fast,
482             write_back=write_back,
483             mode=mode,
484             report=report,
485         )
486     else:
487         reformat_many(
488             sources=sources, fast=fast, write_back=write_back, mode=mode, report=report
489         )
490
491     if verbose or not quiet:
492         out("Oh no! 💥 💔 💥" if report.return_code else "All done! ✨ 🍰 ✨")
493         click.secho(str(report), err=True)
494     ctx.exit(report.return_code)
495
496
497 def path_empty(
498     src: Tuple[str, ...], quiet: bool, verbose: bool, ctx: click.Context
499 ) -> None:
500     """
501     Exit if there is no `src` provided for formatting
502     """
503     if not src:
504         if verbose or not quiet:
505             out("No Path provided. Nothing to do 😴")
506             ctx.exit(0)
507
508
509 def reformat_one(
510     src: Path, fast: bool, write_back: WriteBack, mode: FileMode, report: "Report"
511 ) -> None:
512     """Reformat a single file under `src` without spawning child processes.
513
514     `fast`, `write_back`, and `mode` options are passed to
515     :func:`format_file_in_place` or :func:`format_stdin_to_stdout`.
516     """
517     try:
518         changed = Changed.NO
519         if not src.is_file() and str(src) == "-":
520             if format_stdin_to_stdout(fast=fast, write_back=write_back, mode=mode):
521                 changed = Changed.YES
522         else:
523             cache: Cache = {}
524             if write_back != WriteBack.DIFF:
525                 cache = read_cache(mode)
526                 res_src = src.resolve()
527                 if res_src in cache and cache[res_src] == get_cache_info(res_src):
528                     changed = Changed.CACHED
529             if changed is not Changed.CACHED and format_file_in_place(
530                 src, fast=fast, write_back=write_back, mode=mode
531             ):
532                 changed = Changed.YES
533             if (write_back is WriteBack.YES and changed is not Changed.CACHED) or (
534                 write_back is WriteBack.CHECK and changed is Changed.NO
535             ):
536                 write_cache(cache, [src], mode)
537         report.done(src, changed)
538     except Exception as exc:
539         report.failed(src, str(exc))
540
541
542 def reformat_many(
543     sources: Set[Path],
544     fast: bool,
545     write_back: WriteBack,
546     mode: FileMode,
547     report: "Report",
548 ) -> None:
549     """Reformat multiple files using a ProcessPoolExecutor."""
550     loop = asyncio.get_event_loop()
551     worker_count = os.cpu_count()
552     if sys.platform == "win32":
553         # Work around https://bugs.python.org/issue26903
554         worker_count = min(worker_count, 61)
555     executor = ProcessPoolExecutor(max_workers=worker_count)
556     try:
557         loop.run_until_complete(
558             schedule_formatting(
559                 sources=sources,
560                 fast=fast,
561                 write_back=write_back,
562                 mode=mode,
563                 report=report,
564                 loop=loop,
565                 executor=executor,
566             )
567         )
568     finally:
569         shutdown(loop)
570         executor.shutdown()
571
572
573 async def schedule_formatting(
574     sources: Set[Path],
575     fast: bool,
576     write_back: WriteBack,
577     mode: FileMode,
578     report: "Report",
579     loop: asyncio.AbstractEventLoop,
580     executor: Executor,
581 ) -> None:
582     """Run formatting of `sources` in parallel using the provided `executor`.
583
584     (Use ProcessPoolExecutors for actual parallelism.)
585
586     `write_back`, `fast`, and `mode` options are passed to
587     :func:`format_file_in_place`.
588     """
589     cache: Cache = {}
590     if write_back != WriteBack.DIFF:
591         cache = read_cache(mode)
592         sources, cached = filter_cached(cache, sources)
593         for src in sorted(cached):
594             report.done(src, Changed.CACHED)
595     if not sources:
596         return
597
598     cancelled = []
599     sources_to_cache = []
600     lock = None
601     if write_back == WriteBack.DIFF:
602         # For diff output, we need locks to ensure we don't interleave output
603         # from different processes.
604         manager = Manager()
605         lock = manager.Lock()
606     tasks = {
607         asyncio.ensure_future(
608             loop.run_in_executor(
609                 executor, format_file_in_place, src, fast, mode, write_back, lock
610             )
611         ): src
612         for src in sorted(sources)
613     }
614     pending: Iterable["asyncio.Future[bool]"] = tasks.keys()
615     try:
616         loop.add_signal_handler(signal.SIGINT, cancel, pending)
617         loop.add_signal_handler(signal.SIGTERM, cancel, pending)
618     except NotImplementedError:
619         # There are no good alternatives for these on Windows.
620         pass
621     while pending:
622         done, _ = await asyncio.wait(pending, return_when=asyncio.FIRST_COMPLETED)
623         for task in done:
624             src = tasks.pop(task)
625             if task.cancelled():
626                 cancelled.append(task)
627             elif task.exception():
628                 report.failed(src, str(task.exception()))
629             else:
630                 changed = Changed.YES if task.result() else Changed.NO
631                 # If the file was written back or was successfully checked as
632                 # well-formatted, store this information in the cache.
633                 if write_back is WriteBack.YES or (
634                     write_back is WriteBack.CHECK and changed is Changed.NO
635                 ):
636                     sources_to_cache.append(src)
637                 report.done(src, changed)
638     if cancelled:
639         await asyncio.gather(*cancelled, loop=loop, return_exceptions=True)
640     if sources_to_cache:
641         write_cache(cache, sources_to_cache, mode)
642
643
644 def format_file_in_place(
645     src: Path,
646     fast: bool,
647     mode: FileMode,
648     write_back: WriteBack = WriteBack.NO,
649     lock: Any = None,  # multiprocessing.Manager().Lock() is some crazy proxy
650 ) -> bool:
651     """Format file under `src` path. Return True if changed.
652
653     If `write_back` is DIFF, write a diff to stdout. If it is YES, write reformatted
654     code to the file.
655     `mode` and `fast` options are passed to :func:`format_file_contents`.
656     """
657     if src.suffix == ".pyi":
658         mode = replace(mode, is_pyi=True)
659
660     then = datetime.utcfromtimestamp(src.stat().st_mtime)
661     with open(src, "rb") as buf:
662         src_contents, encoding, newline = decode_bytes(buf.read())
663     try:
664         dst_contents = format_file_contents(src_contents, fast=fast, mode=mode)
665     except NothingChanged:
666         return False
667
668     if write_back == WriteBack.YES:
669         with open(src, "w", encoding=encoding, newline=newline) as f:
670             f.write(dst_contents)
671     elif write_back == WriteBack.DIFF:
672         now = datetime.utcnow()
673         src_name = f"{src}\t{then} +0000"
674         dst_name = f"{src}\t{now} +0000"
675         diff_contents = diff(src_contents, dst_contents, src_name, dst_name)
676
677         with lock or nullcontext():
678             f = io.TextIOWrapper(
679                 sys.stdout.buffer,
680                 encoding=encoding,
681                 newline=newline,
682                 write_through=True,
683             )
684             f.write(diff_contents)
685             f.detach()
686
687     return True
688
689
690 def format_stdin_to_stdout(
691     fast: bool, *, write_back: WriteBack = WriteBack.NO, mode: FileMode
692 ) -> bool:
693     """Format file on stdin. Return True if changed.
694
695     If `write_back` is YES, write reformatted code back to stdout. If it is DIFF,
696     write a diff to stdout. The `mode` argument is passed to
697     :func:`format_file_contents`.
698     """
699     then = datetime.utcnow()
700     src, encoding, newline = decode_bytes(sys.stdin.buffer.read())
701     dst = src
702     try:
703         dst = format_file_contents(src, fast=fast, mode=mode)
704         return True
705
706     except NothingChanged:
707         return False
708
709     finally:
710         f = io.TextIOWrapper(
711             sys.stdout.buffer, encoding=encoding, newline=newline, write_through=True
712         )
713         if write_back == WriteBack.YES:
714             f.write(dst)
715         elif write_back == WriteBack.DIFF:
716             now = datetime.utcnow()
717             src_name = f"STDIN\t{then} +0000"
718             dst_name = f"STDOUT\t{now} +0000"
719             f.write(diff(src, dst, src_name, dst_name))
720         f.detach()
721
722
723 def format_file_contents(
724     src_contents: str, *, fast: bool, mode: FileMode
725 ) -> FileContent:
726     """Reformat contents a file and return new contents.
727
728     If `fast` is False, additionally confirm that the reformatted code is
729     valid by calling :func:`assert_equivalent` and :func:`assert_stable` on it.
730     `mode` is passed to :func:`format_str`.
731     """
732     if src_contents.strip() == "":
733         raise NothingChanged
734
735     dst_contents = format_str(src_contents, mode=mode)
736     if src_contents == dst_contents:
737         raise NothingChanged
738
739     if not fast:
740         assert_equivalent(src_contents, dst_contents)
741         assert_stable(src_contents, dst_contents, mode=mode)
742     return dst_contents
743
744
745 def format_str(src_contents: str, *, mode: FileMode) -> FileContent:
746     """Reformat a string and return new contents.
747
748     `mode` determines formatting options, such as how many characters per line are
749     allowed.  Example:
750
751     >>> import black
752     >>> print(black.format_str("def f(arg:str='')->None:...", mode=FileMode()))
753     def f(arg: str = "") -> None:
754         ...
755
756     A more complex example:
757     >>> print(
758     ...   black.format_str(
759     ...     "def f(arg:str='')->None: hey",
760     ...     mode=black.FileMode(
761     ...       target_versions={black.TargetVersion.PY36},
762     ...       line_length=10,
763     ...       string_normalization=False,
764     ...       is_pyi=False,
765     ...     ),
766     ...   ),
767     ... )
768     def f(
769         arg: str = '',
770     ) -> None:
771         hey
772
773     """
774     src_node = lib2to3_parse(src_contents.lstrip(), mode.target_versions)
775     dst_contents = []
776     future_imports = get_future_imports(src_node)
777     if mode.target_versions:
778         versions = mode.target_versions
779     else:
780         versions = detect_target_versions(src_node)
781     normalize_fmt_off(src_node)
782     lines = LineGenerator(
783         remove_u_prefix="unicode_literals" in future_imports
784         or supports_feature(versions, Feature.UNICODE_LITERALS),
785         is_pyi=mode.is_pyi,
786         normalize_strings=mode.string_normalization,
787     )
788     elt = EmptyLineTracker(is_pyi=mode.is_pyi)
789     empty_line = Line()
790     after = 0
791     split_line_features = {
792         feature
793         for feature in {Feature.TRAILING_COMMA_IN_CALL, Feature.TRAILING_COMMA_IN_DEF}
794         if supports_feature(versions, feature)
795     }
796     for current_line in lines.visit(src_node):
797         dst_contents.append(str(empty_line) * after)
798         before, after = elt.maybe_empty_lines(current_line)
799         dst_contents.append(str(empty_line) * before)
800         for line in split_line(
801             current_line, line_length=mode.line_length, features=split_line_features
802         ):
803             dst_contents.append(str(line))
804     return "".join(dst_contents)
805
806
807 def decode_bytes(src: bytes) -> Tuple[FileContent, Encoding, NewLine]:
808     """Return a tuple of (decoded_contents, encoding, newline).
809
810     `newline` is either CRLF or LF but `decoded_contents` is decoded with
811     universal newlines (i.e. only contains LF).
812     """
813     srcbuf = io.BytesIO(src)
814     encoding, lines = tokenize.detect_encoding(srcbuf.readline)
815     if not lines:
816         return "", encoding, "\n"
817
818     newline = "\r\n" if b"\r\n" == lines[0][-2:] else "\n"
819     srcbuf.seek(0)
820     with io.TextIOWrapper(srcbuf, encoding) as tiow:
821         return tiow.read(), encoding, newline
822
823
824 def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]:
825     if not target_versions:
826         # No target_version specified, so try all grammars.
827         return [
828             # Python 3.7+
829             pygram.python_grammar_no_print_statement_no_exec_statement_async_keywords,
830             # Python 3.0-3.6
831             pygram.python_grammar_no_print_statement_no_exec_statement,
832             # Python 2.7 with future print_function import
833             pygram.python_grammar_no_print_statement,
834             # Python 2.7
835             pygram.python_grammar,
836         ]
837
838     if all(version.is_python2() for version in target_versions):
839         # Python 2-only code, so try Python 2 grammars.
840         return [
841             # Python 2.7 with future print_function import
842             pygram.python_grammar_no_print_statement,
843             # Python 2.7
844             pygram.python_grammar,
845         ]
846
847     # Python 3-compatible code, so only try Python 3 grammar.
848     grammars = []
849     # If we have to parse both, try to parse async as a keyword first
850     if not supports_feature(target_versions, Feature.ASYNC_IDENTIFIERS):
851         # Python 3.7+
852         grammars.append(
853             pygram.python_grammar_no_print_statement_no_exec_statement_async_keywords
854         )
855     if not supports_feature(target_versions, Feature.ASYNC_KEYWORDS):
856         # Python 3.0-3.6
857         grammars.append(pygram.python_grammar_no_print_statement_no_exec_statement)
858     # At least one of the above branches must have been taken, because every Python
859     # version has exactly one of the two 'ASYNC_*' flags
860     return grammars
861
862
863 def lib2to3_parse(src_txt: str, target_versions: Iterable[TargetVersion] = ()) -> Node:
864     """Given a string with source, return the lib2to3 Node."""
865     if src_txt[-1:] != "\n":
866         src_txt += "\n"
867
868     for grammar in get_grammars(set(target_versions)):
869         drv = driver.Driver(grammar, pytree.convert)
870         try:
871             result = drv.parse_string(src_txt, True)
872             break
873
874         except ParseError as pe:
875             lineno, column = pe.context[1]
876             lines = src_txt.splitlines()
877             try:
878                 faulty_line = lines[lineno - 1]
879             except IndexError:
880                 faulty_line = "<line number missing in source>"
881             exc = InvalidInput(f"Cannot parse: {lineno}:{column}: {faulty_line}")
882     else:
883         raise exc from None
884
885     if isinstance(result, Leaf):
886         result = Node(syms.file_input, [result])
887     return result
888
889
890 def lib2to3_unparse(node: Node) -> str:
891     """Given a lib2to3 node, return its string representation."""
892     code = str(node)
893     return code
894
895
896 T = TypeVar("T")
897
898
899 class Visitor(Generic[T]):
900     """Basic lib2to3 visitor that yields things of type `T` on `visit()`."""
901
902     def visit(self, node: LN) -> Iterator[T]:
903         """Main method to visit `node` and its children.
904
905         It tries to find a `visit_*()` method for the given `node.type`, like
906         `visit_simple_stmt` for Node objects or `visit_INDENT` for Leaf objects.
907         If no dedicated `visit_*()` method is found, chooses `visit_default()`
908         instead.
909
910         Then yields objects of type `T` from the selected visitor.
911         """
912         if node.type < 256:
913             name = token.tok_name[node.type]
914         else:
915             name = str(type_repr(node.type))
916         # We explicitly branch on whether a visitor exists (instead of
917         # using self.visit_default as the default arg to getattr) in order
918         # to save needing to create a bound method object and so mypyc can
919         # generate a native call to visit_default.
920         visitf = getattr(self, f"visit_{name}", None)
921         if visitf:
922             yield from visitf(node)
923         else:
924             yield from self.visit_default(node)
925
926     def visit_default(self, node: LN) -> Iterator[T]:
927         """Default `visit_*()` implementation. Recurses to children of `node`."""
928         if isinstance(node, Node):
929             for child in node.children:
930                 yield from self.visit(child)
931
932
933 @dataclass
934 class DebugVisitor(Visitor[T]):
935     tree_depth: int = 0
936
937     def visit_default(self, node: LN) -> Iterator[T]:
938         indent = " " * (2 * self.tree_depth)
939         if isinstance(node, Node):
940             _type = type_repr(node.type)
941             out(f"{indent}{_type}", fg="yellow")
942             self.tree_depth += 1
943             for child in node.children:
944                 yield from self.visit(child)
945
946             self.tree_depth -= 1
947             out(f"{indent}/{_type}", fg="yellow", bold=False)
948         else:
949             _type = token.tok_name.get(node.type, str(node.type))
950             out(f"{indent}{_type}", fg="blue", nl=False)
951             if node.prefix:
952                 # We don't have to handle prefixes for `Node` objects since
953                 # that delegates to the first child anyway.
954                 out(f" {node.prefix!r}", fg="green", bold=False, nl=False)
955             out(f" {node.value!r}", fg="blue", bold=False)
956
957     @classmethod
958     def show(cls, code: Union[str, Leaf, Node]) -> None:
959         """Pretty-print the lib2to3 AST of a given string of `code`.
960
961         Convenience method for debugging.
962         """
963         v: DebugVisitor[None] = DebugVisitor()
964         if isinstance(code, str):
965             code = lib2to3_parse(code)
966         list(v.visit(code))
967
968
969 WHITESPACE: Final = {token.DEDENT, token.INDENT, token.NEWLINE}
970 STATEMENT: Final = {
971     syms.if_stmt,
972     syms.while_stmt,
973     syms.for_stmt,
974     syms.try_stmt,
975     syms.except_clause,
976     syms.with_stmt,
977     syms.funcdef,
978     syms.classdef,
979 }
980 STANDALONE_COMMENT: Final = 153
981 token.tok_name[STANDALONE_COMMENT] = "STANDALONE_COMMENT"
982 LOGIC_OPERATORS: Final = {"and", "or"}
983 COMPARATORS: Final = {
984     token.LESS,
985     token.GREATER,
986     token.EQEQUAL,
987     token.NOTEQUAL,
988     token.LESSEQUAL,
989     token.GREATEREQUAL,
990 }
991 MATH_OPERATORS: Final = {
992     token.VBAR,
993     token.CIRCUMFLEX,
994     token.AMPER,
995     token.LEFTSHIFT,
996     token.RIGHTSHIFT,
997     token.PLUS,
998     token.MINUS,
999     token.STAR,
1000     token.SLASH,
1001     token.DOUBLESLASH,
1002     token.PERCENT,
1003     token.AT,
1004     token.TILDE,
1005     token.DOUBLESTAR,
1006 }
1007 STARS: Final = {token.STAR, token.DOUBLESTAR}
1008 VARARGS_SPECIALS: Final = STARS | {token.SLASH}
1009 VARARGS_PARENTS: Final = {
1010     syms.arglist,
1011     syms.argument,  # double star in arglist
1012     syms.trailer,  # single argument to call
1013     syms.typedargslist,
1014     syms.varargslist,  # lambdas
1015 }
1016 UNPACKING_PARENTS: Final = {
1017     syms.atom,  # single element of a list or set literal
1018     syms.dictsetmaker,
1019     syms.listmaker,
1020     syms.testlist_gexp,
1021     syms.testlist_star_expr,
1022 }
1023 TEST_DESCENDANTS: Final = {
1024     syms.test,
1025     syms.lambdef,
1026     syms.or_test,
1027     syms.and_test,
1028     syms.not_test,
1029     syms.comparison,
1030     syms.star_expr,
1031     syms.expr,
1032     syms.xor_expr,
1033     syms.and_expr,
1034     syms.shift_expr,
1035     syms.arith_expr,
1036     syms.trailer,
1037     syms.term,
1038     syms.power,
1039 }
1040 ASSIGNMENTS: Final = {
1041     "=",
1042     "+=",
1043     "-=",
1044     "*=",
1045     "@=",
1046     "/=",
1047     "%=",
1048     "&=",
1049     "|=",
1050     "^=",
1051     "<<=",
1052     ">>=",
1053     "**=",
1054     "//=",
1055 }
1056 COMPREHENSION_PRIORITY: Final = 20
1057 COMMA_PRIORITY: Final = 18
1058 TERNARY_PRIORITY: Final = 16
1059 LOGIC_PRIORITY: Final = 14
1060 STRING_PRIORITY: Final = 12
1061 COMPARATOR_PRIORITY: Final = 10
1062 MATH_PRIORITIES: Final = {
1063     token.VBAR: 9,
1064     token.CIRCUMFLEX: 8,
1065     token.AMPER: 7,
1066     token.LEFTSHIFT: 6,
1067     token.RIGHTSHIFT: 6,
1068     token.PLUS: 5,
1069     token.MINUS: 5,
1070     token.STAR: 4,
1071     token.SLASH: 4,
1072     token.DOUBLESLASH: 4,
1073     token.PERCENT: 4,
1074     token.AT: 4,
1075     token.TILDE: 3,
1076     token.DOUBLESTAR: 2,
1077 }
1078 DOT_PRIORITY: Final = 1
1079
1080
1081 @dataclass
1082 class BracketTracker:
1083     """Keeps track of brackets on a line."""
1084
1085     depth: int = 0
1086     bracket_match: Dict[Tuple[Depth, NodeType], Leaf] = field(default_factory=dict)
1087     delimiters: Dict[LeafID, Priority] = field(default_factory=dict)
1088     previous: Optional[Leaf] = None
1089     _for_loop_depths: List[int] = field(default_factory=list)
1090     _lambda_argument_depths: List[int] = field(default_factory=list)
1091
1092     def mark(self, leaf: Leaf) -> None:
1093         """Mark `leaf` with bracket-related metadata. Keep track of delimiters.
1094
1095         All leaves receive an int `bracket_depth` field that stores how deep
1096         within brackets a given leaf is. 0 means there are no enclosing brackets
1097         that started on this line.
1098
1099         If a leaf is itself a closing bracket, it receives an `opening_bracket`
1100         field that it forms a pair with. This is a one-directional link to
1101         avoid reference cycles.
1102
1103         If a leaf is a delimiter (a token on which Black can split the line if
1104         needed) and it's on depth 0, its `id()` is stored in the tracker's
1105         `delimiters` field.
1106         """
1107         if leaf.type == token.COMMENT:
1108             return
1109
1110         self.maybe_decrement_after_for_loop_variable(leaf)
1111         self.maybe_decrement_after_lambda_arguments(leaf)
1112         if leaf.type in CLOSING_BRACKETS:
1113             self.depth -= 1
1114             opening_bracket = self.bracket_match.pop((self.depth, leaf.type))
1115             leaf.opening_bracket = opening_bracket
1116         leaf.bracket_depth = self.depth
1117         if self.depth == 0:
1118             delim = is_split_before_delimiter(leaf, self.previous)
1119             if delim and self.previous is not None:
1120                 self.delimiters[id(self.previous)] = delim
1121             else:
1122                 delim = is_split_after_delimiter(leaf, self.previous)
1123                 if delim:
1124                     self.delimiters[id(leaf)] = delim
1125         if leaf.type in OPENING_BRACKETS:
1126             self.bracket_match[self.depth, BRACKET[leaf.type]] = leaf
1127             self.depth += 1
1128         self.previous = leaf
1129         self.maybe_increment_lambda_arguments(leaf)
1130         self.maybe_increment_for_loop_variable(leaf)
1131
1132     def any_open_brackets(self) -> bool:
1133         """Return True if there is an yet unmatched open bracket on the line."""
1134         return bool(self.bracket_match)
1135
1136     def max_delimiter_priority(self, exclude: Iterable[LeafID] = ()) -> Priority:
1137         """Return the highest priority of a delimiter found on the line.
1138
1139         Values are consistent with what `is_split_*_delimiter()` return.
1140         Raises ValueError on no delimiters.
1141         """
1142         return max(v for k, v in self.delimiters.items() if k not in exclude)
1143
1144     def delimiter_count_with_priority(self, priority: Priority = 0) -> int:
1145         """Return the number of delimiters with the given `priority`.
1146
1147         If no `priority` is passed, defaults to max priority on the line.
1148         """
1149         if not self.delimiters:
1150             return 0
1151
1152         priority = priority or self.max_delimiter_priority()
1153         return sum(1 for p in self.delimiters.values() if p == priority)
1154
1155     def maybe_increment_for_loop_variable(self, leaf: Leaf) -> bool:
1156         """In a for loop, or comprehension, the variables are often unpacks.
1157
1158         To avoid splitting on the comma in this situation, increase the depth of
1159         tokens between `for` and `in`.
1160         """
1161         if leaf.type == token.NAME and leaf.value == "for":
1162             self.depth += 1
1163             self._for_loop_depths.append(self.depth)
1164             return True
1165
1166         return False
1167
1168     def maybe_decrement_after_for_loop_variable(self, leaf: Leaf) -> bool:
1169         """See `maybe_increment_for_loop_variable` above for explanation."""
1170         if (
1171             self._for_loop_depths
1172             and self._for_loop_depths[-1] == self.depth
1173             and leaf.type == token.NAME
1174             and leaf.value == "in"
1175         ):
1176             self.depth -= 1
1177             self._for_loop_depths.pop()
1178             return True
1179
1180         return False
1181
1182     def maybe_increment_lambda_arguments(self, leaf: Leaf) -> bool:
1183         """In a lambda expression, there might be more than one argument.
1184
1185         To avoid splitting on the comma in this situation, increase the depth of
1186         tokens between `lambda` and `:`.
1187         """
1188         if leaf.type == token.NAME and leaf.value == "lambda":
1189             self.depth += 1
1190             self._lambda_argument_depths.append(self.depth)
1191             return True
1192
1193         return False
1194
1195     def maybe_decrement_after_lambda_arguments(self, leaf: Leaf) -> bool:
1196         """See `maybe_increment_lambda_arguments` above for explanation."""
1197         if (
1198             self._lambda_argument_depths
1199             and self._lambda_argument_depths[-1] == self.depth
1200             and leaf.type == token.COLON
1201         ):
1202             self.depth -= 1
1203             self._lambda_argument_depths.pop()
1204             return True
1205
1206         return False
1207
1208     def get_open_lsqb(self) -> Optional[Leaf]:
1209         """Return the most recent opening square bracket (if any)."""
1210         return self.bracket_match.get((self.depth - 1, token.RSQB))
1211
1212
1213 @dataclass
1214 class Line:
1215     """Holds leaves and comments. Can be printed with `str(line)`."""
1216
1217     depth: int = 0
1218     leaves: List[Leaf] = field(default_factory=list)
1219     # keys ordered like `leaves`
1220     comments: Dict[LeafID, List[Leaf]] = field(default_factory=dict)
1221     bracket_tracker: BracketTracker = field(default_factory=BracketTracker)
1222     inside_brackets: bool = False
1223     should_explode: bool = False
1224
1225     def append(self, leaf: Leaf, preformatted: bool = False) -> None:
1226         """Add a new `leaf` to the end of the line.
1227
1228         Unless `preformatted` is True, the `leaf` will receive a new consistent
1229         whitespace prefix and metadata applied by :class:`BracketTracker`.
1230         Trailing commas are maybe removed, unpacked for loop variables are
1231         demoted from being delimiters.
1232
1233         Inline comments are put aside.
1234         """
1235         has_value = leaf.type in BRACKETS or bool(leaf.value.strip())
1236         if not has_value:
1237             return
1238
1239         if token.COLON == leaf.type and self.is_class_paren_empty:
1240             del self.leaves[-2:]
1241         if self.leaves and not preformatted:
1242             # Note: at this point leaf.prefix should be empty except for
1243             # imports, for which we only preserve newlines.
1244             leaf.prefix += whitespace(
1245                 leaf, complex_subscript=self.is_complex_subscript(leaf)
1246             )
1247         if self.inside_brackets or not preformatted:
1248             self.bracket_tracker.mark(leaf)
1249             self.maybe_remove_trailing_comma(leaf)
1250         if not self.append_comment(leaf):
1251             self.leaves.append(leaf)
1252
1253     def append_safe(self, leaf: Leaf, preformatted: bool = False) -> None:
1254         """Like :func:`append()` but disallow invalid standalone comment structure.
1255
1256         Raises ValueError when any `leaf` is appended after a standalone comment
1257         or when a standalone comment is not the first leaf on the line.
1258         """
1259         if self.bracket_tracker.depth == 0:
1260             if self.is_comment:
1261                 raise ValueError("cannot append to standalone comments")
1262
1263             if self.leaves and leaf.type == STANDALONE_COMMENT:
1264                 raise ValueError(
1265                     "cannot append standalone comments to a populated line"
1266                 )
1267
1268         self.append(leaf, preformatted=preformatted)
1269
1270     @property
1271     def is_comment(self) -> bool:
1272         """Is this line a standalone comment?"""
1273         return len(self.leaves) == 1 and self.leaves[0].type == STANDALONE_COMMENT
1274
1275     @property
1276     def is_decorator(self) -> bool:
1277         """Is this line a decorator?"""
1278         return bool(self) and self.leaves[0].type == token.AT
1279
1280     @property
1281     def is_import(self) -> bool:
1282         """Is this an import line?"""
1283         return bool(self) and is_import(self.leaves[0])
1284
1285     @property
1286     def is_class(self) -> bool:
1287         """Is this line a class definition?"""
1288         return (
1289             bool(self)
1290             and self.leaves[0].type == token.NAME
1291             and self.leaves[0].value == "class"
1292         )
1293
1294     @property
1295     def is_stub_class(self) -> bool:
1296         """Is this line a class definition with a body consisting only of "..."?"""
1297         return self.is_class and self.leaves[-3:] == [
1298             Leaf(token.DOT, ".") for _ in range(3)
1299         ]
1300
1301     @property
1302     def is_collection_with_optional_trailing_comma(self) -> bool:
1303         """Is this line a collection literal with a trailing comma that's optional?
1304
1305         Note that the trailing comma in a 1-tuple is not optional.
1306         """
1307         if not self.leaves or len(self.leaves) < 4:
1308             return False
1309
1310         # Look for and address a trailing colon.
1311         if self.leaves[-1].type == token.COLON:
1312             closer = self.leaves[-2]
1313             close_index = -2
1314         else:
1315             closer = self.leaves[-1]
1316             close_index = -1
1317         if closer.type not in CLOSING_BRACKETS or self.inside_brackets:
1318             return False
1319
1320         if closer.type == token.RPAR:
1321             # Tuples require an extra check, because if there's only
1322             # one element in the tuple removing the comma unmakes the
1323             # tuple.
1324             #
1325             # We also check for parens before looking for the trailing
1326             # comma because in some cases (eg assigning a dict
1327             # literal) the literal gets wrapped in temporary parens
1328             # during parsing. This case is covered by the
1329             # collections.py test data.
1330             opener = closer.opening_bracket
1331             for _open_index, leaf in enumerate(self.leaves):
1332                 if leaf is opener:
1333                     break
1334
1335             else:
1336                 # Couldn't find the matching opening paren, play it safe.
1337                 return False
1338
1339             commas = 0
1340             comma_depth = self.leaves[close_index - 1].bracket_depth
1341             for leaf in self.leaves[_open_index + 1 : close_index]:
1342                 if leaf.bracket_depth == comma_depth and leaf.type == token.COMMA:
1343                     commas += 1
1344             if commas > 1:
1345                 # We haven't looked yet for the trailing comma because
1346                 # we might also have caught noop parens.
1347                 return self.leaves[close_index - 1].type == token.COMMA
1348
1349             elif commas == 1:
1350                 return False  # it's either a one-tuple or didn't have a trailing comma
1351
1352             if self.leaves[close_index - 1].type in CLOSING_BRACKETS:
1353                 close_index -= 1
1354                 closer = self.leaves[close_index]
1355                 if closer.type == token.RPAR:
1356                     # TODO: this is a gut feeling. Will we ever see this?
1357                     return False
1358
1359         if self.leaves[close_index - 1].type != token.COMMA:
1360             return False
1361
1362         return True
1363
1364     @property
1365     def is_def(self) -> bool:
1366         """Is this a function definition? (Also returns True for async defs.)"""
1367         try:
1368             first_leaf = self.leaves[0]
1369         except IndexError:
1370             return False
1371
1372         try:
1373             second_leaf: Optional[Leaf] = self.leaves[1]
1374         except IndexError:
1375             second_leaf = None
1376         return (first_leaf.type == token.NAME and first_leaf.value == "def") or (
1377             first_leaf.type == token.ASYNC
1378             and second_leaf is not None
1379             and second_leaf.type == token.NAME
1380             and second_leaf.value == "def"
1381         )
1382
1383     @property
1384     def is_class_paren_empty(self) -> bool:
1385         """Is this a class with no base classes but using parentheses?
1386
1387         Those are unnecessary and should be removed.
1388         """
1389         return (
1390             bool(self)
1391             and len(self.leaves) == 4
1392             and self.is_class
1393             and self.leaves[2].type == token.LPAR
1394             and self.leaves[2].value == "("
1395             and self.leaves[3].type == token.RPAR
1396             and self.leaves[3].value == ")"
1397         )
1398
1399     @property
1400     def is_triple_quoted_string(self) -> bool:
1401         """Is the line a triple quoted string?"""
1402         return (
1403             bool(self)
1404             and self.leaves[0].type == token.STRING
1405             and self.leaves[0].value.startswith(('"""', "'''"))
1406         )
1407
1408     def contains_standalone_comments(self, depth_limit: int = sys.maxsize) -> bool:
1409         """If so, needs to be split before emitting."""
1410         for leaf in self.leaves:
1411             if leaf.type == STANDALONE_COMMENT and leaf.bracket_depth <= depth_limit:
1412                 return True
1413
1414         return False
1415
1416     def contains_uncollapsable_type_comments(self) -> bool:
1417         ignored_ids = set()
1418         try:
1419             last_leaf = self.leaves[-1]
1420             ignored_ids.add(id(last_leaf))
1421             if last_leaf.type == token.COMMA or (
1422                 last_leaf.type == token.RPAR and not last_leaf.value
1423             ):
1424                 # When trailing commas or optional parens are inserted by Black for
1425                 # consistency, comments after the previous last element are not moved
1426                 # (they don't have to, rendering will still be correct).  So we ignore
1427                 # trailing commas and invisible.
1428                 last_leaf = self.leaves[-2]
1429                 ignored_ids.add(id(last_leaf))
1430         except IndexError:
1431             return False
1432
1433         # A type comment is uncollapsable if it is attached to a leaf
1434         # that isn't at the end of the line (since that could cause it
1435         # to get associated to a different argument) or if there are
1436         # comments before it (since that could cause it to get hidden
1437         # behind a comment.
1438         comment_seen = False
1439         for leaf_id, comments in self.comments.items():
1440             for comment in comments:
1441                 if is_type_comment(comment):
1442                     if comment_seen or (
1443                         not is_type_comment(comment, " ignore")
1444                         and leaf_id not in ignored_ids
1445                     ):
1446                         return True
1447
1448                 comment_seen = True
1449
1450         return False
1451
1452     def contains_unsplittable_type_ignore(self) -> bool:
1453         if not self.leaves:
1454             return False
1455
1456         # If a 'type: ignore' is attached to the end of a line, we
1457         # can't split the line, because we can't know which of the
1458         # subexpressions the ignore was meant to apply to.
1459         #
1460         # We only want this to apply to actual physical lines from the
1461         # original source, though: we don't want the presence of a
1462         # 'type: ignore' at the end of a multiline expression to
1463         # justify pushing it all onto one line. Thus we
1464         # (unfortunately) need to check the actual source lines and
1465         # only report an unsplittable 'type: ignore' if this line was
1466         # one line in the original code.
1467
1468         # Grab the first and last line numbers, skipping generated leaves
1469         first_line = next((l.lineno for l in self.leaves if l.lineno != 0), 0)
1470         last_line = next((l.lineno for l in reversed(self.leaves) if l.lineno != 0), 0)
1471
1472         if first_line == last_line:
1473             # We look at the last two leaves since a comma or an
1474             # invisible paren could have been added at the end of the
1475             # line.
1476             for node in self.leaves[-2:]:
1477                 for comment in self.comments.get(id(node), []):
1478                     if is_type_comment(comment, " ignore"):
1479                         return True
1480
1481         return False
1482
1483     def contains_multiline_strings(self) -> bool:
1484         return any(is_multiline_string(leaf) for leaf in self.leaves)
1485
1486     def maybe_remove_trailing_comma(self, closing: Leaf) -> bool:
1487         """Remove trailing comma if there is one and it's safe."""
1488         if not (self.leaves and self.leaves[-1].type == token.COMMA):
1489             return False
1490
1491         # We remove trailing commas only in the case of importing a
1492         # single name from a module.
1493         if not (
1494             self.leaves
1495             and self.is_import
1496             and len(self.leaves) > 4
1497             and self.leaves[-1].type == token.COMMA
1498             and closing.type in CLOSING_BRACKETS
1499             and self.leaves[-4].type == token.NAME
1500             and (
1501                 # regular `from foo import bar,`
1502                 self.leaves[-4].value == "import"
1503                 # `from foo import (bar as baz,)
1504                 or (
1505                     len(self.leaves) > 6
1506                     and self.leaves[-6].value == "import"
1507                     and self.leaves[-3].value == "as"
1508                 )
1509                 # `from foo import bar as baz,`
1510                 or (
1511                     len(self.leaves) > 5
1512                     and self.leaves[-5].value == "import"
1513                     and self.leaves[-3].value == "as"
1514                 )
1515             )
1516             and closing.type == token.RPAR
1517         ):
1518             return False
1519
1520         self.remove_trailing_comma()
1521         return True
1522
1523     def append_comment(self, comment: Leaf) -> bool:
1524         """Add an inline or standalone comment to the line."""
1525         if (
1526             comment.type == STANDALONE_COMMENT
1527             and self.bracket_tracker.any_open_brackets()
1528         ):
1529             comment.prefix = ""
1530             return False
1531
1532         if comment.type != token.COMMENT:
1533             return False
1534
1535         if not self.leaves:
1536             comment.type = STANDALONE_COMMENT
1537             comment.prefix = ""
1538             return False
1539
1540         last_leaf = self.leaves[-1]
1541         if (
1542             last_leaf.type == token.RPAR
1543             and not last_leaf.value
1544             and last_leaf.parent
1545             and len(list(last_leaf.parent.leaves())) <= 3
1546             and not is_type_comment(comment)
1547         ):
1548             # Comments on an optional parens wrapping a single leaf should belong to
1549             # the wrapped node except if it's a type comment. Pinning the comment like
1550             # this avoids unstable formatting caused by comment migration.
1551             if len(self.leaves) < 2:
1552                 comment.type = STANDALONE_COMMENT
1553                 comment.prefix = ""
1554                 return False
1555
1556             last_leaf = self.leaves[-2]
1557         self.comments.setdefault(id(last_leaf), []).append(comment)
1558         return True
1559
1560     def comments_after(self, leaf: Leaf) -> List[Leaf]:
1561         """Generate comments that should appear directly after `leaf`."""
1562         return self.comments.get(id(leaf), [])
1563
1564     def remove_trailing_comma(self) -> None:
1565         """Remove the trailing comma and moves the comments attached to it."""
1566         trailing_comma = self.leaves.pop()
1567         trailing_comma_comments = self.comments.pop(id(trailing_comma), [])
1568         self.comments.setdefault(id(self.leaves[-1]), []).extend(
1569             trailing_comma_comments
1570         )
1571
1572     def is_complex_subscript(self, leaf: Leaf) -> bool:
1573         """Return True iff `leaf` is part of a slice with non-trivial exprs."""
1574         open_lsqb = self.bracket_tracker.get_open_lsqb()
1575         if open_lsqb is None:
1576             return False
1577
1578         subscript_start = open_lsqb.next_sibling
1579
1580         if isinstance(subscript_start, Node):
1581             if subscript_start.type == syms.listmaker:
1582                 return False
1583
1584             if subscript_start.type == syms.subscriptlist:
1585                 subscript_start = child_towards(subscript_start, leaf)
1586         return subscript_start is not None and any(
1587             n.type in TEST_DESCENDANTS for n in subscript_start.pre_order()
1588         )
1589
1590     def __str__(self) -> str:
1591         """Render the line."""
1592         if not self:
1593             return "\n"
1594
1595         indent = "    " * self.depth
1596         leaves = iter(self.leaves)
1597         first = next(leaves)
1598         res = f"{first.prefix}{indent}{first.value}"
1599         for leaf in leaves:
1600             res += str(leaf)
1601         for comment in itertools.chain.from_iterable(self.comments.values()):
1602             res += str(comment)
1603         return res + "\n"
1604
1605     def __bool__(self) -> bool:
1606         """Return True if the line has leaves or comments."""
1607         return bool(self.leaves or self.comments)
1608
1609
1610 @dataclass
1611 class EmptyLineTracker:
1612     """Provides a stateful method that returns the number of potential extra
1613     empty lines needed before and after the currently processed line.
1614
1615     Note: this tracker works on lines that haven't been split yet.  It assumes
1616     the prefix of the first leaf consists of optional newlines.  Those newlines
1617     are consumed by `maybe_empty_lines()` and included in the computation.
1618     """
1619
1620     is_pyi: bool = False
1621     previous_line: Optional[Line] = None
1622     previous_after: int = 0
1623     previous_defs: List[int] = field(default_factory=list)
1624
1625     def maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
1626         """Return the number of extra empty lines before and after the `current_line`.
1627
1628         This is for separating `def`, `async def` and `class` with extra empty
1629         lines (two on module-level).
1630         """
1631         before, after = self._maybe_empty_lines(current_line)
1632         before = (
1633             # Black should not insert empty lines at the beginning
1634             # of the file
1635             0
1636             if self.previous_line is None
1637             else before - self.previous_after
1638         )
1639         self.previous_after = after
1640         self.previous_line = current_line
1641         return before, after
1642
1643     def _maybe_empty_lines(self, current_line: Line) -> Tuple[int, int]:
1644         max_allowed = 1
1645         if current_line.depth == 0:
1646             max_allowed = 1 if self.is_pyi else 2
1647         if current_line.leaves:
1648             # Consume the first leaf's extra newlines.
1649             first_leaf = current_line.leaves[0]
1650             before = first_leaf.prefix.count("\n")
1651             before = min(before, max_allowed)
1652             first_leaf.prefix = ""
1653         else:
1654             before = 0
1655         depth = current_line.depth
1656         while self.previous_defs and self.previous_defs[-1] >= depth:
1657             self.previous_defs.pop()
1658             if self.is_pyi:
1659                 before = 0 if depth else 1
1660             else:
1661                 before = 1 if depth else 2
1662         if current_line.is_decorator or current_line.is_def or current_line.is_class:
1663             return self._maybe_empty_lines_for_class_or_def(current_line, before)
1664
1665         if (
1666             self.previous_line
1667             and self.previous_line.is_import
1668             and not current_line.is_import
1669             and depth == self.previous_line.depth
1670         ):
1671             return (before or 1), 0
1672
1673         if (
1674             self.previous_line
1675             and self.previous_line.is_class
1676             and current_line.is_triple_quoted_string
1677         ):
1678             return before, 1
1679
1680         return before, 0
1681
1682     def _maybe_empty_lines_for_class_or_def(
1683         self, current_line: Line, before: int
1684     ) -> Tuple[int, int]:
1685         if not current_line.is_decorator:
1686             self.previous_defs.append(current_line.depth)
1687         if self.previous_line is None:
1688             # Don't insert empty lines before the first line in the file.
1689             return 0, 0
1690
1691         if self.previous_line.is_decorator:
1692             return 0, 0
1693
1694         if self.previous_line.depth < current_line.depth and (
1695             self.previous_line.is_class or self.previous_line.is_def
1696         ):
1697             return 0, 0
1698
1699         if (
1700             self.previous_line.is_comment
1701             and self.previous_line.depth == current_line.depth
1702             and before == 0
1703         ):
1704             return 0, 0
1705
1706         if self.is_pyi:
1707             if self.previous_line.depth > current_line.depth:
1708                 newlines = 1
1709             elif current_line.is_class or self.previous_line.is_class:
1710                 if current_line.is_stub_class and self.previous_line.is_stub_class:
1711                     # No blank line between classes with an empty body
1712                     newlines = 0
1713                 else:
1714                     newlines = 1
1715             elif current_line.is_def and not self.previous_line.is_def:
1716                 # Blank line between a block of functions and a block of non-functions
1717                 newlines = 1
1718             else:
1719                 newlines = 0
1720         else:
1721             newlines = 2
1722         if current_line.depth and newlines:
1723             newlines -= 1
1724         return newlines, 0
1725
1726
1727 @dataclass
1728 class LineGenerator(Visitor[Line]):
1729     """Generates reformatted Line objects.  Empty lines are not emitted.
1730
1731     Note: destroys the tree it's visiting by mutating prefixes of its leaves
1732     in ways that will no longer stringify to valid Python code on the tree.
1733     """
1734
1735     is_pyi: bool = False
1736     normalize_strings: bool = True
1737     current_line: Line = field(default_factory=Line)
1738     remove_u_prefix: bool = False
1739
1740     def line(self, indent: int = 0) -> Iterator[Line]:
1741         """Generate a line.
1742
1743         If the line is empty, only emit if it makes sense.
1744         If the line is too long, split it first and then generate.
1745
1746         If any lines were generated, set up a new current_line.
1747         """
1748         if not self.current_line:
1749             self.current_line.depth += indent
1750             return  # Line is empty, don't emit. Creating a new one unnecessary.
1751
1752         complete_line = self.current_line
1753         self.current_line = Line(depth=complete_line.depth + indent)
1754         yield complete_line
1755
1756     def visit_default(self, node: LN) -> Iterator[Line]:
1757         """Default `visit_*()` implementation. Recurses to children of `node`."""
1758         if isinstance(node, Leaf):
1759             any_open_brackets = self.current_line.bracket_tracker.any_open_brackets()
1760             for comment in generate_comments(node):
1761                 if any_open_brackets:
1762                     # any comment within brackets is subject to splitting
1763                     self.current_line.append(comment)
1764                 elif comment.type == token.COMMENT:
1765                     # regular trailing comment
1766                     self.current_line.append(comment)
1767                     yield from self.line()
1768
1769                 else:
1770                     # regular standalone comment
1771                     yield from self.line()
1772
1773                     self.current_line.append(comment)
1774                     yield from self.line()
1775
1776             normalize_prefix(node, inside_brackets=any_open_brackets)
1777             if self.normalize_strings and node.type == token.STRING:
1778                 normalize_string_prefix(node, remove_u_prefix=self.remove_u_prefix)
1779                 normalize_string_quotes(node)
1780             if node.type == token.NUMBER:
1781                 normalize_numeric_literal(node)
1782             if node.type not in WHITESPACE:
1783                 self.current_line.append(node)
1784         yield from super().visit_default(node)
1785
1786     def visit_INDENT(self, node: Leaf) -> Iterator[Line]:
1787         """Increase indentation level, maybe yield a line."""
1788         # In blib2to3 INDENT never holds comments.
1789         yield from self.line(+1)
1790         yield from self.visit_default(node)
1791
1792     def visit_DEDENT(self, node: Leaf) -> Iterator[Line]:
1793         """Decrease indentation level, maybe yield a line."""
1794         # The current line might still wait for trailing comments.  At DEDENT time
1795         # there won't be any (they would be prefixes on the preceding NEWLINE).
1796         # Emit the line then.
1797         yield from self.line()
1798
1799         # While DEDENT has no value, its prefix may contain standalone comments
1800         # that belong to the current indentation level.  Get 'em.
1801         yield from self.visit_default(node)
1802
1803         # Finally, emit the dedent.
1804         yield from self.line(-1)
1805
1806     def visit_stmt(
1807         self, node: Node, keywords: Set[str], parens: Set[str]
1808     ) -> Iterator[Line]:
1809         """Visit a statement.
1810
1811         This implementation is shared for `if`, `while`, `for`, `try`, `except`,
1812         `def`, `with`, `class`, `assert` and assignments.
1813
1814         The relevant Python language `keywords` for a given statement will be
1815         NAME leaves within it. This methods puts those on a separate line.
1816
1817         `parens` holds a set of string leaf values immediately after which
1818         invisible parens should be put.
1819         """
1820         normalize_invisible_parens(node, parens_after=parens)
1821         for child in node.children:
1822             if child.type == token.NAME and child.value in keywords:  # type: ignore
1823                 yield from self.line()
1824
1825             yield from self.visit(child)
1826
1827     def visit_suite(self, node: Node) -> Iterator[Line]:
1828         """Visit a suite."""
1829         if self.is_pyi and is_stub_suite(node):
1830             yield from self.visit(node.children[2])
1831         else:
1832             yield from self.visit_default(node)
1833
1834     def visit_simple_stmt(self, node: Node) -> Iterator[Line]:
1835         """Visit a statement without nested statements."""
1836         is_suite_like = node.parent and node.parent.type in STATEMENT
1837         if is_suite_like:
1838             if self.is_pyi and is_stub_body(node):
1839                 yield from self.visit_default(node)
1840             else:
1841                 yield from self.line(+1)
1842                 yield from self.visit_default(node)
1843                 yield from self.line(-1)
1844
1845         else:
1846             if not self.is_pyi or not node.parent or not is_stub_suite(node.parent):
1847                 yield from self.line()
1848             yield from self.visit_default(node)
1849
1850     def visit_async_stmt(self, node: Node) -> Iterator[Line]:
1851         """Visit `async def`, `async for`, `async with`."""
1852         yield from self.line()
1853
1854         children = iter(node.children)
1855         for child in children:
1856             yield from self.visit(child)
1857
1858             if child.type == token.ASYNC:
1859                 break
1860
1861         internal_stmt = next(children)
1862         for child in internal_stmt.children:
1863             yield from self.visit(child)
1864
1865     def visit_decorators(self, node: Node) -> Iterator[Line]:
1866         """Visit decorators."""
1867         for child in node.children:
1868             yield from self.line()
1869             yield from self.visit(child)
1870
1871     def visit_SEMI(self, leaf: Leaf) -> Iterator[Line]:
1872         """Remove a semicolon and put the other statement on a separate line."""
1873         yield from self.line()
1874
1875     def visit_ENDMARKER(self, leaf: Leaf) -> Iterator[Line]:
1876         """End of file. Process outstanding comments and end with a newline."""
1877         yield from self.visit_default(leaf)
1878         yield from self.line()
1879
1880     def visit_STANDALONE_COMMENT(self, leaf: Leaf) -> Iterator[Line]:
1881         if not self.current_line.bracket_tracker.any_open_brackets():
1882             yield from self.line()
1883         yield from self.visit_default(leaf)
1884
1885     def visit_factor(self, node: Node) -> Iterator[Line]:
1886         """Force parentheses between a unary op and a binary power:
1887
1888         -2 ** 8 -> -(2 ** 8)
1889         """
1890         _operator, operand = node.children
1891         if (
1892             operand.type == syms.power
1893             and len(operand.children) == 3
1894             and operand.children[1].type == token.DOUBLESTAR
1895         ):
1896             lpar = Leaf(token.LPAR, "(")
1897             rpar = Leaf(token.RPAR, ")")
1898             index = operand.remove() or 0
1899             node.insert_child(index, Node(syms.atom, [lpar, operand, rpar]))
1900         yield from self.visit_default(node)
1901
1902     def __post_init__(self) -> None:
1903         """You are in a twisty little maze of passages."""
1904         v = self.visit_stmt
1905         Ø: Set[str] = set()
1906         self.visit_assert_stmt = partial(v, keywords={"assert"}, parens={"assert", ","})
1907         self.visit_if_stmt = partial(
1908             v, keywords={"if", "else", "elif"}, parens={"if", "elif"}
1909         )
1910         self.visit_while_stmt = partial(v, keywords={"while", "else"}, parens={"while"})
1911         self.visit_for_stmt = partial(v, keywords={"for", "else"}, parens={"for", "in"})
1912         self.visit_try_stmt = partial(
1913             v, keywords={"try", "except", "else", "finally"}, parens=Ø
1914         )
1915         self.visit_except_clause = partial(v, keywords={"except"}, parens=Ø)
1916         self.visit_with_stmt = partial(v, keywords={"with"}, parens=Ø)
1917         self.visit_funcdef = partial(v, keywords={"def"}, parens=Ø)
1918         self.visit_classdef = partial(v, keywords={"class"}, parens=Ø)
1919         self.visit_expr_stmt = partial(v, keywords=Ø, parens=ASSIGNMENTS)
1920         self.visit_return_stmt = partial(v, keywords={"return"}, parens={"return"})
1921         self.visit_import_from = partial(v, keywords=Ø, parens={"import"})
1922         self.visit_del_stmt = partial(v, keywords=Ø, parens={"del"})
1923         self.visit_async_funcdef = self.visit_async_stmt
1924         self.visit_decorated = self.visit_decorators
1925
1926
1927 IMPLICIT_TUPLE = {syms.testlist, syms.testlist_star_expr, syms.exprlist}
1928 BRACKET = {token.LPAR: token.RPAR, token.LSQB: token.RSQB, token.LBRACE: token.RBRACE}
1929 OPENING_BRACKETS = set(BRACKET.keys())
1930 CLOSING_BRACKETS = set(BRACKET.values())
1931 BRACKETS = OPENING_BRACKETS | CLOSING_BRACKETS
1932 ALWAYS_NO_SPACE = CLOSING_BRACKETS | {token.COMMA, STANDALONE_COMMENT}
1933
1934
1935 def whitespace(leaf: Leaf, *, complex_subscript: bool) -> str:  # noqa: C901
1936     """Return whitespace prefix if needed for the given `leaf`.
1937
1938     `complex_subscript` signals whether the given leaf is part of a subscription
1939     which has non-trivial arguments, like arithmetic expressions or function calls.
1940     """
1941     NO = ""
1942     SPACE = " "
1943     DOUBLESPACE = "  "
1944     t = leaf.type
1945     p = leaf.parent
1946     v = leaf.value
1947     if t in ALWAYS_NO_SPACE:
1948         return NO
1949
1950     if t == token.COMMENT:
1951         return DOUBLESPACE
1952
1953     assert p is not None, f"INTERNAL ERROR: hand-made leaf without parent: {leaf!r}"
1954     if t == token.COLON and p.type not in {
1955         syms.subscript,
1956         syms.subscriptlist,
1957         syms.sliceop,
1958     }:
1959         return NO
1960
1961     prev = leaf.prev_sibling
1962     if not prev:
1963         prevp = preceding_leaf(p)
1964         if not prevp or prevp.type in OPENING_BRACKETS:
1965             return NO
1966
1967         if t == token.COLON:
1968             if prevp.type == token.COLON:
1969                 return NO
1970
1971             elif prevp.type != token.COMMA and not complex_subscript:
1972                 return NO
1973
1974             return SPACE
1975
1976         if prevp.type == token.EQUAL:
1977             if prevp.parent:
1978                 if prevp.parent.type in {
1979                     syms.arglist,
1980                     syms.argument,
1981                     syms.parameters,
1982                     syms.varargslist,
1983                 }:
1984                     return NO
1985
1986                 elif prevp.parent.type == syms.typedargslist:
1987                     # A bit hacky: if the equal sign has whitespace, it means we
1988                     # previously found it's a typed argument.  So, we're using
1989                     # that, too.
1990                     return prevp.prefix
1991
1992         elif prevp.type in VARARGS_SPECIALS:
1993             if is_vararg(prevp, within=VARARGS_PARENTS | UNPACKING_PARENTS):
1994                 return NO
1995
1996         elif prevp.type == token.COLON:
1997             if prevp.parent and prevp.parent.type in {syms.subscript, syms.sliceop}:
1998                 return SPACE if complex_subscript else NO
1999
2000         elif (
2001             prevp.parent
2002             and prevp.parent.type == syms.factor
2003             and prevp.type in MATH_OPERATORS
2004         ):
2005             return NO
2006
2007         elif (
2008             prevp.type == token.RIGHTSHIFT
2009             and prevp.parent
2010             and prevp.parent.type == syms.shift_expr
2011             and prevp.prev_sibling
2012             and prevp.prev_sibling.type == token.NAME
2013             and prevp.prev_sibling.value == "print"  # type: ignore
2014         ):
2015             # Python 2 print chevron
2016             return NO
2017
2018     elif prev.type in OPENING_BRACKETS:
2019         return NO
2020
2021     if p.type in {syms.parameters, syms.arglist}:
2022         # untyped function signatures or calls
2023         if not prev or prev.type != token.COMMA:
2024             return NO
2025
2026     elif p.type == syms.varargslist:
2027         # lambdas
2028         if prev and prev.type != token.COMMA:
2029             return NO
2030
2031     elif p.type == syms.typedargslist:
2032         # typed function signatures
2033         if not prev:
2034             return NO
2035
2036         if t == token.EQUAL:
2037             if prev.type != syms.tname:
2038                 return NO
2039
2040         elif prev.type == token.EQUAL:
2041             # A bit hacky: if the equal sign has whitespace, it means we
2042             # previously found it's a typed argument.  So, we're using that, too.
2043             return prev.prefix
2044
2045         elif prev.type != token.COMMA:
2046             return NO
2047
2048     elif p.type == syms.tname:
2049         # type names
2050         if not prev:
2051             prevp = preceding_leaf(p)
2052             if not prevp or prevp.type != token.COMMA:
2053                 return NO
2054
2055     elif p.type == syms.trailer:
2056         # attributes and calls
2057         if t == token.LPAR or t == token.RPAR:
2058             return NO
2059
2060         if not prev:
2061             if t == token.DOT:
2062                 prevp = preceding_leaf(p)
2063                 if not prevp or prevp.type != token.NUMBER:
2064                     return NO
2065
2066             elif t == token.LSQB:
2067                 return NO
2068
2069         elif prev.type != token.COMMA:
2070             return NO
2071
2072     elif p.type == syms.argument:
2073         # single argument
2074         if t == token.EQUAL:
2075             return NO
2076
2077         if not prev:
2078             prevp = preceding_leaf(p)
2079             if not prevp or prevp.type == token.LPAR:
2080                 return NO
2081
2082         elif prev.type in {token.EQUAL} | VARARGS_SPECIALS:
2083             return NO
2084
2085     elif p.type == syms.decorator:
2086         # decorators
2087         return NO
2088
2089     elif p.type == syms.dotted_name:
2090         if prev:
2091             return NO
2092
2093         prevp = preceding_leaf(p)
2094         if not prevp or prevp.type == token.AT or prevp.type == token.DOT:
2095             return NO
2096
2097     elif p.type == syms.classdef:
2098         if t == token.LPAR:
2099             return NO
2100
2101         if prev and prev.type == token.LPAR:
2102             return NO
2103
2104     elif p.type in {syms.subscript, syms.sliceop}:
2105         # indexing
2106         if not prev:
2107             assert p.parent is not None, "subscripts are always parented"
2108             if p.parent.type == syms.subscriptlist:
2109                 return SPACE
2110
2111             return NO
2112
2113         elif not complex_subscript:
2114             return NO
2115
2116     elif p.type == syms.atom:
2117         if prev and t == token.DOT:
2118             # dots, but not the first one.
2119             return NO
2120
2121     elif p.type == syms.dictsetmaker:
2122         # dict unpacking
2123         if prev and prev.type == token.DOUBLESTAR:
2124             return NO
2125
2126     elif p.type in {syms.factor, syms.star_expr}:
2127         # unary ops
2128         if not prev:
2129             prevp = preceding_leaf(p)
2130             if not prevp or prevp.type in OPENING_BRACKETS:
2131                 return NO
2132
2133             prevp_parent = prevp.parent
2134             assert prevp_parent is not None
2135             if prevp.type == token.COLON and prevp_parent.type in {
2136                 syms.subscript,
2137                 syms.sliceop,
2138             }:
2139                 return NO
2140
2141             elif prevp.type == token.EQUAL and prevp_parent.type == syms.argument:
2142                 return NO
2143
2144         elif t in {token.NAME, token.NUMBER, token.STRING}:
2145             return NO
2146
2147     elif p.type == syms.import_from:
2148         if t == token.DOT:
2149             if prev and prev.type == token.DOT:
2150                 return NO
2151
2152         elif t == token.NAME:
2153             if v == "import":
2154                 return SPACE
2155
2156             if prev and prev.type == token.DOT:
2157                 return NO
2158
2159     elif p.type == syms.sliceop:
2160         return NO
2161
2162     return SPACE
2163
2164
2165 def preceding_leaf(node: Optional[LN]) -> Optional[Leaf]:
2166     """Return the first leaf that precedes `node`, if any."""
2167     while node:
2168         res = node.prev_sibling
2169         if res:
2170             if isinstance(res, Leaf):
2171                 return res
2172
2173             try:
2174                 return list(res.leaves())[-1]
2175
2176             except IndexError:
2177                 return None
2178
2179         node = node.parent
2180     return None
2181
2182
2183 def child_towards(ancestor: Node, descendant: LN) -> Optional[LN]:
2184     """Return the child of `ancestor` that contains `descendant`."""
2185     node: Optional[LN] = descendant
2186     while node and node.parent != ancestor:
2187         node = node.parent
2188     return node
2189
2190
2191 def container_of(leaf: Leaf) -> LN:
2192     """Return `leaf` or one of its ancestors that is the topmost container of it.
2193
2194     By "container" we mean a node where `leaf` is the very first child.
2195     """
2196     same_prefix = leaf.prefix
2197     container: LN = leaf
2198     while container:
2199         parent = container.parent
2200         if parent is None:
2201             break
2202
2203         if parent.children[0].prefix != same_prefix:
2204             break
2205
2206         if parent.type == syms.file_input:
2207             break
2208
2209         if parent.prev_sibling is not None and parent.prev_sibling.type in BRACKETS:
2210             break
2211
2212         container = parent
2213     return container
2214
2215
2216 def is_split_after_delimiter(leaf: Leaf, previous: Optional[Leaf] = None) -> Priority:
2217     """Return the priority of the `leaf` delimiter, given a line break after it.
2218
2219     The delimiter priorities returned here are from those delimiters that would
2220     cause a line break after themselves.
2221
2222     Higher numbers are higher priority.
2223     """
2224     if leaf.type == token.COMMA:
2225         return COMMA_PRIORITY
2226
2227     return 0
2228
2229
2230 def is_split_before_delimiter(leaf: Leaf, previous: Optional[Leaf] = None) -> Priority:
2231     """Return the priority of the `leaf` delimiter, given a line break before it.
2232
2233     The delimiter priorities returned here are from those delimiters that would
2234     cause a line break before themselves.
2235
2236     Higher numbers are higher priority.
2237     """
2238     if is_vararg(leaf, within=VARARGS_PARENTS | UNPACKING_PARENTS):
2239         # * and ** might also be MATH_OPERATORS but in this case they are not.
2240         # Don't treat them as a delimiter.
2241         return 0
2242
2243     if (
2244         leaf.type == token.DOT
2245         and leaf.parent
2246         and leaf.parent.type not in {syms.import_from, syms.dotted_name}
2247         and (previous is None or previous.type in CLOSING_BRACKETS)
2248     ):
2249         return DOT_PRIORITY
2250
2251     if (
2252         leaf.type in MATH_OPERATORS
2253         and leaf.parent
2254         and leaf.parent.type not in {syms.factor, syms.star_expr}
2255     ):
2256         return MATH_PRIORITIES[leaf.type]
2257
2258     if leaf.type in COMPARATORS:
2259         return COMPARATOR_PRIORITY
2260
2261     if (
2262         leaf.type == token.STRING
2263         and previous is not None
2264         and previous.type == token.STRING
2265     ):
2266         return STRING_PRIORITY
2267
2268     if leaf.type not in {token.NAME, token.ASYNC}:
2269         return 0
2270
2271     if (
2272         leaf.value == "for"
2273         and leaf.parent
2274         and leaf.parent.type in {syms.comp_for, syms.old_comp_for}
2275         or leaf.type == token.ASYNC
2276     ):
2277         if (
2278             not isinstance(leaf.prev_sibling, Leaf)
2279             or leaf.prev_sibling.value != "async"
2280         ):
2281             return COMPREHENSION_PRIORITY
2282
2283     if (
2284         leaf.value == "if"
2285         and leaf.parent
2286         and leaf.parent.type in {syms.comp_if, syms.old_comp_if}
2287     ):
2288         return COMPREHENSION_PRIORITY
2289
2290     if leaf.value in {"if", "else"} and leaf.parent and leaf.parent.type == syms.test:
2291         return TERNARY_PRIORITY
2292
2293     if leaf.value == "is":
2294         return COMPARATOR_PRIORITY
2295
2296     if (
2297         leaf.value == "in"
2298         and leaf.parent
2299         and leaf.parent.type in {syms.comp_op, syms.comparison}
2300         and not (
2301             previous is not None
2302             and previous.type == token.NAME
2303             and previous.value == "not"
2304         )
2305     ):
2306         return COMPARATOR_PRIORITY
2307
2308     if (
2309         leaf.value == "not"
2310         and leaf.parent
2311         and leaf.parent.type == syms.comp_op
2312         and not (
2313             previous is not None
2314             and previous.type == token.NAME
2315             and previous.value == "is"
2316         )
2317     ):
2318         return COMPARATOR_PRIORITY
2319
2320     if leaf.value in LOGIC_OPERATORS and leaf.parent:
2321         return LOGIC_PRIORITY
2322
2323     return 0
2324
2325
2326 FMT_OFF = {"# fmt: off", "# fmt:off", "# yapf: disable"}
2327 FMT_ON = {"# fmt: on", "# fmt:on", "# yapf: enable"}
2328
2329
2330 def generate_comments(leaf: LN) -> Iterator[Leaf]:
2331     """Clean the prefix of the `leaf` and generate comments from it, if any.
2332
2333     Comments in lib2to3 are shoved into the whitespace prefix.  This happens
2334     in `pgen2/driver.py:Driver.parse_tokens()`.  This was a brilliant implementation
2335     move because it does away with modifying the grammar to include all the
2336     possible places in which comments can be placed.
2337
2338     The sad consequence for us though is that comments don't "belong" anywhere.
2339     This is why this function generates simple parentless Leaf objects for
2340     comments.  We simply don't know what the correct parent should be.
2341
2342     No matter though, we can live without this.  We really only need to
2343     differentiate between inline and standalone comments.  The latter don't
2344     share the line with any code.
2345
2346     Inline comments are emitted as regular token.COMMENT leaves.  Standalone
2347     are emitted with a fake STANDALONE_COMMENT token identifier.
2348     """
2349     for pc in list_comments(leaf.prefix, is_endmarker=leaf.type == token.ENDMARKER):
2350         yield Leaf(pc.type, pc.value, prefix="\n" * pc.newlines)
2351
2352
2353 @dataclass
2354 class ProtoComment:
2355     """Describes a piece of syntax that is a comment.
2356
2357     It's not a :class:`blib2to3.pytree.Leaf` so that:
2358
2359     * it can be cached (`Leaf` objects should not be reused more than once as
2360       they store their lineno, column, prefix, and parent information);
2361     * `newlines` and `consumed` fields are kept separate from the `value`. This
2362       simplifies handling of special marker comments like ``# fmt: off/on``.
2363     """
2364
2365     type: int  # token.COMMENT or STANDALONE_COMMENT
2366     value: str  # content of the comment
2367     newlines: int  # how many newlines before the comment
2368     consumed: int  # how many characters of the original leaf's prefix did we consume
2369
2370
2371 @lru_cache(maxsize=4096)
2372 def list_comments(prefix: str, *, is_endmarker: bool) -> List[ProtoComment]:
2373     """Return a list of :class:`ProtoComment` objects parsed from the given `prefix`."""
2374     result: List[ProtoComment] = []
2375     if not prefix or "#" not in prefix:
2376         return result
2377
2378     consumed = 0
2379     nlines = 0
2380     ignored_lines = 0
2381     for index, line in enumerate(prefix.split("\n")):
2382         consumed += len(line) + 1  # adding the length of the split '\n'
2383         line = line.lstrip()
2384         if not line:
2385             nlines += 1
2386         if not line.startswith("#"):
2387             # Escaped newlines outside of a comment are not really newlines at
2388             # all. We treat a single-line comment following an escaped newline
2389             # as a simple trailing comment.
2390             if line.endswith("\\"):
2391                 ignored_lines += 1
2392             continue
2393
2394         if index == ignored_lines and not is_endmarker:
2395             comment_type = token.COMMENT  # simple trailing comment
2396         else:
2397             comment_type = STANDALONE_COMMENT
2398         comment = make_comment(line)
2399         result.append(
2400             ProtoComment(
2401                 type=comment_type, value=comment, newlines=nlines, consumed=consumed
2402             )
2403         )
2404         nlines = 0
2405     return result
2406
2407
2408 def make_comment(content: str) -> str:
2409     """Return a consistently formatted comment from the given `content` string.
2410
2411     All comments (except for "##", "#!", "#:", '#'", "#%%") should have a single
2412     space between the hash sign and the content.
2413
2414     If `content` didn't start with a hash sign, one is provided.
2415     """
2416     content = content.rstrip()
2417     if not content:
2418         return "#"
2419
2420     if content[0] == "#":
2421         content = content[1:]
2422     if content and content[0] not in " !:#'%":
2423         content = " " + content
2424     return "#" + content
2425
2426
2427 def split_line(
2428     line: Line,
2429     line_length: int,
2430     inner: bool = False,
2431     features: Collection[Feature] = (),
2432 ) -> Iterator[Line]:
2433     """Split a `line` into potentially many lines.
2434
2435     They should fit in the allotted `line_length` but might not be able to.
2436     `inner` signifies that there were a pair of brackets somewhere around the
2437     current `line`, possibly transitively. This means we can fallback to splitting
2438     by delimiters if the LHS/RHS don't yield any results.
2439
2440     `features` are syntactical features that may be used in the output.
2441     """
2442     if line.is_comment:
2443         yield line
2444         return
2445
2446     line_str = str(line).strip("\n")
2447
2448     if (
2449         not line.contains_uncollapsable_type_comments()
2450         and not line.should_explode
2451         and not line.is_collection_with_optional_trailing_comma
2452         and (
2453             is_line_short_enough(line, line_length=line_length, line_str=line_str)
2454             or line.contains_unsplittable_type_ignore()
2455         )
2456     ):
2457         yield line
2458         return
2459
2460     split_funcs: List[SplitFunc]
2461     if line.is_def:
2462         split_funcs = [left_hand_split]
2463     else:
2464
2465         def rhs(line: Line, features: Collection[Feature]) -> Iterator[Line]:
2466             for omit in generate_trailers_to_omit(line, line_length):
2467                 lines = list(right_hand_split(line, line_length, features, omit=omit))
2468                 if is_line_short_enough(lines[0], line_length=line_length):
2469                     yield from lines
2470                     return
2471
2472             # All splits failed, best effort split with no omits.
2473             # This mostly happens to multiline strings that are by definition
2474             # reported as not fitting a single line.
2475             # line_length=1 here was historically a bug that somehow became a feature.
2476             # See #762 and #781 for the full story.
2477             yield from right_hand_split(line, line_length=1, features=features)
2478
2479         if line.inside_brackets:
2480             split_funcs = [delimiter_split, standalone_comment_split, rhs]
2481         else:
2482             split_funcs = [rhs]
2483     for split_func in split_funcs:
2484         # We are accumulating lines in `result` because we might want to abort
2485         # mission and return the original line in the end, or attempt a different
2486         # split altogether.
2487         result: List[Line] = []
2488         try:
2489             for l in split_func(line, features):
2490                 if str(l).strip("\n") == line_str:
2491                     raise CannotSplit("Split function returned an unchanged result")
2492
2493                 result.extend(
2494                     split_line(
2495                         l, line_length=line_length, inner=True, features=features
2496                     )
2497                 )
2498         except CannotSplit:
2499             continue
2500
2501         else:
2502             yield from result
2503             break
2504
2505     else:
2506         yield line
2507
2508
2509 def left_hand_split(line: Line, features: Collection[Feature] = ()) -> Iterator[Line]:
2510     """Split line into many lines, starting with the first matching bracket pair.
2511
2512     Note: this usually looks weird, only use this for function definitions.
2513     Prefer RHS otherwise.  This is why this function is not symmetrical with
2514     :func:`right_hand_split` which also handles optional parentheses.
2515     """
2516     tail_leaves: List[Leaf] = []
2517     body_leaves: List[Leaf] = []
2518     head_leaves: List[Leaf] = []
2519     current_leaves = head_leaves
2520     matching_bracket: Optional[Leaf] = None
2521     for leaf in line.leaves:
2522         if (
2523             current_leaves is body_leaves
2524             and leaf.type in CLOSING_BRACKETS
2525             and leaf.opening_bracket is matching_bracket
2526         ):
2527             current_leaves = tail_leaves if body_leaves else head_leaves
2528         current_leaves.append(leaf)
2529         if current_leaves is head_leaves:
2530             if leaf.type in OPENING_BRACKETS:
2531                 matching_bracket = leaf
2532                 current_leaves = body_leaves
2533     if not matching_bracket:
2534         raise CannotSplit("No brackets found")
2535
2536     head = bracket_split_build_line(head_leaves, line, matching_bracket)
2537     body = bracket_split_build_line(body_leaves, line, matching_bracket, is_body=True)
2538     tail = bracket_split_build_line(tail_leaves, line, matching_bracket)
2539     bracket_split_succeeded_or_raise(head, body, tail)
2540     for result in (head, body, tail):
2541         if result:
2542             yield result
2543
2544
2545 def right_hand_split(
2546     line: Line,
2547     line_length: int,
2548     features: Collection[Feature] = (),
2549     omit: Collection[LeafID] = (),
2550 ) -> Iterator[Line]:
2551     """Split line into many lines, starting with the last matching bracket pair.
2552
2553     If the split was by optional parentheses, attempt splitting without them, too.
2554     `omit` is a collection of closing bracket IDs that shouldn't be considered for
2555     this split.
2556
2557     Note: running this function modifies `bracket_depth` on the leaves of `line`.
2558     """
2559     tail_leaves: List[Leaf] = []
2560     body_leaves: List[Leaf] = []
2561     head_leaves: List[Leaf] = []
2562     current_leaves = tail_leaves
2563     opening_bracket: Optional[Leaf] = None
2564     closing_bracket: Optional[Leaf] = None
2565     for leaf in reversed(line.leaves):
2566         if current_leaves is body_leaves:
2567             if leaf is opening_bracket:
2568                 current_leaves = head_leaves if body_leaves else tail_leaves
2569         current_leaves.append(leaf)
2570         if current_leaves is tail_leaves:
2571             if leaf.type in CLOSING_BRACKETS and id(leaf) not in omit:
2572                 opening_bracket = leaf.opening_bracket
2573                 closing_bracket = leaf
2574                 current_leaves = body_leaves
2575     if not (opening_bracket and closing_bracket and head_leaves):
2576         # If there is no opening or closing_bracket that means the split failed and
2577         # all content is in the tail.  Otherwise, if `head_leaves` are empty, it means
2578         # the matching `opening_bracket` wasn't available on `line` anymore.
2579         raise CannotSplit("No brackets found")
2580
2581     tail_leaves.reverse()
2582     body_leaves.reverse()
2583     head_leaves.reverse()
2584     head = bracket_split_build_line(head_leaves, line, opening_bracket)
2585     body = bracket_split_build_line(body_leaves, line, opening_bracket, is_body=True)
2586     tail = bracket_split_build_line(tail_leaves, line, opening_bracket)
2587     bracket_split_succeeded_or_raise(head, body, tail)
2588     if (
2589         # the body shouldn't be exploded
2590         not body.should_explode
2591         # the opening bracket is an optional paren
2592         and opening_bracket.type == token.LPAR
2593         and not opening_bracket.value
2594         # the closing bracket is an optional paren
2595         and closing_bracket.type == token.RPAR
2596         and not closing_bracket.value
2597         # it's not an import (optional parens are the only thing we can split on
2598         # in this case; attempting a split without them is a waste of time)
2599         and not line.is_import
2600         # there are no standalone comments in the body
2601         and not body.contains_standalone_comments(0)
2602         # and we can actually remove the parens
2603         and can_omit_invisible_parens(body, line_length)
2604     ):
2605         omit = {id(closing_bracket), *omit}
2606         try:
2607             yield from right_hand_split(line, line_length, features=features, omit=omit)
2608             return
2609
2610         except CannotSplit:
2611             if not (
2612                 can_be_split(body)
2613                 or is_line_short_enough(body, line_length=line_length)
2614             ):
2615                 raise CannotSplit(
2616                     "Splitting failed, body is still too long and can't be split."
2617                 )
2618
2619             elif head.contains_multiline_strings() or tail.contains_multiline_strings():
2620                 raise CannotSplit(
2621                     "The current optional pair of parentheses is bound to fail to "
2622                     "satisfy the splitting algorithm because the head or the tail "
2623                     "contains multiline strings which by definition never fit one "
2624                     "line."
2625                 )
2626
2627     ensure_visible(opening_bracket)
2628     ensure_visible(closing_bracket)
2629     for result in (head, body, tail):
2630         if result:
2631             yield result
2632
2633
2634 def bracket_split_succeeded_or_raise(head: Line, body: Line, tail: Line) -> None:
2635     """Raise :exc:`CannotSplit` if the last left- or right-hand split failed.
2636
2637     Do nothing otherwise.
2638
2639     A left- or right-hand split is based on a pair of brackets. Content before
2640     (and including) the opening bracket is left on one line, content inside the
2641     brackets is put on a separate line, and finally content starting with and
2642     following the closing bracket is put on a separate line.
2643
2644     Those are called `head`, `body`, and `tail`, respectively. If the split
2645     produced the same line (all content in `head`) or ended up with an empty `body`
2646     and the `tail` is just the closing bracket, then it's considered failed.
2647     """
2648     tail_len = len(str(tail).strip())
2649     if not body:
2650         if tail_len == 0:
2651             raise CannotSplit("Splitting brackets produced the same line")
2652
2653         elif tail_len < 3:
2654             raise CannotSplit(
2655                 f"Splitting brackets on an empty body to save "
2656                 f"{tail_len} characters is not worth it"
2657             )
2658
2659
2660 def bracket_split_build_line(
2661     leaves: List[Leaf], original: Line, opening_bracket: Leaf, *, is_body: bool = False
2662 ) -> Line:
2663     """Return a new line with given `leaves` and respective comments from `original`.
2664
2665     If `is_body` is True, the result line is one-indented inside brackets and as such
2666     has its first leaf's prefix normalized and a trailing comma added when expected.
2667     """
2668     result = Line(depth=original.depth)
2669     if is_body:
2670         result.inside_brackets = True
2671         result.depth += 1
2672         if leaves:
2673             # Since body is a new indent level, remove spurious leading whitespace.
2674             normalize_prefix(leaves[0], inside_brackets=True)
2675             # Ensure a trailing comma for imports and standalone function arguments, but
2676             # be careful not to add one after any comments or within type annotations.
2677             no_commas = (
2678                 original.is_def
2679                 and opening_bracket.value == "("
2680                 and not any(l.type == token.COMMA for l in leaves)
2681             )
2682
2683             if original.is_import or no_commas:
2684                 for i in range(len(leaves) - 1, -1, -1):
2685                     if leaves[i].type == STANDALONE_COMMENT:
2686                         continue
2687
2688                     if leaves[i].type != token.COMMA:
2689                         leaves.insert(i + 1, Leaf(token.COMMA, ","))
2690                     break
2691
2692     # Populate the line
2693     for leaf in leaves:
2694         result.append(leaf, preformatted=True)
2695         for comment_after in original.comments_after(leaf):
2696             result.append(comment_after, preformatted=True)
2697     if is_body:
2698         result.should_explode = should_explode(result, opening_bracket)
2699     return result
2700
2701
2702 def dont_increase_indentation(split_func: SplitFunc) -> SplitFunc:
2703     """Normalize prefix of the first leaf in every line returned by `split_func`.
2704
2705     This is a decorator over relevant split functions.
2706     """
2707
2708     @wraps(split_func)
2709     def split_wrapper(line: Line, features: Collection[Feature] = ()) -> Iterator[Line]:
2710         for l in split_func(line, features):
2711             normalize_prefix(l.leaves[0], inside_brackets=True)
2712             yield l
2713
2714     return split_wrapper
2715
2716
2717 @dont_increase_indentation
2718 def delimiter_split(line: Line, features: Collection[Feature] = ()) -> Iterator[Line]:
2719     """Split according to delimiters of the highest priority.
2720
2721     If the appropriate Features are given, the split will add trailing commas
2722     also in function signatures and calls that contain `*` and `**`.
2723     """
2724     try:
2725         last_leaf = line.leaves[-1]
2726     except IndexError:
2727         raise CannotSplit("Line empty")
2728
2729     bt = line.bracket_tracker
2730     try:
2731         delimiter_priority = bt.max_delimiter_priority(exclude={id(last_leaf)})
2732     except ValueError:
2733         raise CannotSplit("No delimiters found")
2734
2735     if delimiter_priority == DOT_PRIORITY:
2736         if bt.delimiter_count_with_priority(delimiter_priority) == 1:
2737             raise CannotSplit("Splitting a single attribute from its owner looks wrong")
2738
2739     current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
2740     lowest_depth = sys.maxsize
2741     trailing_comma_safe = True
2742
2743     def append_to_line(leaf: Leaf) -> Iterator[Line]:
2744         """Append `leaf` to current line or to new line if appending impossible."""
2745         nonlocal current_line
2746         try:
2747             current_line.append_safe(leaf, preformatted=True)
2748         except ValueError:
2749             yield current_line
2750
2751             current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
2752             current_line.append(leaf)
2753
2754     for leaf in line.leaves:
2755         yield from append_to_line(leaf)
2756
2757         for comment_after in line.comments_after(leaf):
2758             yield from append_to_line(comment_after)
2759
2760         lowest_depth = min(lowest_depth, leaf.bracket_depth)
2761         if leaf.bracket_depth == lowest_depth:
2762             if is_vararg(leaf, within={syms.typedargslist}):
2763                 trailing_comma_safe = (
2764                     trailing_comma_safe and Feature.TRAILING_COMMA_IN_DEF in features
2765                 )
2766             elif is_vararg(leaf, within={syms.arglist, syms.argument}):
2767                 trailing_comma_safe = (
2768                     trailing_comma_safe and Feature.TRAILING_COMMA_IN_CALL in features
2769                 )
2770
2771         leaf_priority = bt.delimiters.get(id(leaf))
2772         if leaf_priority == delimiter_priority:
2773             yield current_line
2774
2775             current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
2776     if current_line:
2777         if (
2778             trailing_comma_safe
2779             and delimiter_priority == COMMA_PRIORITY
2780             and current_line.leaves[-1].type != token.COMMA
2781             and current_line.leaves[-1].type != STANDALONE_COMMENT
2782         ):
2783             current_line.append(Leaf(token.COMMA, ","))
2784         yield current_line
2785
2786
2787 @dont_increase_indentation
2788 def standalone_comment_split(
2789     line: Line, features: Collection[Feature] = ()
2790 ) -> Iterator[Line]:
2791     """Split standalone comments from the rest of the line."""
2792     if not line.contains_standalone_comments(0):
2793         raise CannotSplit("Line does not have any standalone comments")
2794
2795     current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
2796
2797     def append_to_line(leaf: Leaf) -> Iterator[Line]:
2798         """Append `leaf` to current line or to new line if appending impossible."""
2799         nonlocal current_line
2800         try:
2801             current_line.append_safe(leaf, preformatted=True)
2802         except ValueError:
2803             yield current_line
2804
2805             current_line = Line(depth=line.depth, inside_brackets=line.inside_brackets)
2806             current_line.append(leaf)
2807
2808     for leaf in line.leaves:
2809         yield from append_to_line(leaf)
2810
2811         for comment_after in line.comments_after(leaf):
2812             yield from append_to_line(comment_after)
2813
2814     if current_line:
2815         yield current_line
2816
2817
2818 def is_import(leaf: Leaf) -> bool:
2819     """Return True if the given leaf starts an import statement."""
2820     p = leaf.parent
2821     t = leaf.type
2822     v = leaf.value
2823     return bool(
2824         t == token.NAME
2825         and (
2826             (v == "import" and p and p.type == syms.import_name)
2827             or (v == "from" and p and p.type == syms.import_from)
2828         )
2829     )
2830
2831
2832 def is_type_comment(leaf: Leaf, suffix: str = "") -> bool:
2833     """Return True if the given leaf is a special comment.
2834     Only returns true for type comments for now."""
2835     t = leaf.type
2836     v = leaf.value
2837     return t in {token.COMMENT, STANDALONE_COMMENT} and v.startswith("# type:" + suffix)
2838
2839
2840 def normalize_prefix(leaf: Leaf, *, inside_brackets: bool) -> None:
2841     """Leave existing extra newlines if not `inside_brackets`. Remove everything
2842     else.
2843
2844     Note: don't use backslashes for formatting or you'll lose your voting rights.
2845     """
2846     if not inside_brackets:
2847         spl = leaf.prefix.split("#")
2848         if "\\" not in spl[0]:
2849             nl_count = spl[-1].count("\n")
2850             if len(spl) > 1:
2851                 nl_count -= 1
2852             leaf.prefix = "\n" * nl_count
2853             return
2854
2855     leaf.prefix = ""
2856
2857
2858 def normalize_string_prefix(leaf: Leaf, remove_u_prefix: bool = False) -> None:
2859     """Make all string prefixes lowercase.
2860
2861     If remove_u_prefix is given, also removes any u prefix from the string.
2862
2863     Note: Mutates its argument.
2864     """
2865     match = re.match(r"^([furbFURB]*)(.*)$", leaf.value, re.DOTALL)
2866     assert match is not None, f"failed to match string {leaf.value!r}"
2867     orig_prefix = match.group(1)
2868     new_prefix = orig_prefix.replace("F", "f").replace("B", "b").replace("U", "u")
2869     if remove_u_prefix:
2870         new_prefix = new_prefix.replace("u", "")
2871     leaf.value = f"{new_prefix}{match.group(2)}"
2872
2873
2874 def normalize_string_quotes(leaf: Leaf) -> None:
2875     """Prefer double quotes but only if it doesn't cause more escaping.
2876
2877     Adds or removes backslashes as appropriate. Doesn't parse and fix
2878     strings nested in f-strings (yet).
2879
2880     Note: Mutates its argument.
2881     """
2882     value = leaf.value.lstrip("furbFURB")
2883     if value[:3] == '"""':
2884         return
2885
2886     elif value[:3] == "'''":
2887         orig_quote = "'''"
2888         new_quote = '"""'
2889     elif value[0] == '"':
2890         orig_quote = '"'
2891         new_quote = "'"
2892     else:
2893         orig_quote = "'"
2894         new_quote = '"'
2895     first_quote_pos = leaf.value.find(orig_quote)
2896     if first_quote_pos == -1:
2897         return  # There's an internal error
2898
2899     prefix = leaf.value[:first_quote_pos]
2900     unescaped_new_quote = re.compile(rf"(([^\\]|^)(\\\\)*){new_quote}")
2901     escaped_new_quote = re.compile(rf"([^\\]|^)\\((?:\\\\)*){new_quote}")
2902     escaped_orig_quote = re.compile(rf"([^\\]|^)\\((?:\\\\)*){orig_quote}")
2903     body = leaf.value[first_quote_pos + len(orig_quote) : -len(orig_quote)]
2904     if "r" in prefix.casefold():
2905         if unescaped_new_quote.search(body):
2906             # There's at least one unescaped new_quote in this raw string
2907             # so converting is impossible
2908             return
2909
2910         # Do not introduce or remove backslashes in raw strings
2911         new_body = body
2912     else:
2913         # remove unnecessary escapes
2914         new_body = sub_twice(escaped_new_quote, rf"\1\2{new_quote}", body)
2915         if body != new_body:
2916             # Consider the string without unnecessary escapes as the original
2917             body = new_body
2918             leaf.value = f"{prefix}{orig_quote}{body}{orig_quote}"
2919         new_body = sub_twice(escaped_orig_quote, rf"\1\2{orig_quote}", new_body)
2920         new_body = sub_twice(unescaped_new_quote, rf"\1\\{new_quote}", new_body)
2921     if "f" in prefix.casefold():
2922         matches = re.findall(
2923             r"""
2924             (?:[^{]|^)\{  # start of the string or a non-{ followed by a single {
2925                 ([^{].*?)  # contents of the brackets except if begins with {{
2926             \}(?:[^}]|$)  # A } followed by end of the string or a non-}
2927             """,
2928             new_body,
2929             re.VERBOSE,
2930         )
2931         for m in matches:
2932             if "\\" in str(m):
2933                 # Do not introduce backslashes in interpolated expressions
2934                 return
2935
2936     if new_quote == '"""' and new_body[-1:] == '"':
2937         # edge case:
2938         new_body = new_body[:-1] + '\\"'
2939     orig_escape_count = body.count("\\")
2940     new_escape_count = new_body.count("\\")
2941     if new_escape_count > orig_escape_count:
2942         return  # Do not introduce more escaping
2943
2944     if new_escape_count == orig_escape_count and orig_quote == '"':
2945         return  # Prefer double quotes
2946
2947     leaf.value = f"{prefix}{new_quote}{new_body}{new_quote}"
2948
2949
2950 def normalize_numeric_literal(leaf: Leaf) -> None:
2951     """Normalizes numeric (float, int, and complex) literals.
2952
2953     All letters used in the representation are normalized to lowercase (except
2954     in Python 2 long literals).
2955     """
2956     text = leaf.value.lower()
2957     if text.startswith(("0o", "0b")):
2958         # Leave octal and binary literals alone.
2959         pass
2960     elif text.startswith("0x"):
2961         # Change hex literals to upper case.
2962         before, after = text[:2], text[2:]
2963         text = f"{before}{after.upper()}"
2964     elif "e" in text:
2965         before, after = text.split("e")
2966         sign = ""
2967         if after.startswith("-"):
2968             after = after[1:]
2969             sign = "-"
2970         elif after.startswith("+"):
2971             after = after[1:]
2972         before = format_float_or_int_string(before)
2973         text = f"{before}e{sign}{after}"
2974     elif text.endswith(("j", "l")):
2975         number = text[:-1]
2976         suffix = text[-1]
2977         # Capitalize in "2L" because "l" looks too similar to "1".
2978         if suffix == "l":
2979             suffix = "L"
2980         text = f"{format_float_or_int_string(number)}{suffix}"
2981     else:
2982         text = format_float_or_int_string(text)
2983     leaf.value = text
2984
2985
2986 def format_float_or_int_string(text: str) -> str:
2987     """Formats a float string like "1.0"."""
2988     if "." not in text:
2989         return text
2990
2991     before, after = text.split(".")
2992     return f"{before or 0}.{after or 0}"
2993
2994
2995 def normalize_invisible_parens(node: Node, parens_after: Set[str]) -> None:
2996     """Make existing optional parentheses invisible or create new ones.
2997
2998     `parens_after` is a set of string leaf values immediately after which parens
2999     should be put.
3000
3001     Standardizes on visible parentheses for single-element tuples, and keeps
3002     existing visible parentheses for other tuples and generator expressions.
3003     """
3004     for pc in list_comments(node.prefix, is_endmarker=False):
3005         if pc.value in FMT_OFF:
3006             # This `node` has a prefix with `# fmt: off`, don't mess with parens.
3007             return
3008     check_lpar = False
3009     for index, child in enumerate(list(node.children)):
3010         # Add parentheses around long tuple unpacking in assignments.
3011         if (
3012             index == 0
3013             and isinstance(child, Node)
3014             and child.type == syms.testlist_star_expr
3015         ):
3016             check_lpar = True
3017
3018         if check_lpar:
3019             if is_walrus_assignment(child):
3020                 continue
3021
3022             if child.type == syms.atom:
3023                 if maybe_make_parens_invisible_in_atom(child, parent=node):
3024                     wrap_in_parentheses(node, child, visible=False)
3025             elif is_one_tuple(child):
3026                 wrap_in_parentheses(node, child, visible=True)
3027             elif node.type == syms.import_from:
3028                 # "import from" nodes store parentheses directly as part of
3029                 # the statement
3030                 if child.type == token.LPAR:
3031                     # make parentheses invisible
3032                     child.value = ""  # type: ignore
3033                     node.children[-1].value = ""  # type: ignore
3034                 elif child.type != token.STAR:
3035                     # insert invisible parentheses
3036                     node.insert_child(index, Leaf(token.LPAR, ""))
3037                     node.append_child(Leaf(token.RPAR, ""))
3038                 break
3039
3040             elif not (isinstance(child, Leaf) and is_multiline_string(child)):
3041                 wrap_in_parentheses(node, child, visible=False)
3042
3043         check_lpar = isinstance(child, Leaf) and child.value in parens_after
3044
3045
3046 def normalize_fmt_off(node: Node) -> None:
3047     """Convert content between `# fmt: off`/`# fmt: on` into standalone comments."""
3048     try_again = True
3049     while try_again:
3050         try_again = convert_one_fmt_off_pair(node)
3051
3052
3053 def convert_one_fmt_off_pair(node: Node) -> bool:
3054     """Convert content of a single `# fmt: off`/`# fmt: on` into a standalone comment.
3055
3056     Returns True if a pair was converted.
3057     """
3058     for leaf in node.leaves():
3059         previous_consumed = 0
3060         for comment in list_comments(leaf.prefix, is_endmarker=False):
3061             if comment.value in FMT_OFF:
3062                 # We only want standalone comments. If there's no previous leaf or
3063                 # the previous leaf is indentation, it's a standalone comment in
3064                 # disguise.
3065                 if comment.type != STANDALONE_COMMENT:
3066                     prev = preceding_leaf(leaf)
3067                     if prev and prev.type not in WHITESPACE:
3068                         continue
3069
3070                 ignored_nodes = list(generate_ignored_nodes(leaf))
3071                 if not ignored_nodes:
3072                     continue
3073
3074                 first = ignored_nodes[0]  # Can be a container node with the `leaf`.
3075                 parent = first.parent
3076                 prefix = first.prefix
3077                 first.prefix = prefix[comment.consumed :]
3078                 hidden_value = (
3079                     comment.value + "\n" + "".join(str(n) for n in ignored_nodes)
3080                 )
3081                 if hidden_value.endswith("\n"):
3082                     # That happens when one of the `ignored_nodes` ended with a NEWLINE
3083                     # leaf (possibly followed by a DEDENT).
3084                     hidden_value = hidden_value[:-1]
3085                 first_idx: Optional[int] = None
3086                 for ignored in ignored_nodes:
3087                     index = ignored.remove()
3088                     if first_idx is None:
3089                         first_idx = index
3090                 assert parent is not None, "INTERNAL ERROR: fmt: on/off handling (1)"
3091                 assert first_idx is not None, "INTERNAL ERROR: fmt: on/off handling (2)"
3092                 parent.insert_child(
3093                     first_idx,
3094                     Leaf(
3095                         STANDALONE_COMMENT,
3096                         hidden_value,
3097                         prefix=prefix[:previous_consumed] + "\n" * comment.newlines,
3098                     ),
3099                 )
3100                 return True
3101
3102             previous_consumed = comment.consumed
3103
3104     return False
3105
3106
3107 def generate_ignored_nodes(leaf: Leaf) -> Iterator[LN]:
3108     """Starting from the container of `leaf`, generate all leaves until `# fmt: on`.
3109
3110     Stops at the end of the block.
3111     """
3112     container: Optional[LN] = container_of(leaf)
3113     while container is not None and container.type != token.ENDMARKER:
3114         is_fmt_on = False
3115         for comment in list_comments(container.prefix, is_endmarker=False):
3116             if comment.value in FMT_ON:
3117                 is_fmt_on = True
3118             elif comment.value in FMT_OFF:
3119                 is_fmt_on = False
3120         if is_fmt_on:
3121             return
3122
3123         yield container
3124
3125         container = container.next_sibling
3126
3127
3128 def maybe_make_parens_invisible_in_atom(node: LN, parent: LN) -> bool:
3129     """If it's safe, make the parens in the atom `node` invisible, recursively.
3130     Additionally, remove repeated, adjacent invisible parens from the atom `node`
3131     as they are redundant.
3132
3133     Returns whether the node should itself be wrapped in invisible parentheses.
3134
3135     """
3136     if (
3137         node.type != syms.atom
3138         or is_empty_tuple(node)
3139         or is_one_tuple(node)
3140         or (is_yield(node) and parent.type != syms.expr_stmt)
3141         or max_delimiter_priority_in_atom(node) >= COMMA_PRIORITY
3142     ):
3143         return False
3144
3145     first = node.children[0]
3146     last = node.children[-1]
3147     if first.type == token.LPAR and last.type == token.RPAR:
3148         middle = node.children[1]
3149         # make parentheses invisible
3150         first.value = ""  # type: ignore
3151         last.value = ""  # type: ignore
3152         maybe_make_parens_invisible_in_atom(middle, parent=parent)
3153
3154         if is_atom_with_invisible_parens(middle):
3155             # Strip the invisible parens from `middle` by replacing
3156             # it with the child in-between the invisible parens
3157             middle.replace(middle.children[1])
3158
3159         return False
3160
3161     return True
3162
3163
3164 def is_atom_with_invisible_parens(node: LN) -> bool:
3165     """Given a `LN`, determines whether it's an atom `node` with invisible
3166     parens. Useful in dedupe-ing and normalizing parens.
3167     """
3168     if isinstance(node, Leaf) or node.type != syms.atom:
3169         return False
3170
3171     first, last = node.children[0], node.children[-1]
3172     return (
3173         isinstance(first, Leaf)
3174         and first.type == token.LPAR
3175         and first.value == ""
3176         and isinstance(last, Leaf)
3177         and last.type == token.RPAR
3178         and last.value == ""
3179     )
3180
3181
3182 def is_empty_tuple(node: LN) -> bool:
3183     """Return True if `node` holds an empty tuple."""
3184     return (
3185         node.type == syms.atom
3186         and len(node.children) == 2
3187         and node.children[0].type == token.LPAR
3188         and node.children[1].type == token.RPAR
3189     )
3190
3191
3192 def unwrap_singleton_parenthesis(node: LN) -> Optional[LN]:
3193     """Returns `wrapped` if `node` is of the shape ( wrapped ).
3194
3195     Parenthesis can be optional. Returns None otherwise"""
3196     if len(node.children) != 3:
3197         return None
3198
3199     lpar, wrapped, rpar = node.children
3200     if not (lpar.type == token.LPAR and rpar.type == token.RPAR):
3201         return None
3202
3203     return wrapped
3204
3205
3206 def wrap_in_parentheses(parent: Node, child: LN, *, visible: bool = True) -> None:
3207     """Wrap `child` in parentheses.
3208
3209     This replaces `child` with an atom holding the parentheses and the old
3210     child.  That requires moving the prefix.
3211
3212     If `visible` is False, the leaves will be valueless (and thus invisible).
3213     """
3214     lpar = Leaf(token.LPAR, "(" if visible else "")
3215     rpar = Leaf(token.RPAR, ")" if visible else "")
3216     prefix = child.prefix
3217     child.prefix = ""
3218     index = child.remove() or 0
3219     new_child = Node(syms.atom, [lpar, child, rpar])
3220     new_child.prefix = prefix
3221     parent.insert_child(index, new_child)
3222
3223
3224 def is_one_tuple(node: LN) -> bool:
3225     """Return True if `node` holds a tuple with one element, with or without parens."""
3226     if node.type == syms.atom:
3227         gexp = unwrap_singleton_parenthesis(node)
3228         if gexp is None or gexp.type != syms.testlist_gexp:
3229             return False
3230
3231         return len(gexp.children) == 2 and gexp.children[1].type == token.COMMA
3232
3233     return (
3234         node.type in IMPLICIT_TUPLE
3235         and len(node.children) == 2
3236         and node.children[1].type == token.COMMA
3237     )
3238
3239
3240 def is_walrus_assignment(node: LN) -> bool:
3241     """Return True iff `node` is of the shape ( test := test )"""
3242     inner = unwrap_singleton_parenthesis(node)
3243     return inner is not None and inner.type == syms.namedexpr_test
3244
3245
3246 def is_yield(node: LN) -> bool:
3247     """Return True if `node` holds a `yield` or `yield from` expression."""
3248     if node.type == syms.yield_expr:
3249         return True
3250
3251     if node.type == token.NAME and node.value == "yield":  # type: ignore
3252         return True
3253
3254     if node.type != syms.atom:
3255         return False
3256
3257     if len(node.children) != 3:
3258         return False
3259
3260     lpar, expr, rpar = node.children
3261     if lpar.type == token.LPAR and rpar.type == token.RPAR:
3262         return is_yield(expr)
3263
3264     return False
3265
3266
3267 def is_vararg(leaf: Leaf, within: Set[NodeType]) -> bool:
3268     """Return True if `leaf` is a star or double star in a vararg or kwarg.
3269
3270     If `within` includes VARARGS_PARENTS, this applies to function signatures.
3271     If `within` includes UNPACKING_PARENTS, it applies to right hand-side
3272     extended iterable unpacking (PEP 3132) and additional unpacking
3273     generalizations (PEP 448).
3274     """
3275     if leaf.type not in VARARGS_SPECIALS or not leaf.parent:
3276         return False
3277
3278     p = leaf.parent
3279     if p.type == syms.star_expr:
3280         # Star expressions are also used as assignment targets in extended
3281         # iterable unpacking (PEP 3132).  See what its parent is instead.
3282         if not p.parent:
3283             return False
3284
3285         p = p.parent
3286
3287     return p.type in within
3288
3289
3290 def is_multiline_string(leaf: Leaf) -> bool:
3291     """Return True if `leaf` is a multiline string that actually spans many lines."""
3292     value = leaf.value.lstrip("furbFURB")
3293     return value[:3] in {'"""', "'''"} and "\n" in value
3294
3295
3296 def is_stub_suite(node: Node) -> bool:
3297     """Return True if `node` is a suite with a stub body."""
3298     if (
3299         len(node.children) != 4
3300         or node.children[0].type != token.NEWLINE
3301         or node.children[1].type != token.INDENT
3302         or node.children[3].type != token.DEDENT
3303     ):
3304         return False
3305
3306     return is_stub_body(node.children[2])
3307
3308
3309 def is_stub_body(node: LN) -> bool:
3310     """Return True if `node` is a simple statement containing an ellipsis."""
3311     if not isinstance(node, Node) or node.type != syms.simple_stmt:
3312         return False
3313
3314     if len(node.children) != 2:
3315         return False
3316
3317     child = node.children[0]
3318     return (
3319         child.type == syms.atom
3320         and len(child.children) == 3
3321         and all(leaf == Leaf(token.DOT, ".") for leaf in child.children)
3322     )
3323
3324
3325 def max_delimiter_priority_in_atom(node: LN) -> Priority:
3326     """Return maximum delimiter priority inside `node`.
3327
3328     This is specific to atoms with contents contained in a pair of parentheses.
3329     If `node` isn't an atom or there are no enclosing parentheses, returns 0.
3330     """
3331     if node.type != syms.atom:
3332         return 0
3333
3334     first = node.children[0]
3335     last = node.children[-1]
3336     if not (first.type == token.LPAR and last.type == token.RPAR):
3337         return 0
3338
3339     bt = BracketTracker()
3340     for c in node.children[1:-1]:
3341         if isinstance(c, Leaf):
3342             bt.mark(c)
3343         else:
3344             for leaf in c.leaves():
3345                 bt.mark(leaf)
3346     try:
3347         return bt.max_delimiter_priority()
3348
3349     except ValueError:
3350         return 0
3351
3352
3353 def ensure_visible(leaf: Leaf) -> None:
3354     """Make sure parentheses are visible.
3355
3356     They could be invisible as part of some statements (see
3357     :func:`normalize_invisible_parens` and :func:`visit_import_from`).
3358     """
3359     if leaf.type == token.LPAR:
3360         leaf.value = "("
3361     elif leaf.type == token.RPAR:
3362         leaf.value = ")"
3363
3364
3365 def should_explode(line: Line, opening_bracket: Leaf) -> bool:
3366     """Should `line` immediately be split with `delimiter_split()` after RHS?"""
3367
3368     if not (
3369         opening_bracket.parent
3370         and opening_bracket.parent.type in {syms.atom, syms.import_from}
3371         and opening_bracket.value in "[{("
3372     ):
3373         return False
3374
3375     try:
3376         last_leaf = line.leaves[-1]
3377         exclude = {id(last_leaf)} if last_leaf.type == token.COMMA else set()
3378         max_priority = line.bracket_tracker.max_delimiter_priority(exclude=exclude)
3379     except (IndexError, ValueError):
3380         return False
3381
3382     return max_priority == COMMA_PRIORITY
3383
3384
3385 def get_features_used(node: Node) -> Set[Feature]:
3386     """Return a set of (relatively) new Python features used in this file.
3387
3388     Currently looking for:
3389     - f-strings;
3390     - underscores in numeric literals;
3391     - trailing commas after * or ** in function signatures and calls;
3392     - positional only arguments in function signatures and lambdas;
3393     """
3394     features: Set[Feature] = set()
3395     for n in node.pre_order():
3396         if n.type == token.STRING:
3397             value_head = n.value[:2]  # type: ignore
3398             if value_head in {'f"', 'F"', "f'", "F'", "rf", "fr", "RF", "FR"}:
3399                 features.add(Feature.F_STRINGS)
3400
3401         elif n.type == token.NUMBER:
3402             if "_" in n.value:  # type: ignore
3403                 features.add(Feature.NUMERIC_UNDERSCORES)
3404
3405         elif n.type == token.SLASH:
3406             if n.parent and n.parent.type in {syms.typedargslist, syms.arglist}:
3407                 features.add(Feature.POS_ONLY_ARGUMENTS)
3408
3409         elif n.type == token.COLONEQUAL:
3410             features.add(Feature.ASSIGNMENT_EXPRESSIONS)
3411
3412         elif (
3413             n.type in {syms.typedargslist, syms.arglist}
3414             and n.children
3415             and n.children[-1].type == token.COMMA
3416         ):
3417             if n.type == syms.typedargslist:
3418                 feature = Feature.TRAILING_COMMA_IN_DEF
3419             else:
3420                 feature = Feature.TRAILING_COMMA_IN_CALL
3421
3422             for ch in n.children:
3423                 if ch.type in STARS:
3424                     features.add(feature)
3425
3426                 if ch.type == syms.argument:
3427                     for argch in ch.children:
3428                         if argch.type in STARS:
3429                             features.add(feature)
3430
3431     return features
3432
3433
3434 def detect_target_versions(node: Node) -> Set[TargetVersion]:
3435     """Detect the version to target based on the nodes used."""
3436     features = get_features_used(node)
3437     return {
3438         version for version in TargetVersion if features <= VERSION_TO_FEATURES[version]
3439     }
3440
3441
3442 def generate_trailers_to_omit(line: Line, line_length: int) -> Iterator[Set[LeafID]]:
3443     """Generate sets of closing bracket IDs that should be omitted in a RHS.
3444
3445     Brackets can be omitted if the entire trailer up to and including
3446     a preceding closing bracket fits in one line.
3447
3448     Yielded sets are cumulative (contain results of previous yields, too).  First
3449     set is empty.
3450     """
3451
3452     omit: Set[LeafID] = set()
3453     yield omit
3454
3455     length = 4 * line.depth
3456     opening_bracket: Optional[Leaf] = None
3457     closing_bracket: Optional[Leaf] = None
3458     inner_brackets: Set[LeafID] = set()
3459     for index, leaf, leaf_length in enumerate_with_length(line, reversed=True):
3460         length += leaf_length
3461         if length > line_length:
3462             break
3463
3464         has_inline_comment = leaf_length > len(leaf.value) + len(leaf.prefix)
3465         if leaf.type == STANDALONE_COMMENT or has_inline_comment:
3466             break
3467
3468         if opening_bracket:
3469             if leaf is opening_bracket:
3470                 opening_bracket = None
3471             elif leaf.type in CLOSING_BRACKETS:
3472                 inner_brackets.add(id(leaf))
3473         elif leaf.type in CLOSING_BRACKETS:
3474             if index > 0 and line.leaves[index - 1].type in OPENING_BRACKETS:
3475                 # Empty brackets would fail a split so treat them as "inner"
3476                 # brackets (e.g. only add them to the `omit` set if another
3477                 # pair of brackets was good enough.
3478                 inner_brackets.add(id(leaf))
3479                 continue
3480
3481             if closing_bracket:
3482                 omit.add(id(closing_bracket))
3483                 omit.update(inner_brackets)
3484                 inner_brackets.clear()
3485                 yield omit
3486
3487             if leaf.value:
3488                 opening_bracket = leaf.opening_bracket
3489                 closing_bracket = leaf
3490
3491
3492 def get_future_imports(node: Node) -> Set[str]:
3493     """Return a set of __future__ imports in the file."""
3494     imports: Set[str] = set()
3495
3496     def get_imports_from_children(children: List[LN]) -> Generator[str, None, None]:
3497         for child in children:
3498             if isinstance(child, Leaf):
3499                 if child.type == token.NAME:
3500                     yield child.value
3501
3502             elif child.type == syms.import_as_name:
3503                 orig_name = child.children[0]
3504                 assert isinstance(orig_name, Leaf), "Invalid syntax parsing imports"
3505                 assert orig_name.type == token.NAME, "Invalid syntax parsing imports"
3506                 yield orig_name.value
3507
3508             elif child.type == syms.import_as_names:
3509                 yield from get_imports_from_children(child.children)
3510
3511             else:
3512                 raise AssertionError("Invalid syntax parsing imports")
3513
3514     for child in node.children:
3515         if child.type != syms.simple_stmt:
3516             break
3517
3518         first_child = child.children[0]
3519         if isinstance(first_child, Leaf):
3520             # Continue looking if we see a docstring; otherwise stop.
3521             if (
3522                 len(child.children) == 2
3523                 and first_child.type == token.STRING
3524                 and child.children[1].type == token.NEWLINE
3525             ):
3526                 continue
3527
3528             break
3529
3530         elif first_child.type == syms.import_from:
3531             module_name = first_child.children[1]
3532             if not isinstance(module_name, Leaf) or module_name.value != "__future__":
3533                 break
3534
3535             imports |= set(get_imports_from_children(first_child.children[3:]))
3536         else:
3537             break
3538
3539     return imports
3540
3541
3542 @lru_cache()
3543 def get_gitignore(root: Path) -> PathSpec:
3544     """ Return a PathSpec matching gitignore content if present."""
3545     gitignore = root / ".gitignore"
3546     lines: List[str] = []
3547     if gitignore.is_file():
3548         with gitignore.open() as gf:
3549             lines = gf.readlines()
3550     return PathSpec.from_lines("gitwildmatch", lines)
3551
3552
3553 def gen_python_files_in_dir(
3554     path: Path,
3555     root: Path,
3556     include: Pattern[str],
3557     exclude: Pattern[str],
3558     report: "Report",
3559     gitignore: PathSpec,
3560 ) -> Iterator[Path]:
3561     """Generate all files under `path` whose paths are not excluded by the
3562     `exclude` regex, but are included by the `include` regex.
3563
3564     Symbolic links pointing outside of the `root` directory are ignored.
3565
3566     `report` is where output about exclusions goes.
3567     """
3568     assert root.is_absolute(), f"INTERNAL ERROR: `root` must be absolute but is {root}"
3569     for child in path.iterdir():
3570         # First ignore files matching .gitignore
3571         if gitignore.match_file(child.as_posix()):
3572             report.path_ignored(child, f"matches the .gitignore file content")
3573             continue
3574
3575         # Then ignore with `exclude` option.
3576         try:
3577             normalized_path = "/" + child.resolve().relative_to(root).as_posix()
3578         except OSError as e:
3579             report.path_ignored(child, f"cannot be read because {e}")
3580             continue
3581
3582         except ValueError:
3583             if child.is_symlink():
3584                 report.path_ignored(
3585                     child, f"is a symbolic link that points outside {root}"
3586                 )
3587                 continue
3588
3589             raise
3590
3591         if child.is_dir():
3592             normalized_path += "/"
3593
3594         exclude_match = exclude.search(normalized_path)
3595         if exclude_match and exclude_match.group(0):
3596             report.path_ignored(child, f"matches the --exclude regular expression")
3597             continue
3598
3599         if child.is_dir():
3600             yield from gen_python_files_in_dir(
3601                 child, root, include, exclude, report, gitignore
3602             )
3603
3604         elif child.is_file():
3605             include_match = include.search(normalized_path)
3606             if include_match:
3607                 yield child
3608
3609
3610 @lru_cache()
3611 def find_project_root(srcs: Iterable[str]) -> Path:
3612     """Return a directory containing .git, .hg, or pyproject.toml.
3613
3614     That directory can be one of the directories passed in `srcs` or their
3615     common parent.
3616
3617     If no directory in the tree contains a marker that would specify it's the
3618     project root, the root of the file system is returned.
3619     """
3620     if not srcs:
3621         return Path("/").resolve()
3622
3623     common_base = min(Path(src).resolve() for src in srcs)
3624     if common_base.is_dir():
3625         # Append a fake file so `parents` below returns `common_base_dir`, too.
3626         common_base /= "fake-file"
3627     for directory in common_base.parents:
3628         if (directory / ".git").exists():
3629             return directory
3630
3631         if (directory / ".hg").is_dir():
3632             return directory
3633
3634         if (directory / "pyproject.toml").is_file():
3635             return directory
3636
3637     return directory
3638
3639
3640 @dataclass
3641 class Report:
3642     """Provides a reformatting counter. Can be rendered with `str(report)`."""
3643
3644     check: bool = False
3645     diff: bool = False
3646     quiet: bool = False
3647     verbose: bool = False
3648     change_count: int = 0
3649     same_count: int = 0
3650     failure_count: int = 0
3651
3652     def done(self, src: Path, changed: Changed) -> None:
3653         """Increment the counter for successful reformatting. Write out a message."""
3654         if changed is Changed.YES:
3655             reformatted = "would reformat" if self.check or self.diff else "reformatted"
3656             if self.verbose or not self.quiet:
3657                 out(f"{reformatted} {src}")
3658             self.change_count += 1
3659         else:
3660             if self.verbose:
3661                 if changed is Changed.NO:
3662                     msg = f"{src} already well formatted, good job."
3663                 else:
3664                     msg = f"{src} wasn't modified on disk since last run."
3665                 out(msg, bold=False)
3666             self.same_count += 1
3667
3668     def failed(self, src: Path, message: str) -> None:
3669         """Increment the counter for failed reformatting. Write out a message."""
3670         err(f"error: cannot format {src}: {message}")
3671         self.failure_count += 1
3672
3673     def path_ignored(self, path: Path, message: str) -> None:
3674         if self.verbose:
3675             out(f"{path} ignored: {message}", bold=False)
3676
3677     @property
3678     def return_code(self) -> int:
3679         """Return the exit code that the app should use.
3680
3681         This considers the current state of changed files and failures:
3682         - if there were any failures, return 123;
3683         - if any files were changed and --check is being used, return 1;
3684         - otherwise return 0.
3685         """
3686         # According to http://tldp.org/LDP/abs/html/exitcodes.html starting with
3687         # 126 we have special return codes reserved by the shell.
3688         if self.failure_count:
3689             return 123
3690
3691         elif self.change_count and self.check:
3692             return 1
3693
3694         return 0
3695
3696     def __str__(self) -> str:
3697         """Render a color report of the current state.
3698
3699         Use `click.unstyle` to remove colors.
3700         """
3701         if self.check or self.diff:
3702             reformatted = "would be reformatted"
3703             unchanged = "would be left unchanged"
3704             failed = "would fail to reformat"
3705         else:
3706             reformatted = "reformatted"
3707             unchanged = "left unchanged"
3708             failed = "failed to reformat"
3709         report = []
3710         if self.change_count:
3711             s = "s" if self.change_count > 1 else ""
3712             report.append(
3713                 click.style(f"{self.change_count} file{s} {reformatted}", bold=True)
3714             )
3715         if self.same_count:
3716             s = "s" if self.same_count > 1 else ""
3717             report.append(f"{self.same_count} file{s} {unchanged}")
3718         if self.failure_count:
3719             s = "s" if self.failure_count > 1 else ""
3720             report.append(
3721                 click.style(f"{self.failure_count} file{s} {failed}", fg="red")
3722             )
3723         return ", ".join(report) + "."
3724
3725
3726 def parse_ast(src: str) -> Union[ast.AST, ast3.AST, ast27.AST]:
3727     filename = "<unknown>"
3728     if sys.version_info >= (3, 8):
3729         # TODO: support Python 4+ ;)
3730         for minor_version in range(sys.version_info[1], 4, -1):
3731             try:
3732                 return ast.parse(src, filename, feature_version=(3, minor_version))
3733             except SyntaxError:
3734                 continue
3735     else:
3736         for feature_version in (7, 6):
3737             try:
3738                 return ast3.parse(src, filename, feature_version=feature_version)
3739             except SyntaxError:
3740                 continue
3741
3742     return ast27.parse(src)
3743
3744
3745 def _fixup_ast_constants(
3746     node: Union[ast.AST, ast3.AST, ast27.AST]
3747 ) -> Union[ast.AST, ast3.AST, ast27.AST]:
3748     """Map ast nodes deprecated in 3.8 to Constant."""
3749     if isinstance(node, (ast.Str, ast3.Str, ast27.Str, ast.Bytes, ast3.Bytes)):
3750         return ast.Constant(value=node.s)
3751
3752     if isinstance(node, (ast.Num, ast3.Num, ast27.Num)):
3753         return ast.Constant(value=node.n)
3754
3755     if isinstance(node, (ast.NameConstant, ast3.NameConstant)):
3756         return ast.Constant(value=node.value)
3757
3758     return node
3759
3760
3761 def assert_equivalent(src: str, dst: str) -> None:
3762     """Raise AssertionError if `src` and `dst` aren't equivalent."""
3763
3764     def _v(node: Union[ast.AST, ast3.AST, ast27.AST], depth: int = 0) -> Iterator[str]:
3765         """Simple visitor generating strings to compare ASTs by content."""
3766
3767         node = _fixup_ast_constants(node)
3768
3769         yield f"{'  ' * depth}{node.__class__.__name__}("
3770
3771         for field in sorted(node._fields):  # noqa: F402
3772             # TypeIgnore has only one field 'lineno' which breaks this comparison
3773             type_ignore_classes = (ast3.TypeIgnore, ast27.TypeIgnore)
3774             if sys.version_info >= (3, 8):
3775                 type_ignore_classes += (ast.TypeIgnore,)
3776             if isinstance(node, type_ignore_classes):
3777                 break
3778
3779             try:
3780                 value = getattr(node, field)
3781             except AttributeError:
3782                 continue
3783
3784             yield f"{'  ' * (depth+1)}{field}="
3785
3786             if isinstance(value, list):
3787                 for item in value:
3788                     # Ignore nested tuples within del statements, because we may insert
3789                     # parentheses and they change the AST.
3790                     if (
3791                         field == "targets"
3792                         and isinstance(node, (ast.Delete, ast3.Delete, ast27.Delete))
3793                         and isinstance(item, (ast.Tuple, ast3.Tuple, ast27.Tuple))
3794                     ):
3795                         for item in item.elts:
3796                             yield from _v(item, depth + 2)
3797
3798                     elif isinstance(item, (ast.AST, ast3.AST, ast27.AST)):
3799                         yield from _v(item, depth + 2)
3800
3801             elif isinstance(value, (ast.AST, ast3.AST, ast27.AST)):
3802                 yield from _v(value, depth + 2)
3803
3804             else:
3805                 yield f"{'  ' * (depth+2)}{value!r},  # {value.__class__.__name__}"
3806
3807         yield f"{'  ' * depth})  # /{node.__class__.__name__}"
3808
3809     try:
3810         src_ast = parse_ast(src)
3811     except Exception as exc:
3812         raise AssertionError(
3813             f"cannot use --safe with this file; failed to parse source file.  "
3814             f"AST error message: {exc}"
3815         )
3816
3817     try:
3818         dst_ast = parse_ast(dst)
3819     except Exception as exc:
3820         log = dump_to_file("".join(traceback.format_tb(exc.__traceback__)), dst)
3821         raise AssertionError(
3822             f"INTERNAL ERROR: Black produced invalid code: {exc}. "
3823             f"Please report a bug on https://github.com/psf/black/issues.  "
3824             f"This invalid output might be helpful: {log}"
3825         ) from None
3826
3827     src_ast_str = "\n".join(_v(src_ast))
3828     dst_ast_str = "\n".join(_v(dst_ast))
3829     if src_ast_str != dst_ast_str:
3830         log = dump_to_file(diff(src_ast_str, dst_ast_str, "src", "dst"))
3831         raise AssertionError(
3832             f"INTERNAL ERROR: Black produced code that is not equivalent to "
3833             f"the source.  "
3834             f"Please report a bug on https://github.com/psf/black/issues.  "
3835             f"This diff might be helpful: {log}"
3836         ) from None
3837
3838
3839 def assert_stable(src: str, dst: str, mode: FileMode) -> None:
3840     """Raise AssertionError if `dst` reformats differently the second time."""
3841     newdst = format_str(dst, mode=mode)
3842     if dst != newdst:
3843         log = dump_to_file(
3844             diff(src, dst, "source", "first pass"),
3845             diff(dst, newdst, "first pass", "second pass"),
3846         )
3847         raise AssertionError(
3848             f"INTERNAL ERROR: Black produced different code on the second pass "
3849             f"of the formatter.  "
3850             f"Please report a bug on https://github.com/psf/black/issues.  "
3851             f"This diff might be helpful: {log}"
3852         ) from None
3853
3854
3855 @mypyc_attr(patchable=True)
3856 def dump_to_file(*output: str) -> str:
3857     """Dump `output` to a temporary file. Return path to the file."""
3858     with tempfile.NamedTemporaryFile(
3859         mode="w", prefix="blk_", suffix=".log", delete=False, encoding="utf8"
3860     ) as f:
3861         for lines in output:
3862             f.write(lines)
3863             if lines and lines[-1] != "\n":
3864                 f.write("\n")
3865     return f.name
3866
3867
3868 @contextmanager
3869 def nullcontext() -> Iterator[None]:
3870     """Return an empty context manager.
3871
3872     To be used like `nullcontext` in Python 3.7.
3873     """
3874     yield
3875
3876
3877 def diff(a: str, b: str, a_name: str, b_name: str) -> str:
3878     """Return a unified diff string between strings `a` and `b`."""
3879     import difflib
3880
3881     a_lines = [line + "\n" for line in a.split("\n")]
3882     b_lines = [line + "\n" for line in b.split("\n")]
3883     return "".join(
3884         difflib.unified_diff(a_lines, b_lines, fromfile=a_name, tofile=b_name, n=5)
3885     )
3886
3887
3888 def cancel(tasks: Iterable["asyncio.Task[Any]"]) -> None:
3889     """asyncio signal handler that cancels all `tasks` and reports to stderr."""
3890     err("Aborted!")
3891     for task in tasks:
3892         task.cancel()
3893
3894
3895 def shutdown(loop: asyncio.AbstractEventLoop) -> None:
3896     """Cancel all pending tasks on `loop`, wait for them, and close the loop."""
3897     try:
3898         if sys.version_info[:2] >= (3, 7):
3899             all_tasks = asyncio.all_tasks
3900         else:
3901             all_tasks = asyncio.Task.all_tasks
3902         # This part is borrowed from asyncio/runners.py in Python 3.7b2.
3903         to_cancel = [task for task in all_tasks(loop) if not task.done()]
3904         if not to_cancel:
3905             return
3906
3907         for task in to_cancel:
3908             task.cancel()
3909         loop.run_until_complete(
3910             asyncio.gather(*to_cancel, loop=loop, return_exceptions=True)
3911         )
3912     finally:
3913         # `concurrent.futures.Future` objects cannot be cancelled once they
3914         # are already running. There might be some when the `shutdown()` happened.
3915         # Silence their logger's spew about the event loop being closed.
3916         cf_logger = logging.getLogger("concurrent.futures")
3917         cf_logger.setLevel(logging.CRITICAL)
3918         loop.close()
3919
3920
3921 def sub_twice(regex: Pattern[str], replacement: str, original: str) -> str:
3922     """Replace `regex` with `replacement` twice on `original`.
3923
3924     This is used by string normalization to perform replaces on
3925     overlapping matches.
3926     """
3927     return regex.sub(replacement, regex.sub(replacement, original))
3928
3929
3930 def re_compile_maybe_verbose(regex: str) -> Pattern[str]:
3931     """Compile a regular expression string in `regex`.
3932
3933     If it contains newlines, use verbose mode.
3934     """
3935     if "\n" in regex:
3936         regex = "(?x)" + regex
3937     compiled: Pattern[str] = re.compile(regex)
3938     return compiled
3939
3940
3941 def enumerate_reversed(sequence: Sequence[T]) -> Iterator[Tuple[Index, T]]:
3942     """Like `reversed(enumerate(sequence))` if that were possible."""
3943     index = len(sequence) - 1
3944     for element in reversed(sequence):
3945         yield (index, element)
3946         index -= 1
3947
3948
3949 def enumerate_with_length(
3950     line: Line, reversed: bool = False
3951 ) -> Iterator[Tuple[Index, Leaf, int]]:
3952     """Return an enumeration of leaves with their length.
3953
3954     Stops prematurely on multiline strings and standalone comments.
3955     """
3956     op = cast(
3957         Callable[[Sequence[Leaf]], Iterator[Tuple[Index, Leaf]]],
3958         enumerate_reversed if reversed else enumerate,
3959     )
3960     for index, leaf in op(line.leaves):
3961         length = len(leaf.prefix) + len(leaf.value)
3962         if "\n" in leaf.value:
3963             return  # Multiline strings, we can't continue.
3964
3965         for comment in line.comments_after(leaf):
3966             length += len(comment.value)
3967
3968         yield index, leaf, length
3969
3970
3971 def is_line_short_enough(line: Line, *, line_length: int, line_str: str = "") -> bool:
3972     """Return True if `line` is no longer than `line_length`.
3973
3974     Uses the provided `line_str` rendering, if any, otherwise computes a new one.
3975     """
3976     if not line_str:
3977         line_str = str(line).strip("\n")
3978     return (
3979         len(line_str) <= line_length
3980         and "\n" not in line_str  # multiline strings
3981         and not line.contains_standalone_comments()
3982     )
3983
3984
3985 def can_be_split(line: Line) -> bool:
3986     """Return False if the line cannot be split *for sure*.
3987
3988     This is not an exhaustive search but a cheap heuristic that we can use to
3989     avoid some unfortunate formattings (mostly around wrapping unsplittable code
3990     in unnecessary parentheses).
3991     """
3992     leaves = line.leaves
3993     if len(leaves) < 2:
3994         return False
3995
3996     if leaves[0].type == token.STRING and leaves[1].type == token.DOT:
3997         call_count = 0
3998         dot_count = 0
3999         next = leaves[-1]
4000         for leaf in leaves[-2::-1]:
4001             if leaf.type in OPENING_BRACKETS:
4002                 if next.type not in CLOSING_BRACKETS:
4003                     return False
4004
4005                 call_count += 1
4006             elif leaf.type == token.DOT:
4007                 dot_count += 1
4008             elif leaf.type == token.NAME:
4009                 if not (next.type == token.DOT or next.type in OPENING_BRACKETS):
4010                     return False
4011
4012             elif leaf.type not in CLOSING_BRACKETS:
4013                 return False
4014
4015             if dot_count > 1 and call_count > 1:
4016                 return False
4017
4018     return True
4019
4020
4021 def can_omit_invisible_parens(line: Line, line_length: int) -> bool:
4022     """Does `line` have a shape safe to reformat without optional parens around it?
4023
4024     Returns True for only a subset of potentially nice looking formattings but
4025     the point is to not return false positives that end up producing lines that
4026     are too long.
4027     """
4028     bt = line.bracket_tracker
4029     if not bt.delimiters:
4030         # Without delimiters the optional parentheses are useless.
4031         return True
4032
4033     max_priority = bt.max_delimiter_priority()
4034     if bt.delimiter_count_with_priority(max_priority) > 1:
4035         # With more than one delimiter of a kind the optional parentheses read better.
4036         return False
4037
4038     if max_priority == DOT_PRIORITY:
4039         # A single stranded method call doesn't require optional parentheses.
4040         return True
4041
4042     assert len(line.leaves) >= 2, "Stranded delimiter"
4043
4044     first = line.leaves[0]
4045     second = line.leaves[1]
4046     penultimate = line.leaves[-2]
4047     last = line.leaves[-1]
4048
4049     # With a single delimiter, omit if the expression starts or ends with
4050     # a bracket.
4051     if first.type in OPENING_BRACKETS and second.type not in CLOSING_BRACKETS:
4052         remainder = False
4053         length = 4 * line.depth
4054         for _index, leaf, leaf_length in enumerate_with_length(line):
4055             if leaf.type in CLOSING_BRACKETS and leaf.opening_bracket is first:
4056                 remainder = True
4057             if remainder:
4058                 length += leaf_length
4059                 if length > line_length:
4060                     break
4061
4062                 if leaf.type in OPENING_BRACKETS:
4063                     # There are brackets we can further split on.
4064                     remainder = False
4065
4066         else:
4067             # checked the entire string and line length wasn't exceeded
4068             if len(line.leaves) == _index + 1:
4069                 return True
4070
4071         # Note: we are not returning False here because a line might have *both*
4072         # a leading opening bracket and a trailing closing bracket.  If the
4073         # opening bracket doesn't match our rule, maybe the closing will.
4074
4075     if (
4076         last.type == token.RPAR
4077         or last.type == token.RBRACE
4078         or (
4079             # don't use indexing for omitting optional parentheses;
4080             # it looks weird
4081             last.type == token.RSQB
4082             and last.parent
4083             and last.parent.type != syms.trailer
4084         )
4085     ):
4086         if penultimate.type in OPENING_BRACKETS:
4087             # Empty brackets don't help.
4088             return False
4089
4090         if is_multiline_string(first):
4091             # Additional wrapping of a multiline string in this situation is
4092             # unnecessary.
4093             return True
4094
4095         length = 4 * line.depth
4096         seen_other_brackets = False
4097         for _index, leaf, leaf_length in enumerate_with_length(line):
4098             length += leaf_length
4099             if leaf is last.opening_bracket:
4100                 if seen_other_brackets or length <= line_length:
4101                     return True
4102
4103             elif leaf.type in OPENING_BRACKETS:
4104                 # There are brackets we can further split on.
4105                 seen_other_brackets = True
4106
4107     return False
4108
4109
4110 def get_cache_file(mode: FileMode) -> Path:
4111     return CACHE_DIR / f"cache.{mode.get_cache_key()}.pickle"
4112
4113
4114 def read_cache(mode: FileMode) -> Cache:
4115     """Read the cache if it exists and is well formed.
4116
4117     If it is not well formed, the call to write_cache later should resolve the issue.
4118     """
4119     cache_file = get_cache_file(mode)
4120     if not cache_file.exists():
4121         return {}
4122
4123     with cache_file.open("rb") as fobj:
4124         try:
4125             cache: Cache = pickle.load(fobj)
4126         except (pickle.UnpicklingError, ValueError):
4127             return {}
4128
4129     return cache
4130
4131
4132 def get_cache_info(path: Path) -> CacheInfo:
4133     """Return the information used to check if a file is already formatted or not."""
4134     stat = path.stat()
4135     return stat.st_mtime, stat.st_size
4136
4137
4138 def filter_cached(cache: Cache, sources: Iterable[Path]) -> Tuple[Set[Path], Set[Path]]:
4139     """Split an iterable of paths in `sources` into two sets.
4140
4141     The first contains paths of files that modified on disk or are not in the
4142     cache. The other contains paths to non-modified files.
4143     """
4144     todo, done = set(), set()
4145     for src in sources:
4146         src = src.resolve()
4147         if cache.get(src) != get_cache_info(src):
4148             todo.add(src)
4149         else:
4150             done.add(src)
4151     return todo, done
4152
4153
4154 def write_cache(cache: Cache, sources: Iterable[Path], mode: FileMode) -> None:
4155     """Update the cache file."""
4156     cache_file = get_cache_file(mode)
4157     try:
4158         CACHE_DIR.mkdir(parents=True, exist_ok=True)
4159         new_cache = {**cache, **{src.resolve(): get_cache_info(src) for src in sources}}
4160         with tempfile.NamedTemporaryFile(dir=str(cache_file.parent), delete=False) as f:
4161             pickle.dump(new_cache, f, protocol=4)
4162         os.replace(f.name, cache_file)
4163     except OSError:
4164         pass
4165
4166
4167 def patch_click() -> None:
4168     """Make Click not crash.
4169
4170     On certain misconfigured environments, Python 3 selects the ASCII encoding as the
4171     default which restricts paths that it can access during the lifetime of the
4172     application.  Click refuses to work in this scenario by raising a RuntimeError.
4173
4174     In case of Black the likelihood that non-ASCII characters are going to be used in
4175     file paths is minimal since it's Python source code.  Moreover, this crash was
4176     spurious on Python 3.7 thanks to PEP 538 and PEP 540.
4177     """
4178     try:
4179         from click import core
4180         from click import _unicodefun  # type: ignore
4181     except ModuleNotFoundError:
4182         return
4183
4184     for module in (core, _unicodefun):
4185         if hasattr(module, "_verify_python3_env"):
4186             module._verify_python3_env = lambda: None
4187
4188
4189 def patched_main() -> None:
4190     freeze_support()
4191     patch_click()
4192     main()
4193
4194
4195 if __name__ == "__main__":
4196     patched_main()