def gen_python_files( paths: Iterable[Path], root: Path, include: Pattern[str], exclude: Pattern[str], extend_exclude: Optional[Pattern[str]], force_exclude: Optional[Pattern[str]], report: Report, gitignore: Optional[PathSpec], *, verbose: bool, quiet: bool, ) -> Iterator[Path]: """Generate all files under `path` whose paths are not excluded by the `exclude_regex`, `extend_exclude`, or `force_exclude` regexes, but are included by the `include` regex. Symbolic links pointing outside of the `root` directory are ignored. `report` is where output about exclusions goes. """ assert root.is_absolute( ), f"INTERNAL ERROR: `root` must be absolute but is {root}" for child in paths: normalized_path = normalize_path_maybe_ignore(child, root, report) if normalized_path is None: continue # First ignore files matching .gitignore, if passed if gitignore is not None and gitignore.match_file(normalized_path): report.path_ignored(child, "matches the .gitignore file content") continue # Then ignore with `--exclude` `--extend-exclude` and `--force-exclude` options. normalized_path = "/" + normalized_path if child.is_dir(): normalized_path += "/" if path_is_excluded(normalized_path, exclude): report.path_ignored(child, "matches the --exclude regular expression") continue if path_is_excluded(normalized_path, extend_exclude): report.path_ignored( child, "matches the --extend-exclude regular expression") continue if path_is_excluded(normalized_path, force_exclude): report.path_ignored( child, "matches the --force-exclude regular expression") continue if child.is_dir(): # If gitignore is None, gitignore usage is disabled, while a Falsey # gitignore is when the directory doesn't have a .gitignore file. yield from gen_python_files( child.iterdir(), root, include, exclude, extend_exclude, force_exclude, report, gitignore + get_gitignore(child) if gitignore is not None else None, verbose=verbose, quiet=quiet, ) elif child.is_file(): if child.suffix == ".ipynb" and not jupyter_dependencies_are_installed( verbose=verbose, quiet=quiet): continue include_match = include.search( normalized_path) if include else True if include_match: yield child
def get_sources( *, ctx: click.Context, src: Tuple[str, ...], quiet: bool, verbose: bool, include: Pattern[str], exclude: Optional[Pattern[str]], extend_exclude: Optional[Pattern[str]], force_exclude: Optional[Pattern[str]], report: "Report", stdin_filename: Optional[str], ) -> Set[Path]: """Compute the set of files to be formatted.""" root = find_project_root(src) sources: Set[Path] = set() path_empty(src, "No Path provided. Nothing to do 😴", quiet, verbose, ctx) if exclude is None: exclude = re_compile_maybe_verbose(DEFAULT_EXCLUDES) gitignore = get_gitignore(root) else: gitignore = None for s in src: if s == "-" and stdin_filename: p = Path(stdin_filename) is_stdin = True else: p = Path(s) is_stdin = False if is_stdin or p.is_file(): normalized_path = normalize_path_maybe_ignore(p, root, report) if normalized_path is None: continue normalized_path = "/" + normalized_path # Hard-exclude any files that matches the `--force-exclude` regex. if force_exclude: force_exclude_match = force_exclude.search(normalized_path) else: force_exclude_match = None if force_exclude_match and force_exclude_match.group(0): report.path_ignored( p, "matches the --force-exclude regular expression") continue if is_stdin: p = Path(f"{STDIN_PLACEHOLDER}{str(p)}") if p.suffix == ".ipynb" and not jupyter_dependencies_are_installed( verbose=verbose, quiet=quiet): continue sources.add(p) elif p.is_dir(): sources.update( gen_python_files( p.iterdir(), root, include, exclude, extend_exclude, force_exclude, report, gitignore, verbose=verbose, quiet=quiet, )) elif s == "-": sources.add(p) else: err(f"invalid path: {s}") return sources