diff --git a/src/depcheck/config.py b/src/depcheck/config.py new file mode 100644 index 0000000..da271b5 --- /dev/null +++ b/src/depcheck/config.py @@ -0,0 +1,102 @@ +"""Configuration system for depcheck.""" + +import fnmatch +import os +from dataclasses import dataclass, field +from pathlib import Path +from typing import Optional + +import yaml + +from depcheck.models import Severity + + +@dataclass +class Config: + """Configuration for depcheck.""" + + ignore_patterns: list[str] = field(default_factory=list) + ignore_packages: list[str] = field(default_factory=list) + fail_level: Severity = Severity.MEDIUM + output_format: str = "terminal" + verbose: bool = False + quiet: bool = False + include_dev: bool = True + package_managers: list[str] = field(default_factory=list) + + +def load_config(config_path: Optional[Path] = None) -> Config: + """Load configuration from file.""" + config = Config() + + if config_path is None: + config_path = _find_config_file() + + if config_path and config_path.exists(): + try: + content = config_path.read_text() + data = yaml.safe_load(content) or {} + except (yaml.YAMLError, OSError): + return config + else: + return config + + if "ignore_patterns" in data: + config.ignore_patterns = data["ignore_patterns"] + + if "ignore_packages" in data: + config.ignore_packages = data["ignore_packages"] + + if "fail_level" in data: + try: + config.fail_level = Severity(data["fail_level"]) + except ValueError: + pass + + if "output" in data: + output = data["output"] + if "format" in output: + config.output_format = output["format"] + if "verbose" in output: + config.verbose = output["verbose"] + if "quiet" in output: + config.quiet = output["quiet"] + + if "include_dev" in data: + config.include_dev = data["include_dev"] + + if "package_managers" in data: + config.package_managers = data["package_managers"] + + return config + + +def _find_config_file() -> Optional[Path]: + """Find config file in current dir or XDG locations.""" + current_dir = Path.cwd() + config_path = current_dir / ".depcheck.yaml" + if config_path.exists(): + return config_path + + xdg_config = os.environ.get("XDG_CONFIG_HOME", str(Path.home() / ".config")) + xdg_config_path = Path(xdg_config) / "depcheck" / ".depcheck.yaml" + if xdg_config_path.exists(): + return xdg_config_path + + return None + + +def should_ignore_package(config: Config, package_name: str) -> bool: + """Check if a package should be ignored.""" + for pattern in config.ignore_packages: + if fnmatch.fnmatch(package_name, pattern): + return True + return False + + +def should_ignore_file(config: Config, file_path: Path) -> bool: + """Check if a file should be ignored.""" + for pattern in config.ignore_patterns: + if pattern in str(file_path): + return True + return False