def main(args): """ This matches the default behaviour of the black formatter. This script will raise an exception if changes by black are required. """ sources = set() root = Path(os.getcwd()) p = Path(".") include_regex = re_compile_maybe_verbose(DEFAULT_INCLUDES) exclude_regex = re_compile_maybe_verbose(DEFAULT_EXCLUDES) report = Report() sources.update( gen_python_files_in_dir(p, root, include_regex, exclude_regex, report, get_gitignore(root))) # To conform to flake8 line length used for this project. mode = FileMode(line_length=79) write_back = WriteBack.from_configuration(check=False, diff=not args.force) reformat_many( sources=sources, fast=False, write_back=write_back, mode=mode, report=report, ) if report.change_count != 0: exception_msg = """ Black formatter suggests formatting changes required Run with '-f' option to automatically format. """ raise Exception(exception_msg)
def test_include_exclude(self) -> None: path = THIS_DIR / "include_exclude_tests" include = re.compile(r"\.pyi?$") exclude = re.compile(r"/exclude/|/\.definitely_exclude/") sources: List[Path] = [] expected = [ Path(THIS_DIR / "include_exclude_tests/b/dont_exclude/a.py"), Path(THIS_DIR / "include_exclude_tests/b/dont_exclude/a.pyi"), ] sources.extend(black.gen_python_files_in_dir(path, include, exclude)) self.assertEqual(sorted(expected), sorted(sources))
def test_include_exclude(self) -> None: path = THIS_DIR / "data" / "include_exclude_tests" include = re.compile(r"\.pyi?$") exclude = re.compile(r"/exclude/|/\.definitely_exclude/") report = black.Report() sources: List[Path] = [] expected = [ Path(path / "b/dont_exclude/a.py"), Path(path / "b/dont_exclude/a.pyi"), ] this_abs = THIS_DIR.resolve() sources.extend( black.gen_python_files_in_dir(path, this_abs, include, exclude, report)) self.assertEqual(sorted(expected), sorted(sources))
def test_empty_exclude(self) -> None: path = THIS_DIR / "include_exclude_tests" empty = re.compile(r"") sources: List[Path] = [] expected = [ Path(path / "b/dont_exclude/a.py"), Path(path / "b/dont_exclude/a.pyi"), Path(path / "b/exclude/a.py"), Path(path / "b/exclude/a.pyi"), Path(path / "b/.definitely_exclude/a.py"), Path(path / "b/.definitely_exclude/a.pyi"), ] sources.extend( black.gen_python_files_in_dir(path, re.compile(black.DEFAULT_INCLUDES), empty)) self.assertEqual(sorted(expected), sorted(sources))
def get_source_files(paths: Iterable[str]) -> Iterable[Path]: report = Report() root = find_project_root((f for f in paths)) sources: Set[Path] = set() for filename in paths: path = Path(filename) if path.is_dir(): sources.update( gen_python_files_in_dir( path=path, root=root, include=INCLUDES, exclude=EXCLUDES, report=report, gitignore=get_gitignore(root), )) elif path.is_file(): sources.add(path) else: print(f"Error: invalid path: {path}") exit(1) return sources
def test_empty_include(self) -> None: path = THIS_DIR / "data" / "include_exclude_tests" report = black.Report() empty = re.compile(r"") sources: List[Path] = [] expected = [ Path(path / "b/exclude/a.pie"), Path(path / "b/exclude/a.py"), Path(path / "b/exclude/a.pyi"), Path(path / "b/dont_exclude/a.pie"), Path(path / "b/dont_exclude/a.py"), Path(path / "b/dont_exclude/a.pyi"), Path(path / "b/.definitely_exclude/a.pie"), Path(path / "b/.definitely_exclude/a.py"), Path(path / "b/.definitely_exclude/a.pyi"), ] this_abs = THIS_DIR.resolve() sources.extend( black.gen_python_files_in_dir(path, this_abs, empty, re.compile(black.DEFAULT_EXCLUDES), report)) self.assertEqual(sorted(expected), sorted(sources))
def cli( ctx: click.Context, line_length: int, check: bool, include: str, exclude: str, quiet: bool, verbose: bool, clear_output: bool, src: Tuple[str], config: Optional[str], ) -> None: """ The uncompromising code formatter, for Jupyter notebooks. """ write_back = black.WriteBack.from_configuration(check=check, diff=False) mode = black.FileMode.from_configuration( py36=True, pyi=False, skip_string_normalization=False, skip_numeric_underscore_normalization=False, ) if config and verbose: black.out(f"Using configuration from {config}.", bold=False, fg="blue") try: include_regex = black.re_compile_maybe_verbose(include) except re.error: black.err(f"Invalid regular expression for include given: {include!r}") ctx.exit(2) try: exclude_regex = black.re_compile_maybe_verbose(exclude) except re.error: black.err(f"Invalid regular expression for exclude given: {exclude!r}") ctx.exit(2) report = black.Report(check=check, quiet=quiet, verbose=verbose) root = black.find_project_root(src) sources: Set[Path] = set() for s in src: p = Path(s) if p.is_dir(): sources.update( black.gen_python_files_in_dir( p, root, include_regex, exclude_regex, report ) ) elif p.is_file() or s == "-": # if a file was explicitly given, we don't care about its extension sources.add(p) else: black.err(f"invalid path: {s}") if len(sources) == 0: if verbose or not quiet: black.out("No paths given. Nothing to do.") ctx.exit(0) for source in sources: reformat_one( src=source, line_length=line_length, write_back=write_back, mode=mode, clear_output=clear_output, report=report, quiet=quiet, verbose=verbose, ) if verbose or not quiet: black.out(f"All done!") click.secho(str(report), err=True) ctx.exit(report.return_code)
async def api( *, src: Iterable[str], work_dir: str, line_length: int = black.DEFAULT_LINE_LENGTH, check: bool = False, diff: bool = False, fast: bool = False, pyi: bool = False, py36: bool = False, skip_string_normalization: bool = False, quiet: bool = False, verbose: bool = False, include: str = black.DEFAULT_INCLUDES, exclude: str = black.DEFAULT_EXCLUDES, config: Optional[str] = None, ) -> int: """The uncompromising code formatter.""" src = tuple(src) work_dir = Path(work_dir) loop = asyncio.get_event_loop() write_back = black.WriteBack.from_configuration(check=check, diff=diff) mode = black.FileMode.from_configuration( py36=py36, pyi=pyi, skip_string_normalization=skip_string_normalization ) if config and verbose: black.out(f"Using configuration from {config}.", bold=False, fg="blue") try: include_regex = black.re_compile_maybe_verbose(include) except re.error: black.err(f"Invalid regular expression for include given: {include!r}") return 2 try: exclude_regex = black.re_compile_maybe_verbose(exclude) except re.error: black.err(f"Invalid regular expression for exclude given: {exclude!r}") return 2 report = black.Report(check=check, quiet=quiet, verbose=verbose) root = black.find_project_root((work_dir,)) sources: Set[Path] = set() for s in src: p = work_dir / Path(s) if p.is_dir(): sources.update( black.gen_python_files_in_dir( p, root, include_regex, exclude_regex, report ) ) elif p.is_file() or s == "-": # if a file was explicitly given, we don't care about its extension sources.add(p) else: black.err(f"invalid path: {s}") if len(sources) == 0: if verbose or not quiet: black.out("No paths given. Nothing to do 😴") return 0 if len(sources) == 1: black.reformat_one( src=sources.pop(), line_length=line_length, fast=fast, write_back=write_back, mode=mode, report=report, ) else: await black.schedule_formatting( sources=sources, line_length=line_length, fast=fast, write_back=write_back, mode=mode, report=report, executor=PROCESS_POOL, loop=loop, ) if verbose or not quiet: bang = "💥 💔 💥" if report.return_code else "✨ 🍰 ✨" black.out(f"All done! {bang}") black.secho(str(report), err=True) return report.return_code