Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply force exclude logic before symlink resolution #4015

Merged
merged 3 commits into from Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGES.md
Expand Up @@ -21,7 +21,7 @@
### Configuration

- Add support for single-line format skip with other comments on the same line (#3959)

- Consistently apply force exclusion logic before resolving symlinks (#4015)
- Fix a bug in the matching of absolute path names in `--include` (#3976)

### Packaging
Expand Down
24 changes: 14 additions & 10 deletions src/black/__init__.py
Expand Up @@ -639,24 +639,26 @@ def get_sources(
path = Path(s)
is_stdin = False

# Compare the logic here to the logic in `gen_python_files`.
if is_stdin or path.is_file():
root_relative_path = path.absolute().relative_to(root).as_posix()

root_relative_path = "/" + root_relative_path

# Hard-exclude any files that matches the `--force-exclude` regex.
if path_is_excluded(root_relative_path, force_exclude):
report.path_ignored(
path, "matches the --force-exclude regular expression"
)
continue

normalized_path: Optional[str] = normalize_path_maybe_ignore(
path, root, report
)
if normalized_path is None:
if verbose:
out(f'Skipping invalid source: "{normalized_path}"', fg="red")
continue
if verbose:
out(f'Found input source: "{normalized_path}"', fg="blue")

normalized_path = "/" + normalized_path
# Hard-exclude any files that matches the `--force-exclude` regex.
if path_is_excluded(normalized_path, force_exclude):
report.path_ignored(
path, "matches the --force-exclude regular expression"
)
continue

if is_stdin:
path = Path(f"{STDIN_PLACEHOLDER}{str(path)}")
Expand All @@ -666,6 +668,8 @@ def get_sources(
):
continue

if verbose:
out(f'Found input source: "{normalized_path}"', fg="blue")
sources.add(path)
elif path.is_dir():
path = root / (path.resolve().relative_to(root))
Expand Down
17 changes: 17 additions & 0 deletions tests/test_black.py
Expand Up @@ -2552,6 +2552,23 @@ def test_get_sources_with_stdin_filename_and_force_exclude(self) -> None:
stdin_filename=stdin_filename,
)

@patch("black.find_project_root", lambda *args: (THIS_DIR.resolve(), None))
def test_get_sources_with_stdin_filename_and_force_exclude_and_symlink(
self,
) -> None:
# Force exclude should exclude a symlink based on the symlink, not its target
path = THIS_DIR / "data" / "include_exclude_tests"
stdin_filename = str(path / "symlink.py")
expected = [f"__BLACK_STDIN_FILENAME__{stdin_filename}"]
target = path / "b/exclude/a.py"
with patch("pathlib.Path.resolve", return_value=target):
assert_collected_sources(
src=["-"],
expected=expected,
force_exclude=r"exclude/a\.py",
stdin_filename=stdin_filename,
)


class TestDeFactoAPI:
"""Test that certain symbols that are commonly used externally keep working.
Expand Down