def reformat_one(src: Path, fast: bool, write_back: WriteBack, mode: Mode, report: "Report") -> None: """Reformat a single file under `src` without spawning child processes. `fast`, `write_back`, and `mode` options are passed to :func:`format_file_in_place` or :func:`format_stdin_to_stdout`. """ try: changed = Changed.NO if str(src) == "-": is_stdin = True elif str(src).startswith(STDIN_PLACEHOLDER): is_stdin = True # Use the original name again in case we want to print something # to the user src = Path(str(src)[len(STDIN_PLACEHOLDER):]) else: is_stdin = False if is_stdin: if src.suffix == ".pyi": mode = replace(mode, is_pyi=True) elif src.suffix == ".ipynb": mode = replace(mode, is_ipynb=True) if format_stdin_to_stdout(fast=fast, write_back=write_back, mode=mode): changed = Changed.YES else: cache: Cache = {} if write_back not in (WriteBack.DIFF, WriteBack.COLOR_DIFF): cache = read_cache(mode) res_src = src.resolve() res_src_s = str(res_src) if res_src_s in cache and cache[res_src_s] == get_cache_info( res_src): changed = Changed.CACHED if changed is not Changed.CACHED and format_file_in_place( src, fast=fast, write_back=write_back, mode=mode): changed = Changed.YES if (write_back is WriteBack.YES and changed is not Changed.CACHED) or (write_back is WriteBack.CHECK and changed is Changed.NO): write_cache(cache, [src], mode) report.done(src, changed) except Exception as exc: if report.verbose: traceback.print_exc() report.failed(src, str(exc))
async def schedule_formatting( sources: Set[Path], fast: bool, write_back: WriteBack, mode: Mode, report: "Report", loop: asyncio.AbstractEventLoop, executor: Executor, ) -> None: """Run formatting of `sources` in parallel using the provided `executor`. (Use ProcessPoolExecutors for actual parallelism.) `write_back`, `fast`, and `mode` options are passed to :func:`format_file_in_place`. """ cache: Cache = {} if write_back not in (WriteBack.DIFF, WriteBack.COLOR_DIFF): cache = read_cache(mode) sources, cached = filter_cached(cache, sources) for src in sorted(cached): report.done(src, Changed.CACHED) if not sources: return cancelled = [] sources_to_cache = [] lock = None if write_back in (WriteBack.DIFF, WriteBack.COLOR_DIFF): # For diff output, we need locks to ensure we don't interleave output # from different processes. manager = Manager() lock = manager.Lock() tasks = { asyncio.ensure_future( loop.run_in_executor(executor, format_file_in_place, src, fast, mode, write_back, lock)): src for src in sorted(sources) } pending = tasks.keys() try: loop.add_signal_handler(signal.SIGINT, cancel, pending) loop.add_signal_handler(signal.SIGTERM, cancel, pending) except NotImplementedError: # There are no good alternatives for these on Windows. pass while pending: done, _ = await asyncio.wait(pending, return_when=asyncio.FIRST_COMPLETED) for task in done: src = tasks.pop(task) if task.cancelled(): cancelled.append(task) elif task.exception(): report.failed(src, str(task.exception())) else: changed = Changed.YES if task.result() else Changed.NO # If the file was written back or was successfully checked as # well-formatted, store this information in the cache. if write_back is WriteBack.YES or ( write_back is WriteBack.CHECK and changed is Changed.NO): sources_to_cache.append(src) report.done(src, changed) if cancelled: if sys.version_info >= (3, 7): await asyncio.gather(*cancelled, return_exceptions=True) else: await asyncio.gather(*cancelled, loop=loop, return_exceptions=True) if sources_to_cache: write_cache(cache, sources_to_cache, mode)