src/black/concurrency.py
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | Formatting many files at once via multiprocessing. Contains entrypoint and utilities.
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | NOTE: this module is only imported if we need to format several files at once.
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | """
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | import asyncio
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | import logging
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | import os
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | import signal
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | import sys
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | import traceback
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from concurrent.futures import Executor, ProcessPoolExecutor, ThreadPoolExecutor
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from multiprocessing import Manager
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from pathlib import Path
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from typing import Any, Iterable, Optional, Set
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from mypy_extensions import mypyc_attr
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from black import WriteBack, format_file_in_place
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from black.cache import Cache
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from black.mode import Mode
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from black.output import err
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | from black.report import Changed, Report
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
0012 0007 0006 0000 0004 0002 0000 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def maybe_install_uvloop() -> None:
0012 0007 0006 0000 0004 0002 0000 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """If our environment has uvloop installed we use it.
0012 0007 0006 0000 0004 0002 0000 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0012 0007 0006 0000 0004 0002 0000 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | This is called only from command-line entry points to avoid
0012 0007 0006 0000 0004 0002 0000 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | interfering with the parent process if Black is used as a library.
0012 0007 0006 0000 0004 0002 0000 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
0012 0007 0006 0000 0004 0002 0000 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | try:
0012 0007 0006 0000 0004 0002 0000 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | import uvloop
0012 0007 0006 0000 0004 0002 0000 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
0012 0007 0006 0000 0004 0002 0000 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | uvloop.install()
0012 0007 0006 0000 0004 0002 0000 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | except ImportError:
0012 0007 0006 0000 0004 0002 0000 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | pass
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
0005 0005 0004 0000 0000 0000 0001 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def cancel(tasks: Iterable["asyncio.Future[Any]"]) -> None:
0005 0005 0004 0000 0000 0000 0001 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """asyncio signal handler that cancels all `tasks` and reports to stderr."""
0005 0005 0004 0000 0000 0000 0001 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | err("Aborted!")
0005 0005 0004 0000 0000 0000 0001 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | for task in tasks:
0005 0005 0004 0000 0000 0000 0001 -- 02 000 000 000 000 000 000 0000.00 0000.00 0000.00 | task.cancel()
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | def shutdown(loop: asyncio.AbstractEventLoop) -> None:
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | """Cancel all pending tasks on `loop`, wait for them, and close the loop."""
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | try:
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | # This part is borrowed from asyncio/runners.py in Python 3.7b2.
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | to_cancel = [task for task in asyncio.all_tasks(loop) if not task.done()]
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | if not to_cancel:
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | return
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 |
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | for task in to_cancel:
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | task.cancel()
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | loop.run_until_complete(asyncio.gather(*to_cancel, return_exceptions=True))
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | finally:
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | # `concurrent.futures.Future` objects cannot be cancelled once they
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | # are already running. There might be some when the `shutdown()` happened.
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | # Silence their logger's spew about the event loop being closed.
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | cf_logger = logging.getLogger("concurrent.futures")
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | cf_logger.setLevel(logging.CRITICAL)
0022 0013 0012 0006 0000 0003 0007 -- 05 001 002 002 002 003 004 0006.34 0003.17 0000.50 | loop.close()
0022 0013 0012 0006 0000 0003 0007 -- -- --- --- --- --- --- --- ------- ------- ------- |
0022 0013 0012 0006 0000 0003 0007 -- -- --- --- --- --- --- --- ------- ------- ------- |
0022 0013 0012 0006 0000 0003 0007 -- -- --- --- --- --- --- --- ------- ------- ------- | # diff-shades depends on being to monkeypatch this function to operate. I know it's
0022 0013 0012 0006 0000 0003 0007 -- -- --- --- --- --- --- --- ------- ------- ------- | # not ideal, but this shouldn't cause any issues ... hopefully. ~ichard26
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- | @mypyc_attr(patchable=True)
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | def reformat_many(
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | sources: Set[Path],
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | fast: bool,
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | write_back: WriteBack,
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | mode: Mode,
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | report: Report,
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | workers: Optional[int],
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | ) -> None:
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | """Reformat multiple files using a ProcessPoolExecutor."""
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | maybe_install_uvloop()
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 |
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | executor: Executor
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | if workers is None:
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | workers = int(os.environ.get("BLACK_NUM_WORKERS", 0))
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | workers = workers or os.cpu_count() or 1
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | if sys.platform == "win32":
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | # Work around https://bugs.python.org/issue26903
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | workers = min(workers, 60)
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | try:
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | executor = ProcessPoolExecutor(max_workers=workers)
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | except (ImportError, NotImplementedError, OSError):
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | # we arrive here if the underlying system does not support multi-processing
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | # like in AWS Lambda or Termux, in which case we gracefully fallback to
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | # a ThreadPoolExecutor with just a single worker (more workers would not do us
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | # any good due to the Global Interpreter Lock)
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | executor = ThreadPoolExecutor(max_workers=1)
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 |
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | loop = asyncio.new_event_loop()
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | asyncio.set_event_loop(loop)
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | try:
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | loop.run_until_complete(
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | schedule_formatting(
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | sources=sources,
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | fast=fast,
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | write_back=write_back,
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | mode=mode,
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | report=report,
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | loop=loop,
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | executor=executor,
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | )
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | )
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | finally:
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | try:
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | shutdown(loop)
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | finally:
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | asyncio.set_event_loop(None)
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | if executor is not None:
0049 0026 0041 0005 0000 0002 0006 -- 07 004 007 004 009 011 013 0044.97 0115.64 0002.57 | executor.shutdown()
0049 0026 0041 0005 0000 0002 0006 -- -- --- --- --- --- --- --- ------- ------- ------- |
---- ---- ---- ---- ---- ---- ---- -- -- --- --- --- --- --- --- ------- ------- ------- |
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | async def schedule_formatting(
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | sources: Set[Path],
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | fast: bool,
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | write_back: WriteBack,
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | mode: Mode,
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | report: "Report",
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | loop: asyncio.AbstractEventLoop,
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | executor: "Executor",
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | ) -> None:
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | """Run formatting of `sources` in parallel using the provided `executor`.
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 |
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | (Use ProcessPoolExecutors for actual parallelism.)
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 |
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | `write_back`, `fast`, and `mode` options are passed to
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | :func:`format_file_in_place`.
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | """
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | cache = Cache.read(mode)
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | if write_back not in (WriteBack.DIFF, WriteBack.COLOR_DIFF):
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | sources, cached = cache.filtered_cached(sources)
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | for src in sorted(cached):
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | report.done(src, Changed.CACHED)
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | if not sources:
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | return
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 |
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | cancelled = []
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | sources_to_cache = []
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | lock = None
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | if write_back in (WriteBack.DIFF, WriteBack.COLOR_DIFF):
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | # For diff output, we need locks to ensure we don't interleave output
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | # from different processes.
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | manager = Manager()
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | lock = manager.Lock()
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | tasks = {
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | asyncio.ensure_future(
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | loop.run_in_executor(
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | executor, format_file_in_place, src, fast, mode, write_back, lock
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | )
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | ): src
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | for src in sorted(sources)
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | }
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | pending = tasks.keys()
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | try:
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | loop.add_signal_handler(signal.SIGINT, cancel, pending)
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | loop.add_signal_handler(signal.SIGTERM, cancel, pending)
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | except NotImplementedError:
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | # There are no good alternatives for these on Windows.
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | pass
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | while pending:
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | done, _ = await asyncio.wait(pending, return_when=asyncio.FIRST_COMPLETED)
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | for task in done:
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | src = tasks.pop(task)
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | if task.cancelled():
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | cancelled.append(task)
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | elif exc := task.exception():
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | if report.verbose:
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | traceback.print_exception(type(exc), exc, exc.__traceback__)
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | report.failed(src, str(exc))
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | else:
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | changed = Changed.YES if task.result() else Changed.NO
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | # If the file was written back or was successfully checked as
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | # well-formatted, store this information in the cache.
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | if write_back is WriteBack.YES or (
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | write_back is WriteBack.CHECK and changed is Changed.NO
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | ):
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | sources_to_cache.append(src)
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | report.done(src, changed)
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | if cancelled:
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | await asyncio.gather(*cancelled, return_exceptions=True)
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | if sources_to_cache:
0070 0042 0057 0005 0005 0003 0005 -- 18 006 012 008 015 018 023 0095.91 0359.66 0003.75 | cache.write(sources_to_cache)