All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@git.madduck.net.
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
Closes #2164.
Changes behavior of how .gitignore is handled. With this change, the rules in .gitignore are only used as a fallback if no exclusion rule is explicitly passed on the command line or in pyproject.toml. Previously they were used regardless if explicit exclusion rules were specified, preventing any overriding of .gitignore rules.
Those that depend only on .gitignore for their exclusion rules will not be affected. Those that use both .gitignore and exclude will find that exclude will act more like actually specifying exclude and not just another extra-excludes. If the previous behavior was desired, they should move their rules from exclude to extra-excludes.
[circumstances](https://github.com/psf/black/blob/master/docs/the_black_code_style.md#pragmatism)
in which _Black_ may change the AST (#2159)
[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)
#### _Packaging_
- Install `primer.json` (used by `black-primer` by default) with black. (#2154)
@click.option(
"--exclude",
type=str,
@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)."
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}]"
)
@click.option(
"--extend-exclude",
)
@click.option(
"--extend-exclude",
quiet: bool,
verbose: bool,
include: Pattern,
quiet: bool,
verbose: bool,
include: Pattern,
+ exclude: Optional[Pattern],
extend_exclude: Optional[Pattern],
force_exclude: Optional[Pattern],
stdin_filename: Optional[str],
extend_exclude: Optional[Pattern],
force_exclude: Optional[Pattern],
stdin_filename: Optional[str],
quiet: bool,
verbose: bool,
include: Pattern[str],
quiet: bool,
verbose: bool,
include: Pattern[str],
+ exclude: Optional[Pattern[str]],
extend_exclude: Optional[Pattern[str]],
force_exclude: Optional[Pattern[str]],
report: "Report",
extend_exclude: Optional[Pattern[str]],
force_exclude: Optional[Pattern[str]],
report: "Report",
root = find_project_root(src)
sources: Set[Path] = set()
path_empty(src, "No Path provided. Nothing to do 😴", quiet, verbose, ctx)
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
for s in src:
if s == "-" and stdin_filename:
for s in src:
if s == "-" and stdin_filename:
def gen_python_files(
paths: Iterable[Path],
root: Path,
def gen_python_files(
paths: Iterable[Path],
root: Path,
- include: Optional[Pattern[str]],
exclude: Pattern[str],
extend_exclude: Optional[Pattern[str]],
force_exclude: Optional[Pattern[str]],
report: "Report",
exclude: Pattern[str],
extend_exclude: Optional[Pattern[str]],
force_exclude: Optional[Pattern[str]],
report: "Report",
+ 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,
) -> Iterator[Path]:
"""Generate all files under `path` whose paths are not excluded by the
`exclude_regex`, `extend_exclude`, or `force_exclude` regexes,
if normalized_path is None:
continue
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
report.path_ignored(child, "matches the .gitignore file content")
continue
--- /dev/null
+[build-system]
+requires = ["setuptools>=41.0", "setuptools-scm", "wheel"]
+build-backend = "setuptools.build_meta"
)
self.assertEqual(sorted(expected), sorted(sources))
)
self.assertEqual(sorted(expected), sorted(sources))
+ def test_gitingore_used_as_default(self) -> None:
+ 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
@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
Path(path / "b/.definitely_exclude/a.pie"),
Path(path / "b/.definitely_exclude/a.py"),
Path(path / "b/.definitely_exclude/a.pyi"),
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(
]
this_abs = THIS_DIR.resolve()
sources.extend(