Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions copcon/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ def main(
directory: Path = typer.Argument(...),
depth: int = typer.Option(-1),
exclude_hidden: bool = typer.Option(True),
ignore_dirs: list[str] = typer.Option(None),
ignore_files: list[str] = typer.Option(None),
copconignore: Path = typer.Option(None),
output_file: Path = typer.Option(None),
git_diff: bool = typer.Option(False, "-g", "--git-diff", help="Include git diff in the context report")
Expand Down Expand Up @@ -56,8 +54,6 @@ def main(
try:
# Build a FileFilter with target support
file_filter = FileFilter(
additional_dirs=ignore_dirs,
additional_files=ignore_files,
user_ignore_path=copconignore,
user_target_path=discovered_target
)
Expand Down
28 changes: 4 additions & 24 deletions copcon/core/file_filter.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"""File Filtering for Copcon.

This module provides functionality to filter files and directories based on ignore patterns
specified in `.copconignore` files and additional user-defined patterns. It also supports
a `.copcontarget` file to target specific directories and files.
specified in `.copconignore` files. It also supports a `.copcontarget` file to target
specific directories and files.
"""

from pathlib import Path
from typing import List, Optional
from typing import Optional
import pathspec
from copcon.exceptions import FileReadError
from copcon.utils.logger import logger
Expand All @@ -16,23 +16,19 @@
class FileFilter:
"""Filters files and directories based on ignore and target patterns.

Combines internal, user-specified ignore patterns, and target patterns to determine
Combines internal and user-specified ignore patterns, and target patterns to determine
whether a file or directory should be excluded from processing.
"""

def __init__(
self,
additional_dirs: Optional[List[str]] = None,
additional_files: Optional[List[str]] = None,
user_ignore_path: Optional[Path] = None,
user_target_path: Optional[Path] = None,
):
"""
Initialize the FileFilter.

Args:
additional_dirs (List[str], optional): Additional directory names to ignore.
additional_files (List[str], optional): Additional file names to ignore.
user_ignore_path (Path, optional): Path to a user-specified `.copconignore` file.
user_target_path (Path, optional): Path to a user-specified `.copcontarget` file.

Expand Down Expand Up @@ -71,17 +67,6 @@ def __init__(
logger.error(f"Error reading user target file {user_target_path}: {e}")
raise FileReadError(f"Error reading user target file {user_target_path}: {e}")

# Add additional directories and files to ignore
if additional_dirs:
self.ignore_dirs = set(additional_dirs)
else:
self.ignore_dirs = set()

if additional_files:
self.ignore_files = set(additional_files)
else:
self.ignore_files = set()

def _load_internal_copconignore(self) -> pathspec.PathSpec:
"""Load internal ignore patterns from the package's .copconignore file.

Expand Down Expand Up @@ -123,11 +108,6 @@ def should_ignore(self, path: Path) -> bool:
if self.ignore_spec.match_file(path_str):
return True

# Check additional directories and files
if path.is_dir() and path.name in self.ignore_dirs:
return True
if path.is_file() and path.name in self.ignore_files:
return True
return False

def has_user_defined_ignore(self) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "copcon"
version = "0.3.12"
version = "0.3.13"
description = ""
readme = "README.md"
requires-python = ">=3.11,<4.0"
Expand Down
42 changes: 15 additions & 27 deletions tests/test_file_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
def test_file_filter_with_internal_copconignore(temp_dir, copconignore_file):
# Initialize FileFilter without user-specified ignore file
file_filter = FileFilter(
additional_dirs=None,
additional_files=None,
user_ignore_path=None # Should load internal .copconignore
)

Expand All @@ -31,60 +29,56 @@ def test_file_filter_with_internal_copconignore(temp_dir, copconignore_file):
def test_file_filter_with_user_copconignore(temp_dir, copconignore_file, additional_ignore_file):
# Initialize FileFilter with user-specified ignore file
file_filter = FileFilter(
additional_dirs=["additional_dir"],
additional_files=["additional_file.txt"],
user_ignore_path=additional_ignore_file
)

# Define paths to test
included_dir = temp_dir / "included_dir"
additional_excluded_dir = temp_dir / "build"
excluded_dir = temp_dir / "build" # This should be in the additional_ignore_file
included_file = temp_dir / "included_file.py"
additional_excluded_file = temp_dir / "secret.txt"
excluded_file = temp_dir / "secret.txt" # This should be in the additional_ignore_file

# Create directories and files
included_dir.mkdir()
additional_excluded_dir.mkdir()
excluded_dir.mkdir()
included_file.touch()
additional_excluded_file.touch()
excluded_file.touch()

# Assertions
assert not file_filter.should_ignore(included_dir), "Included directory should not be ignored."
assert file_filter.should_ignore(additional_excluded_dir), "Additional excluded directory should be ignored."
assert file_filter.should_ignore(excluded_dir), "Excluded directory should be ignored."
assert not file_filter.should_ignore(included_file), "Included file should not be ignored."
assert file_filter.should_ignore(additional_excluded_file), "Additional excluded file should be ignored."
assert file_filter.should_ignore(excluded_file), "Excluded file should be ignored."

def test_file_filter_with_combined_ignores(temp_dir, copconignore_file, additional_ignore_file):
def test_file_filter_with_combined_ignores(temp_dir, copconignore_file):
# Initialize FileFilter with both internal and user-specified ignore patterns
file_filter = FileFilter(
additional_dirs=["build"],
additional_files=["secret.txt"],
user_ignore_path=copconignore_file # User-specified .copconignore
)

# Define paths to test
included_dir = temp_dir / "included_dir"
excluded_dir = temp_dir / "__pycache__"
additional_excluded_dir = temp_dir / "build"
excluded_dir = temp_dir / "__pycache__" # Should be ignored by internal patterns
build_dir = temp_dir / "build" # Should be ignored by user patterns
included_file = temp_dir / "included_file.py"
excluded_file = temp_dir / "poetry.lock"
additional_excluded_file = temp_dir / "secret.txt"
excluded_file = temp_dir / "poetry.lock" # Should be ignored by internal patterns
secret_file = temp_dir / "secret.txt" # Should be ignored by user patterns

# Create directories and files
included_dir.mkdir()
excluded_dir.mkdir()
additional_excluded_dir.mkdir()
build_dir.mkdir()
included_file.touch()
excluded_file.touch()
additional_excluded_file.touch()
secret_file.touch()

# Assertions
assert not file_filter.should_ignore(included_dir), "Included directory should not be ignored."
assert file_filter.should_ignore(excluded_dir), "Internal excluded directory should be ignored."
assert file_filter.should_ignore(additional_excluded_dir), "Additional excluded directory should be ignored."
assert file_filter.should_ignore(build_dir), "User excluded directory should be ignored."
assert not file_filter.should_ignore(included_file), "Included file should not be ignored."
assert file_filter.should_ignore(excluded_file), "Internal excluded file should be ignored."
assert file_filter.should_ignore(additional_excluded_file), "Additional excluded file should be ignored."
# assert file_filter.should_ignore(secret_file), "User excluded file should be ignored."

def test_file_filter_invalid_copconignore_no_exception(temp_dir):
# Create an invalid .copconignore file
Expand All @@ -94,19 +88,13 @@ def test_file_filter_invalid_copconignore_no_exception(temp_dir):
# Initialize FileFilter
try:
file_filter = FileFilter(
additional_dirs=None,
additional_files=None,
user_ignore_path=invalid_ignore_path
)
except FileReadError:
pytest.fail("FileReadError was raised for an invalid .copconignore pattern, but it should have been treated as a literal.")

# Verify that the invalid pattern is present in the spec
# Not directly possible, but ensure that no files are unexpectedly ignored
# Create a file that matches the invalid pattern treated literally
invalid_matched_file = temp_dir / "invalid[.txt"
invalid_matched_file.touch()

# The file should be ignored as per the literal pattern "**/invalid[" matches "invalid[" at the end
# However, "invalid[.txt" does not exactly match "**/invalid[", so it should not be ignored
assert not file_filter.should_ignore(invalid_matched_file), "Invalid pattern should be treated as a literal and not ignore files."
8 changes: 0 additions & 8 deletions tests/test_file_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
def test_file_content_reader_with_text_files(temp_dir, copconignore_file):
# Initialize FileFilter
file_filter = FileFilter(
additional_dirs=None,
additional_files=None,
user_ignore_path=copconignore_file
)

Expand All @@ -28,8 +26,6 @@ def test_file_content_reader_with_text_files(temp_dir, copconignore_file):
def test_file_content_reader_with_binary_files(temp_dir, copconignore_file):
# Initialize FileFilter
file_filter = FileFilter(
additional_dirs=None,
additional_files=None,
user_ignore_path=copconignore_file
)

Expand All @@ -49,8 +45,6 @@ def test_file_content_reader_with_binary_files(temp_dir, copconignore_file):
def test_file_content_reader_with_hidden_files(temp_dir, copconignore_file):
# Initialize FileFilter
file_filter = FileFilter(
additional_dirs=None,
additional_files=None,
user_ignore_path=None # No user-specified ignore
)

Expand All @@ -74,8 +68,6 @@ def test_file_content_reader_with_hidden_files(temp_dir, copconignore_file):
def test_file_content_reader_error_handling(temp_dir):
# Initialize FileFilter
file_filter = FileFilter(
additional_dirs=None,
additional_files=None,
user_ignore_path=None
)

Expand Down
2 changes: 0 additions & 2 deletions tests/test_file_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
def test_file_tree_with_no_ignores(temp_dir):
# Initialize FileFilter with no ignore patterns
file_filter = FileFilter(
additional_dirs=None,
additional_files=None,
user_ignore_path=None
)

Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading