From f1e7bd1a24cc39f5797e79b6044c0cbc9645b7b9 Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Tue, 3 Feb 2026 07:01:16 +0000 Subject: [PATCH] Add reports, integrations, and utils modules --- vibeguard/utils/config.py | 192 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 vibeguard/utils/config.py diff --git a/vibeguard/utils/config.py b/vibeguard/utils/config.py new file mode 100644 index 0000000..a3eb842 --- /dev/null +++ b/vibeguard/utils/config.py @@ -0,0 +1,192 @@ +"""Configuration handling for VibeGuard.""" + +from dataclasses import dataclass, field +from pathlib import Path +from typing import Any + + +@dataclass +class AnalyzeConfig: + """Configuration for analysis settings.""" + + severity_threshold: str = "warning" + incremental: bool = True + workers: int = 0 + + +@dataclass +class PatternsConfig: + """Configuration for pattern settings.""" + + enabled: list[str] = field(default_factory=lambda: ["all"]) + disabled: list[str] = field(default_factory=list) + + +@dataclass +class IgnoreConfig: + """Configuration for ignore paths.""" + + paths: list[str] = field( + default_factory=lambda: [ + "*.egg-info/", + "*.pyc", + "__pycache__/", + ".git/", + "node_modules/", + "vendor/", + ".tox/", + ".venv/", + "venv/", + "build/", + "dist/", + "*.egg-info/", + ] + ) + + +@dataclass +class OutputConfig: + """Configuration for output settings.""" + + theme: str = "default" + show_fixes: bool = True + show_snippets: bool = True + max_snippet_lines: int = 10 + + +@dataclass +class FormatsConfig: + """Configuration for output formats.""" + + json: bool = True + html: bool = True + sarif: bool = True + + +@dataclass +class GitHubConfig: + """Configuration for GitHub integration.""" + + comment_on_pr: bool = False + create_check_runs: bool = True + sarif_upload_url: str = "" + + +@dataclass +class Config: + """Main configuration class for VibeGuard.""" + + version: str = "0.1.0" + analyze: AnalyzeConfig = field(default_factory=AnalyzeConfig) + patterns: PatternsConfig = field(default_factory=PatternsConfig) + ignore: IgnoreConfig = field(default_factory=IgnoreConfig) + output: OutputConfig = field(default_factory=OutputConfig) + formats: FormatsConfig = field(default_factory=FormatsConfig) + github: GitHubConfig = field(default_factory=GitHubConfig) + + verbose: bool = False + output_format: str = "console" + + def __post_init__(self) -> None: + pass + + def to_dict(self) -> dict[str, Any]: + """Convert config to dictionary.""" + return { + "version": self.version, + "analyze": { + "severity_threshold": self.analyze.severity_threshold, + "incremental": self.analyze.incremental, + "workers": self.analyze.workers, + }, + "patterns": { + "enabled": self.patterns.enabled, + "disabled": self.patterns.disabled, + }, + "ignore": { + "paths": self.ignore.paths, + }, + "output": { + "theme": self.output.theme, + "show_fixes": self.output.show_fixes, + "show_snippets": self.output.show_snippets, + "max_snippet_lines": self.output.max_snippet_lines, + }, + "formats": { + "json": self.formats.json, + "html": self.formats.html, + "sarif": self.formats.sarif, + }, + "github": { + "comment_on_pr": self.github.comment_on_pr, + "create_check_runs": self.github.create_check_runs, + "sarif_upload_url": self.github.sarif_upload_url, + }, + } + + +def load_config(config_path: str | None = None) -> Config: + """Load configuration from a file.""" + config = Config() + + if not config_path: + config_path = ".vibeguard.toml" + + path = Path(config_path) + if not path.exists(): + return config + + try: + import tomllib + + with open(path, "rb") as f: + data = tomllib.load(f) + except ImportError: + import tomli + + with open(path, "rb") as f: + data = tomli.load(f) + + if "analyze" in data: + config.analyze.severity_threshold = data["analyze"].get( + "severity_threshold", config.analyze.severity_threshold + ) + config.analyze.incremental = data["analyze"].get( + "incremental", config.analyze.incremental + ) + config.analyze.workers = data["analyze"].get("workers", config.analyze.workers) + + if "patterns" in data: + config.patterns.enabled = data["patterns"].get("enabled", config.patterns.enabled) + config.patterns.disabled = data["patterns"].get("disabled", config.patterns.disabled) + + if "ignore" in data: + config.ignore.paths = data["ignore"].get("paths", config.ignore.paths) + + if "output" in data: + config.output.theme = data["output"].get("theme", config.output.theme) + config.output.show_fixes = data["output"].get("show_fixes", config.output.show_fixes) + config.output.show_snippets = data["output"].get( + "show_snippets", config.output.show_snippets + ) + config.output.max_snippet_lines = data["output"].get( + "max_snippet_lines", config.output.max_snippet_lines + ) + + if "formats" in data: + config.formats.json = data["formats"].get("json", config.formats.json) + config.formats.html = data["formats"].get("html", config.formats.html) + config.formats.sarif = data["formats"].get("sarif", config.formats.sarif) + + if "github" in data: + config.github.comment_on_pr = data["github"].get( + "comment_on_pr", config.github.comment_on_pr + ) + config.github.create_check_runs = data["github"].get( + "create_check_runs", config.github.create_check_runs + ) + config.github.sarif_upload_url = data["github"].get( + "sarif_upload_url", config.github.sarif_upload_url + ) + + return config