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

Check excludes before symlink resolution for command line parameters #3987

Closed
wants to merge 4 commits into from
Closed
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
3 changes: 2 additions & 1 deletion CHANGES.md
Expand Up @@ -18,7 +18,8 @@
### Configuration

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

- File exclusion and inclusion logic is now consistently applied before symlink
resolution. (#3987) (#3976)
- Fix a bug in the matching of absolute path names in `--include` (#3976)

### Packaging
Expand Down
26 changes: 14 additions & 12 deletions src/black/__init__.py
Expand Up @@ -50,6 +50,7 @@
get_gitignore,
normalize_path_maybe_ignore,
parse_pyproject_toml,
path_is_excluded,
wrap_stream_for_windows,
)
from black.handle_ipynb_magics import (
Expand Down Expand Up @@ -639,25 +640,26 @@ def get_sources(
is_stdin = False

if is_stdin or p.is_file():
root_relative_path = p.absolute().relative_to(root).as_posix()

root_relative_path = "/" + root_relative_path
if p.is_dir():
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(p, "matches the --force-exclude regular expression")
continue

normalized_path: Optional[str] = normalize_path_maybe_ignore(
p, root, report
)
if normalized_path is None:
if verbose:
out(f'Skipping invalid source: "{normalized_path}"', fg="red")
out(f'Skipping invalid source: "{p}"', 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 force_exclude:
force_exclude_match = force_exclude.search(normalized_path)
else:
force_exclude_match = None
if force_exclude_match and force_exclude_match.group(0):
report.path_ignored(p, "matches the --force-exclude regular expression")
continue
out(f'Found input source: "{p}"', fg="blue")

if is_stdin:
p = Path(f"{STDIN_PLACEHOLDER}{str(p)}")
Expand Down
18 changes: 18 additions & 0 deletions tests/test_black.py
Expand Up @@ -1409,6 +1409,24 @@ def test_invalid_cli_regex(self) -> None:
for option in ["--include", "--exclude", "--extend-exclude", "--force-exclude"]:
self.invokeBlack(["-", option, "**()(!!*)"], exit_code=2)

def test_force_exclude_symlink_parameter(self) -> None:
with TemporaryDirectory() as workspace:
root = Path(workspace)
(root / "pyproject.toml").touch()

symlink_target = root / "target.py"
symlink_target.write_text("print ( )\n", encoding="utf-8")

symlink = root / "symlink.py"
symlink.symlink_to(symlink_target)

# target.py would need to be reformatted, and symlink.py points to
# it, but since we force-exclude symlink.py, black should not check
# the pointed-to file.
self.invokeBlack(
["--check", r"--force-exclude=sym", str(symlink)], exit_code=0
)

def test_required_version_matches_version(self) -> None:
self.invokeBlack(
["--required-version", black.__version__, "-c", "0"],
Expand Down