Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
[circumstances](https://github.com/psf/black/blob/master/docs/the_black_code_style.md#pragmatism)
in which _Black_ may change the AST (#2159)

- Allow `.gitignore` rules to be overridden by specifying `exclude` in `pyproject.toml`
or on the command line. (#2170)

#### _Packaging_

- Install `primer.json` (used by `black-primer` by default) with black. (#2154)
Expand Down
25 changes: 15 additions & 10 deletions src/black/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,15 +492,15 @@ def validate_regex(
@click.option(
"--exclude",
type=str,
default=DEFAULT_EXCLUDES,
callback=validate_regex,
help=(
"A regular expression that matches files and directories that should be"
" excluded on recursive searches. An empty value means no paths are excluded."
" Use forward slashes for directories on all platforms (Windows, too)."
" Exclusions are calculated first, inclusions later."
" Exclusions are calculated first, inclusions later. [default:"
f" {DEFAULT_EXCLUDES}]"
),
show_default=True,
show_default=False,
)
@click.option(
"--extend-exclude",
Expand Down Expand Up @@ -587,7 +587,7 @@ def main(
quiet: bool,
verbose: bool,
include: Pattern,
exclude: Pattern,
exclude: Optional[Pattern],
extend_exclude: Optional[Pattern],
force_exclude: Optional[Pattern],
stdin_filename: Optional[str],
Expand Down Expand Up @@ -662,7 +662,7 @@ def get_sources(
quiet: bool,
verbose: bool,
include: Pattern[str],
exclude: Pattern[str],
exclude: Optional[Pattern[str]],
extend_exclude: Optional[Pattern[str]],
force_exclude: Optional[Pattern[str]],
report: "Report",
Expand All @@ -673,7 +673,12 @@ def get_sources(
root = find_project_root(src)
sources: Set[Path] = set()
path_empty(src, "No Path provided. Nothing to do 😴", quiet, verbose, ctx)
gitignore = get_gitignore(root)

if exclude is None:
exclude = re_compile_maybe_verbose(DEFAULT_EXCLUDES)
gitignore = get_gitignore(root)
else:
gitignore = None
Comment thread
ktbarrett marked this conversation as resolved.

for s in src:
if s == "-" and stdin_filename:
Expand Down Expand Up @@ -6215,12 +6220,12 @@ def path_is_excluded(
def gen_python_files(
paths: Iterable[Path],
root: Path,
include: Optional[Pattern[str]],
include: Pattern[str],
exclude: Pattern[str],
extend_exclude: Optional[Pattern[str]],
force_exclude: Optional[Pattern[str]],
report: "Report",
gitignore: PathSpec,
gitignore: Optional[PathSpec],
) -> Iterator[Path]:
"""Generate all files under `path` whose paths are not excluded by the
`exclude_regex`, `extend_exclude`, or `force_exclude` regexes,
Expand All @@ -6236,8 +6241,8 @@ def gen_python_files(
if normalized_path is None:
continue

# First ignore files matching .gitignore
if gitignore.match_file(normalized_path):
# 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

Expand Down
1 change: 1 addition & 0 deletions tests/data/include_exclude_tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dont_exclude/
3 changes: 3 additions & 0 deletions tests/data/include_exclude_tests/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools>=41.0", "setuptools-scm", "wheel"]
build-backend = "setuptools.build_meta"
28 changes: 28 additions & 0 deletions tests/test_black.py
Original file line number Diff line number Diff line change
Expand Up @@ -1418,6 +1418,32 @@ def test_include_exclude(self) -> None:
)
self.assertEqual(sorted(expected), sorted(sources))

def test_gitingore_used_as_default(self) -> None:
Comment thread
ktbarrett marked this conversation as resolved.
path = Path(THIS_DIR / "data" / "include_exclude_tests")
include = re.compile(r"\.pyi?$")
extend_exclude = re.compile(r"/exclude/")
src = str(path / "b/")
report = black.Report()
expected: List[Path] = [
path / "b/.definitely_exclude/a.py",
path / "b/.definitely_exclude/a.pyi",
]
sources = list(
black.get_sources(
ctx=FakeContext(),
src=(src,),
quiet=True,
verbose=False,
include=include,
exclude=None,
extend_exclude=extend_exclude,
force_exclude=None,
report=report,
stdin_filename=None,
)
)
self.assertEqual(sorted(expected), sorted(sources))

@patch("black.find_project_root", lambda *args: THIS_DIR.resolve())
def test_exclude_for_issue_1572(self) -> None:
# Exclude shouldn't touch files that were explicitly given to Black through the
Expand Down Expand Up @@ -1705,6 +1731,8 @@ def test_empty_include(self) -> None:
Path(path / "b/.definitely_exclude/a.pie"),
Path(path / "b/.definitely_exclude/a.py"),
Path(path / "b/.definitely_exclude/a.pyi"),
Path(path / ".gitignore"),
Path(path / "pyproject.toml"),
]
this_abs = THIS_DIR.resolve()
sources.extend(
Expand Down