From 11fda02dba26f98eb0131d9fb70f28ccc3d71784 Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Mon, 2 Feb 2026 21:31:33 +0000 Subject: [PATCH] Add core CLI and configuration modules --- depaudit/config.py | 119 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 depaudit/config.py diff --git a/depaudit/config.py b/depaudit/config.py new file mode 100644 index 0000000..118dfa0 --- /dev/null +++ b/depaudit/config.py @@ -0,0 +1,119 @@ +from __future__ import annotations + +import os +from pathlib import Path +from typing import Any + +import yaml + + +class Config: + def __init__(self, config_path: Path | None = None): + self.config_path = config_path or self._find_config() + self._config: dict[str, Any] = {} + self._load_config() + + def _find_config(self) -> Path | None: + possible_paths = [ + Path(".depauditrc"), + Path("depaudit.config.yaml"), + Path(os.environ.get("DEPAUDIT_CONFIG_FILE", "")), + Path.home() / ".depauditrc", + ] + for path in possible_paths: + if path.exists() and path.stat().st_size > 0: + return path + return None + + def _load_config(self) -> None: + if self.config_path and self.config_path.exists(): + with open(self.config_path, "r") as f: + self._config = yaml.safe_load(f) or {} + else: + self._config = {} + + def get(self, key: str, default: Any = None) -> Any: + keys = key.split(".") + value = self._config + for k in keys: + if isinstance(value, dict): + value = value.get(k) + else: + return default + if value is None: + return default + return value + + @property + def output_format(self) -> str: + return self.get("output.format", "table") + + @property + def use_color(self) -> bool: + color = self.get("output.color", True) + if color is None: + return True + return color + + @property + def verbosity(self) -> str: + return self.get("output.verbosity", "info") + + @property + def vulnerabilities_enabled(self) -> bool: + return self.get("vulnerabilities.enabled", True) + + @property + def severity_filter(self) -> str: + return self.get("vulnerabilities.severity_filter", "all") + + @property + def outdated_enabled(self) -> bool: + return self.get("outdated.enabled", True) + + @property + def licenses_enabled(self) -> bool: + return self.get("licenses.enabled", True) + + @property + def license_allowlist(self) -> list[str]: + return self.get("licenses.allowlist", [ + "MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", "ISC", "MPL-2.0" + ]) + + @property + def license_blocklist(self) -> list[str]: + return self.get("licenses.blocklist", [ + "GPL-1.0", "GPL-2.0", "GPL-3.0", "AGPL-1.0", "AGPL-3.0" + ]) + + @property + def unused_enabled(self) -> bool: + return self.get("unused.enabled", True) + + @property + def cache_enabled(self) -> bool: + return self.get("cache.enabled", True) + + @property + def cache_directory(self) -> Path: + cache_dir = self.get("cache.directory", "~/.cache/depaudit") + return Path(cache_dir).expanduser() + + @property + def cache_ttl(self) -> int: + return self.get("cache.ttl", 604800) + + @property + def network_timeout(self) -> int: + return self.get("network.timeout", 30) + + @property + def cicd_fail_on(self) -> list[str]: + return self.get("cicd.fail_on", ["critical", "high"]) + + def reload(self) -> None: + self._load_config() + + +config = Config()