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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion src/black/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,17 @@ def validate_regex(
"editors that rely on using stdin."
),
)
@click.option(
"--project-root",
type=click.Path(
exists=True, file_okay=False, dir_okay=True, readable=True, allow_dash=True
),
help=(
"Manually specifiy the project root. This will prevent black from searching "
"for the project root itself. Useful to prevent black from picking up git "
"submodules as the project root which can affect the exclude behaviour."
),
)
@click.option(
"-W",
"--workers",
Expand Down Expand Up @@ -438,6 +449,7 @@ def main( # noqa: C901
extend_exclude: Optional[Pattern[str]],
force_exclude: Optional[Pattern[str]],
stdin_filename: Optional[str],
project_root: Optional[str],
workers: int,
src: Tuple[str, ...],
config: Optional[str],
Expand All @@ -455,7 +467,15 @@ def main( # noqa: C901
out(main.get_usage(ctx) + "\n\nOne of 'SRC' or 'code' is required.")
ctx.exit(1)

root, method = find_project_root(src) if code is None else (None, None)
if project_root:
project_root_abs = Path(project_root).resolve()
root, method = (
(project_root_abs, "manually-specified project root")
if code is None
else (None, None)
)
else:
root, method = find_project_root(src) if code is None else (None, None)
ctx.obj["root"] = root

if verbose:
Expand Down
Empty file.
Empty file.
19 changes: 18 additions & 1 deletion tests/test_black.py
Original file line number Diff line number Diff line change
Expand Up @@ -1852,8 +1852,11 @@ def assert_collected_sources(
None if extend_exclude is None else compile_pattern(extend_exclude)
)
gs_force_exclude = None if force_exclude is None else compile_pattern(force_exclude)
if not ctx:
ctx = FakeContext()
ctx.obj["root"], _ = black.find_project_root(gs_src)
collected = black.get_sources(
ctx=ctx or FakeContext(),
ctx=ctx,
src=gs_src,
quiet=False,
verbose=False,
Expand Down Expand Up @@ -2016,6 +2019,20 @@ def test_extend_exclude(self) -> None:
src, expected, exclude=r"\.pyi$", extend_exclude=r"\.definitely_exclude"
)

def test_git_submodule_exclude_full_path(self) -> None:
path = DATA_DIR / "git_submodule_exclude_tests" / "excluded_submodule" / "a.py"
src = [path]
expected: List[str] = []
assert_collected_sources(src, expected, force_exclude=r"excluded_submodule")

def test_git_submodule_exclude_base_path(self) -> None:
path = DATA_DIR / "git_submodule_exclude_tests"
src = [path]
expected = [
Path(path / "a.py"),
]
assert_collected_sources(src, expected, force_exclude=r"excluded_submodule")

@pytest.mark.incompatible_with_mypyc
def test_symlink_out_of_root_directory(self) -> None:
path = MagicMock()
Expand Down