Skip to content

Commit 2e4fac9

Browse files
authored
Apply force exclude logic before symlink resolution (#4015)
1 parent 66008fd commit 2e4fac9

File tree

3 files changed

+32
-11
lines changed

3 files changed

+32
-11
lines changed

CHANGES.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
### Configuration
3535

3636
- Add support for single-line format skip with other comments on the same line (#3959)
37-
37+
- Consistently apply force exclusion logic before resolving symlinks (#4015)
3838
- Fix a bug in the matching of absolute path names in `--include` (#3976)
3939

4040
### Packaging

src/black/__init__.py

+14-10
Original file line numberDiff line numberDiff line change
@@ -682,24 +682,26 @@ def get_sources(
682682
path = Path(s)
683683
is_stdin = False
684684

685+
# Compare the logic here to the logic in `gen_python_files`.
685686
if is_stdin or path.is_file():
687+
root_relative_path = path.absolute().relative_to(root).as_posix()
688+
689+
root_relative_path = "/" + root_relative_path
690+
691+
# Hard-exclude any files that matches the `--force-exclude` regex.
692+
if path_is_excluded(root_relative_path, force_exclude):
693+
report.path_ignored(
694+
path, "matches the --force-exclude regular expression"
695+
)
696+
continue
697+
686698
normalized_path: Optional[str] = normalize_path_maybe_ignore(
687699
path, root, report
688700
)
689701
if normalized_path is None:
690702
if verbose:
691703
out(f'Skipping invalid source: "{normalized_path}"', fg="red")
692704
continue
693-
if verbose:
694-
out(f'Found input source: "{normalized_path}"', fg="blue")
695-
696-
normalized_path = "/" + normalized_path
697-
# Hard-exclude any files that matches the `--force-exclude` regex.
698-
if path_is_excluded(normalized_path, force_exclude):
699-
report.path_ignored(
700-
path, "matches the --force-exclude regular expression"
701-
)
702-
continue
703705

704706
if is_stdin:
705707
path = Path(f"{STDIN_PLACEHOLDER}{str(path)}")
@@ -709,6 +711,8 @@ def get_sources(
709711
):
710712
continue
711713

714+
if verbose:
715+
out(f'Found input source: "{normalized_path}"', fg="blue")
712716
sources.add(path)
713717
elif path.is_dir():
714718
path = root / (path.resolve().relative_to(root))

tests/test_black.py

+17
Original file line numberDiff line numberDiff line change
@@ -2637,6 +2637,23 @@ def test_get_sources_with_stdin_filename_and_force_exclude(self) -> None:
26372637
stdin_filename=stdin_filename,
26382638
)
26392639

2640+
@patch("black.find_project_root", lambda *args: (THIS_DIR.resolve(), None))
2641+
def test_get_sources_with_stdin_filename_and_force_exclude_and_symlink(
2642+
self,
2643+
) -> None:
2644+
# Force exclude should exclude a symlink based on the symlink, not its target
2645+
path = THIS_DIR / "data" / "include_exclude_tests"
2646+
stdin_filename = str(path / "symlink.py")
2647+
expected = [f"__BLACK_STDIN_FILENAME__{stdin_filename}"]
2648+
target = path / "b/exclude/a.py"
2649+
with patch("pathlib.Path.resolve", return_value=target):
2650+
assert_collected_sources(
2651+
src=["-"],
2652+
expected=expected,
2653+
force_exclude=r"exclude/a\.py",
2654+
stdin_filename=stdin_filename,
2655+
)
2656+
26402657

26412658
class TestDeFactoAPI:
26422659
"""Test that certain symbols that are commonly used externally keep working.

0 commit comments

Comments
 (0)