def path_empty(src: Sized, msg: str, quiet: bool, verbose: bool, ctx: click.Context) -> None: """ Exit if there is no `src` provided for formatting """ if not src and (verbose or not quiet): out(msg) ctx.exit(0)
def jupyter_dependencies_are_installed(*, verbose: bool, quiet: bool) -> bool: try: import IPython # noqa:F401 import tokenize_rt # noqa:F401 except ModuleNotFoundError: if verbose or not quiet: msg = ( "Skipping .ipynb files as Jupyter dependencies are not installed.\n" "You can fix this by running ``pip install black[jupyter]``") out(msg) return False else: return True
def done(self, src: Path, changed: Changed) -> None: """Increment the counter for successful reformatting. Write out a message.""" if changed is Changed.YES: reformatted = "would reformat" if self.check or self.diff else "reformatted" if self.verbose or not self.quiet: out(f"{reformatted} {src}") self.change_count += 1 else: if self.verbose: if changed is Changed.NO: msg = f"{src} already well formatted, good job." else: msg = f"{src} wasn't modified on disk since last run." out(msg, bold=False) self.same_count += 1
def assertFormatEqual(self, expected: str, actual: str) -> None: if actual != expected and not os.environ.get("SKIP_AST_PRINT"): bdv: DebugVisitor[Any] out("Expected tree:", fg="green") try: exp_node = black.lib2to3_parse(expected) bdv = DebugVisitor() list(bdv.visit(exp_node)) except Exception as ve: err(str(ve)) out("Actual tree:", fg="red") try: exp_node = black.lib2to3_parse(actual) bdv = DebugVisitor() list(bdv.visit(exp_node)) except Exception as ve: err(str(ve)) self.assertMultiLineEqual(expected, actual)
def visit_default(self, node: LN) -> Iterator[T]: indent = " " * (2 * self.tree_depth) if isinstance(node, Node): _type = type_repr(node.type) out(f"{indent}{_type}", fg="yellow") self.tree_depth += 1 for child in node.children: yield from self.visit(child) self.tree_depth -= 1 out(f"{indent}/{_type}", fg="yellow", bold=False) else: _type = token.tok_name.get(node.type, str(node.type)) out(f"{indent}{_type}", fg="blue", nl=False) if node.prefix: # We don't have to handle prefixes for `Node` objects since # that delegates to the first child anyway. out(f" {node.prefix!r}", fg="green", bold=False, nl=False) out(f" {node.value!r}", fg="blue", bold=False)
def _assert_format_equal(expected: str, actual: str) -> None: if actual != expected and not os.environ.get("SKIP_AST_PRINT"): bdv: DebugVisitor[Any] out("Expected tree:", fg="green") try: exp_node = black.lib2to3_parse(expected) bdv = DebugVisitor() list(bdv.visit(exp_node)) except Exception as ve: err(str(ve)) out("Actual tree:", fg="red") try: exp_node = black.lib2to3_parse(actual) bdv = DebugVisitor() list(bdv.visit(exp_node)) except Exception as ve: err(str(ve)) if actual != expected: out(diff(expected, actual, "expected", "actual")) assert actual == expected
def main( ctx: click.Context, code: Optional[str], line_length: int, target_version: List[TargetVersion], check: bool, diff: bool, color: bool, fast: bool, pyi: bool, ipynb: bool, skip_string_normalization: bool, skip_magic_trailing_comma: bool, experimental_string_processing: bool, quiet: bool, verbose: bool, required_version: Optional[str], include: Pattern[str], exclude: Optional[Pattern[str]], extend_exclude: Optional[Pattern[str]], force_exclude: Optional[Pattern[str]], stdin_filename: Optional[str], workers: int, src: Tuple[str, ...], config: Optional[str], ) -> None: """The uncompromising code formatter.""" if config and verbose: out(f"Using configuration from {config}.", bold=False, fg="blue") error_msg = "Oh no! 💥 💔 💥" if required_version and required_version != __version__: err(f"{error_msg} The required version `{required_version}` does not match" f" the running version `{__version__}`!") ctx.exit(1) if ipynb and pyi: err("Cannot pass both `pyi` and `ipynb` flags!") ctx.exit(1) write_back = WriteBack.from_configuration(check=check, diff=diff, color=color) if target_version: versions = set(target_version) else: # We'll autodetect later. versions = set() mode = Mode( target_versions=versions, line_length=line_length, is_pyi=pyi, is_ipynb=ipynb, string_normalization=not skip_string_normalization, magic_trailing_comma=not skip_magic_trailing_comma, experimental_string_processing=experimental_string_processing, ) if code is not None: # Run in quiet mode by default with -c; the extra output isn't useful. # You can still pass -v to get verbose output. quiet = True report = Report(check=check, diff=diff, quiet=quiet, verbose=verbose) if code is not None: reformat_code(content=code, fast=fast, write_back=write_back, mode=mode, report=report) else: try: sources = get_sources( ctx=ctx, src=src, quiet=quiet, verbose=verbose, include=include, exclude=exclude, extend_exclude=extend_exclude, force_exclude=force_exclude, report=report, stdin_filename=stdin_filename, ) except GitWildMatchPatternError: ctx.exit(1) path_empty( sources, "No Python files are present to be formatted. Nothing to do 😴", quiet, verbose, ctx, ) if len(sources) == 1: reformat_one( src=sources.pop(), fast=fast, write_back=write_back, mode=mode, report=report, ) else: reformat_many( sources=sources, fast=fast, write_back=write_back, mode=mode, report=report, workers=workers, ) if verbose or not quiet: out(error_msg if report.return_code else "All done! ✨ 🍰 ✨") if code is None: click.echo(str(report), err=True) ctx.exit(report.return_code)
def main( # noqa: C901 ctx: click.Context, code: Optional[str], line_length: int, target_version: List[TargetVersion], check: bool, diff: bool, color: bool, fast: bool, pyi: bool, ipynb: bool, python_cell_magics: Sequence[str], skip_string_normalization: bool, skip_magic_trailing_comma: bool, experimental_string_processing: bool, preview: bool, quiet: bool, verbose: bool, required_version: Optional[str], include: Pattern[str], exclude: Optional[Pattern[str]], extend_exclude: Optional[Pattern[str]], force_exclude: Optional[Pattern[str]], stdin_filename: Optional[str], workers: int, src: Tuple[str, ...], config: Optional[str], ) -> None: """The uncompromising code formatter.""" ctx.ensure_object(dict) if src and code is not None: out( main.get_usage(ctx) + "\n\n'SRC' and 'code' cannot be passed simultaneously.") ctx.exit(1) if not src and code is None: out(main.get_usage(ctx) + "\n\nOne of 'SRC' or 'code' is required.") ctx.exit(1) root, method = find_project_root(src) if code is None else (None, None) ctx.obj["root"] = root if verbose: if root: out( f"Identified `{root}` as project root containing a {method}.", fg="blue", ) normalized = [(normalize_path_maybe_ignore(Path(source), root), source) for source in src] srcs_string = ", ".join([ f'"{_norm}"' if _norm else f'\033[31m"{source} (skipping - invalid)"\033[34m' for _norm, source in normalized ]) out(f"Sources to be formatted: {srcs_string}", fg="blue") if config: config_source = ctx.get_parameter_source("config") user_level_config = str(find_user_pyproject_toml()) if config == user_level_config: out( "Using configuration from user-level config at " f"'{user_level_config}'.", fg="blue", ) elif config_source in ( ParameterSource.DEFAULT, ParameterSource.DEFAULT_MAP, ): out("Using configuration from project root.", fg="blue") else: out(f"Using configuration in '{config}'.", fg="blue") error_msg = "Oh no! 💥 💔 💥" if (required_version and required_version != __version__ and required_version != __version__.split(".")[0]): err(f"{error_msg} The required version `{required_version}` does not match" f" the running version `{__version__}`!") ctx.exit(1) if ipynb and pyi: err("Cannot pass both `pyi` and `ipynb` flags!") ctx.exit(1) write_back = WriteBack.from_configuration(check=check, diff=diff, color=color) if target_version: versions = set(target_version) else: # We'll autodetect later. versions = set() mode = Mode( target_versions=versions, line_length=line_length, is_pyi=pyi, is_ipynb=ipynb, string_normalization=not skip_string_normalization, magic_trailing_comma=not skip_magic_trailing_comma, experimental_string_processing=experimental_string_processing, preview=preview, python_cell_magics=set(python_cell_magics), ) if code is not None: # Run in quiet mode by default with -c; the extra output isn't useful. # You can still pass -v to get verbose output. quiet = True report = Report(check=check, diff=diff, quiet=quiet, verbose=verbose) if code is not None: reformat_code(content=code, fast=fast, write_back=write_back, mode=mode, report=report) else: try: sources = get_sources( ctx=ctx, src=src, quiet=quiet, verbose=verbose, include=include, exclude=exclude, extend_exclude=extend_exclude, force_exclude=force_exclude, report=report, stdin_filename=stdin_filename, ) except GitWildMatchPatternError: ctx.exit(1) path_empty( sources, "No Python files are present to be formatted. Nothing to do 😴", quiet, verbose, ctx, ) if len(sources) == 1: reformat_one( src=sources.pop(), fast=fast, write_back=write_back, mode=mode, report=report, ) else: reformat_many( sources=sources, fast=fast, write_back=write_back, mode=mode, report=report, workers=workers, ) if verbose or not quiet: if code is None and (verbose or report.change_count or report.failure_count): out() out(error_msg if report.return_code else "All done! ✨ 🍰 ✨") if code is None: click.echo(str(report), err=True) ctx.exit(report.return_code)
def main( ctx: click.Context, code: Optional[str], line_length: int, target_version: List[TargetVersion], check: bool, diff: bool, color: bool, fast: bool, pyi: bool, skip_string_normalization: bool, skip_magic_trailing_comma: bool, experimental_string_processing: bool, quiet: bool, verbose: bool, include: Pattern, exclude: Optional[Pattern], extend_exclude: Optional[Pattern], force_exclude: Optional[Pattern], stdin_filename: Optional[str], src: Tuple[str, ...], config: Optional[str], ) -> None: """The uncompromising code formatter.""" write_back = WriteBack.from_configuration(check=check, diff=diff, color=color) if target_version: versions = set(target_version) else: # We'll autodetect later. versions = set() mode = Mode( target_versions=versions, line_length=line_length, is_pyi=pyi, string_normalization=not skip_string_normalization, magic_trailing_comma=not skip_magic_trailing_comma, experimental_string_processing=experimental_string_processing, ) if config and verbose: out(f"Using configuration from {config}.", bold=False, fg="blue") if code is not None: print(format_str(code, mode=mode)) ctx.exit(0) report = Report(check=check, diff=diff, quiet=quiet, verbose=verbose) sources = get_sources( ctx=ctx, src=src, quiet=quiet, verbose=verbose, include=include, exclude=exclude, extend_exclude=extend_exclude, force_exclude=force_exclude, report=report, stdin_filename=stdin_filename, ) path_empty( sources, "No Python files are present to be formatted. Nothing to do 😴", quiet, verbose, ctx, ) if len(sources) == 1: reformat_one( src=sources.pop(), fast=fast, write_back=write_back, mode=mode, report=report, ) else: reformat_many(sources=sources, fast=fast, write_back=write_back, mode=mode, report=report) if verbose or not quiet: out("Oh no! 💥 💔 💥" if report.return_code else "All done! ✨ 🍰 ✨") click.secho(str(report), err=True) ctx.exit(report.return_code)
def path_ignored(self, path: Path, message: str) -> None: if self.verbose: out(f"{path} ignored: {message}", bold=False)