X-Git-Url: https://git.madduck.net/etc/vim.git/blobdiff_plain/71e71e5f52e5f6bdeae63cc8c11b1bee44d11c30..5d0d5936db2ed7a01c50a374e32753e1afe9cc71:/src/black/files.py?ds=sidebyside diff --git a/src/black/files.py b/src/black/files.py index 52c77c6..ea517f4 100644 --- a/src/black/files.py +++ b/src/black/files.py @@ -1,9 +1,10 @@ -from functools import lru_cache import io import os -from pathlib import Path import sys +from functools import lru_cache +from pathlib import Path from typing import ( + TYPE_CHECKING, Any, Dict, Iterable, @@ -14,7 +15,6 @@ from typing import ( Sequence, Tuple, Union, - TYPE_CHECKING, ) from mypy_extensions import mypyc_attr @@ -22,20 +22,27 @@ from pathspec import PathSpec from pathspec.patterns.gitwildmatch import GitWildMatchPatternError if sys.version_info >= (3, 11): - import tomllib + try: + import tomllib + except ImportError: + # Help users on older alphas + if not TYPE_CHECKING: + import tomli as tomllib else: import tomli as tomllib +from black.handle_ipynb_magics import jupyter_dependencies_are_installed from black.output import err from black.report import Report -from black.handle_ipynb_magics import jupyter_dependencies_are_installed if TYPE_CHECKING: import colorama # noqa: F401 @lru_cache() -def find_project_root(srcs: Sequence[str]) -> Tuple[Path, str]: +def find_project_root( + srcs: Sequence[str], stdin_filename: Optional[str] = None +) -> Tuple[Path, str]: """Return a directory containing .git, .hg, or pyproject.toml. That directory will be a common parent of all files and directories @@ -48,6 +55,8 @@ def find_project_root(srcs: Sequence[str]) -> Tuple[Path, str]: the second element as a string describing the method by which the project root was discovered. """ + if stdin_filename is not None: + srcs = tuple(stdin_filename if s == "-" else s for s in srcs) if not srcs: srcs = [str(Path.cwd().resolve())] @@ -173,6 +182,19 @@ def normalize_path_maybe_ignore( return root_relative_path +def path_is_ignored( + path: Path, gitignore_dict: Dict[Path, PathSpec], report: Report +) -> bool: + for gitignore_path, pattern in gitignore_dict.items(): + relative_path = normalize_path_maybe_ignore(path, gitignore_path, report) + if relative_path is None: + break + if pattern.match_file(relative_path): + report.path_ignored(path, "matches a .gitignore file content") + return True + return False + + def path_is_excluded( normalized_path: str, pattern: Optional[Pattern[str]], @@ -189,7 +211,7 @@ def gen_python_files( extend_exclude: Optional[Pattern[str]], force_exclude: Optional[Pattern[str]], report: Report, - gitignore: Optional[PathSpec], + gitignore_dict: Optional[Dict[Path, PathSpec]], *, verbose: bool, quiet: bool, @@ -202,6 +224,7 @@ def gen_python_files( `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) @@ -209,8 +232,7 @@ def gen_python_files( 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") + if gitignore_dict and path_is_ignored(child, gitignore_dict, report): continue # Then ignore with `--exclude` `--extend-exclude` and `--force-exclude` options. @@ -235,6 +257,13 @@ def gen_python_files( 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. + if gitignore_dict is not None: + new_gitignore_dict = { + **gitignore_dict, + root / child: get_gitignore(child), + } + else: + new_gitignore_dict = None yield from gen_python_files( child.iterdir(), root, @@ -243,7 +272,7 @@ def gen_python_files( extend_exclude, force_exclude, report, - gitignore + get_gitignore(child) if gitignore is not None else None, + new_gitignore_dict, verbose=verbose, quiet=quiet, )