From 0f1ca3b536ee83951142ed29a64f06a4a3b080b0 Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Mon, 2 Feb 2026 21:35:55 +0000 Subject: [PATCH] Add output formatters --- depaudit/output/__init__.py | 62 +++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 depaudit/output/__init__.py diff --git a/depaudit/output/__init__.py b/depaudit/output/__init__.py new file mode 100644 index 0000000..63b64dd --- /dev/null +++ b/depaudit/output/__init__.py @@ -0,0 +1,62 @@ +from __future__ import annotations + +from abc import ABC, abstractmethod +from dataclasses import dataclass, field +from typing import Any + + +@dataclass +class AuditResult: + vulnerabilities: list[dict[str, Any]] = field(default_factory=list) + outdated: list[dict[str, Any]] = field(default_factory=list) + license_issues: list[dict[str, Any]] = field(default_factory=list) + unused: list[dict[str, Any]] = field(default_factory=list) + scanned_files: list[str] = field(default_factory=list) + scanned_count: int = 0 + error_count: int = 0 + scan_duration: float = 0.0 + + def to_dict(self) -> dict[str, Any]: + return { + "vulnerabilities": self.vulnerabilities, + "outdated": self.outdated, + "license_issues": self.license_issues, + "unused": self.unused, + "scanned_files": self.scanned_files, + "scanned_count": self.scanned_count, + "error_count": self.error_count, + "scan_duration": self.scan_duration, + "summary": self.get_summary(), + } + + def get_summary(self) -> dict[str, Any]: + severity_counts: dict[str, int] = {"critical": 0, "high": 0, "medium": 0, "low": 0} + for vuln in self.vulnerabilities: + severity = vuln.get("severity", "unknown") + if severity in severity_counts: + severity_counts[severity] += 1 + + return { + "total_vulnerabilities": len(self.vulnerabilities), + "severity_breakdown": severity_counts, + "total_outdated": len(self.outdated), + "total_license_issues": len(self.license_issues), + "total_unused": len(self.unused), + } + + +class Formatter(ABC): + def __init__(self, use_color: bool = True, verbosity: str = "info"): + self.use_color = use_color + self.verbosity = verbosity + + @abstractmethod + def format(self, result: AuditResult) -> str: + pass + + def verbose(self, message: str) -> None: + if self.verbosity == "debug": + self._log(message) + + def _log(self, message: str) -> None: + print(message)