63 lines
2.1 KiB
Python
63 lines
2.1 KiB
Python
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)
|