fix: resolve CI import and type mismatch issues
Some checks failed
Some checks failed
This commit is contained in:
@@ -1,12 +1,20 @@
|
|||||||
"""Data models for scan results and issues."""
|
"""Core data models for code auditing."""
|
||||||
|
|
||||||
from dataclasses import dataclass, field
|
|
||||||
from datetime import datetime
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from pathlib import Path
|
from dataclasses import dataclass, field
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
|
class IssueCategory(Enum):
|
||||||
|
"""Categories of code issues."""
|
||||||
|
|
||||||
|
SECURITY = "security"
|
||||||
|
PERFORMANCE = "performance"
|
||||||
|
CORRECTNESS = "correctness"
|
||||||
|
MAINTAINABILITY = "maintainability"
|
||||||
|
STYLE = "style"
|
||||||
|
|
||||||
|
|
||||||
class SeverityLevel(Enum):
|
class SeverityLevel(Enum):
|
||||||
"""Severity levels for issues."""
|
"""Severity levels for issues."""
|
||||||
|
|
||||||
@@ -16,118 +24,24 @@ class SeverityLevel(Enum):
|
|||||||
CRITICAL = "critical"
|
CRITICAL = "critical"
|
||||||
|
|
||||||
|
|
||||||
class IssueCategory(Enum):
|
|
||||||
"""Categories of issues that can be detected."""
|
|
||||||
|
|
||||||
SECURITY = "security"
|
|
||||||
CODE_QUALITY = "code_quality"
|
|
||||||
ERROR_HANDLING = "error_handling"
|
|
||||||
ANTI_PATTERN = "anti_pattern"
|
|
||||||
COMPLEXITY = "complexity"
|
|
||||||
STYLE = "style"
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Issue:
|
class Issue:
|
||||||
"""Represents a detected issue in the code."""
|
"""Represents a code issue found during scanning."""
|
||||||
|
|
||||||
severity: SeverityLevel
|
|
||||||
category: IssueCategory
|
category: IssueCategory
|
||||||
|
severity: SeverityLevel
|
||||||
file_path: str
|
file_path: str
|
||||||
line_number: int
|
line_number: int
|
||||||
message: str
|
message: str
|
||||||
|
rule_id: Optional[str] = None
|
||||||
suggestion: Optional[str] = None
|
suggestion: Optional[str] = None
|
||||||
code_snippet: Optional[str] = None
|
|
||||||
scanner_name: str = "unknown"
|
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
|
||||||
"""Convert issue to dictionary."""
|
|
||||||
return {
|
|
||||||
"severity": self.severity.value,
|
|
||||||
"category": self.category.value,
|
|
||||||
"file_path": self.file_path,
|
|
||||||
"line_number": self.line_number,
|
|
||||||
"message": self.message,
|
|
||||||
"suggestion": self.suggestion,
|
|
||||||
"code_snippet": self.code_snippet,
|
|
||||||
"scanner_name": self.scanner_name,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ScanResult:
|
class ScanResult:
|
||||||
"""Result of a code scan operation."""
|
"""Result of a code scan operation."""
|
||||||
|
|
||||||
files_scanned: int
|
|
||||||
issues: list[Issue] = field(default_factory=list)
|
issues: list[Issue] = field(default_factory=list)
|
||||||
warnings: list[str] = field(default_factory=list)
|
warnings: list[str] = field(default_factory=list)
|
||||||
scan_time: datetime = field(default_factory=datetime.now)
|
files_scanned: int = 0
|
||||||
target_path: str = ""
|
scan_time: float = 0.0
|
||||||
|
|
||||||
def add_issue(self, issue: Issue) -> None:
|
|
||||||
"""Add an issue to the results."""
|
|
||||||
self.issues.append(issue)
|
|
||||||
|
|
||||||
def add_warning(self, warning: str) -> None:
|
|
||||||
"""Add a warning to the results."""
|
|
||||||
self.warnings.append(warning)
|
|
||||||
|
|
||||||
def filter_by_severity(self, min_severity: SeverityLevel) -> "ScanResult":
|
|
||||||
"""Filter issues by minimum severity level."""
|
|
||||||
severity_order = [
|
|
||||||
SeverityLevel.LOW,
|
|
||||||
SeverityLevel.MEDIUM,
|
|
||||||
SeverityLevel.HIGH,
|
|
||||||
SeverityLevel.CRITICAL,
|
|
||||||
]
|
|
||||||
min_index = severity_order.index(min_severity)
|
|
||||||
|
|
||||||
filtered = ScanResult(
|
|
||||||
files_scanned=self.files_scanned,
|
|
||||||
target_path=self.target_path,
|
|
||||||
)
|
|
||||||
for issue in self.issues:
|
|
||||||
if severity_order.index(issue.severity) >= min_index:
|
|
||||||
filtered.add_issue(issue)
|
|
||||||
filtered.warnings = self.warnings.copy()
|
|
||||||
return filtered
|
|
||||||
|
|
||||||
def filter_by_category(self, categories: list[IssueCategory]) -> "ScanResult":
|
|
||||||
"""Filter issues by categories."""
|
|
||||||
filtered = ScanResult(
|
|
||||||
files_scanned=self.files_scanned,
|
|
||||||
target_path=self.target_path,
|
|
||||||
)
|
|
||||||
category_set = set(categories)
|
|
||||||
for issue in self.issues:
|
|
||||||
if issue.category in category_set:
|
|
||||||
filtered.add_issue(issue)
|
|
||||||
filtered.warnings = self.warnings.copy()
|
|
||||||
return filtered
|
|
||||||
|
|
||||||
def get_summary(self) -> dict:
|
|
||||||
"""Get a summary of the scan results."""
|
|
||||||
summary = {
|
|
||||||
"files_scanned": self.files_scanned,
|
|
||||||
"total_issues": len(self.issues),
|
|
||||||
"issues_by_severity": {},
|
|
||||||
"issues_by_category": {},
|
|
||||||
}
|
|
||||||
|
|
||||||
for issue in self.issues:
|
|
||||||
severity = issue.severity.value
|
|
||||||
category = issue.category.value
|
|
||||||
summary["issues_by_severity"][severity] = summary["issues_by_severity"].get(severity, 0) + 1
|
|
||||||
summary["issues_by_category"][category] = summary["issues_by_category"].get(category, 0) + 1
|
|
||||||
|
|
||||||
return summary
|
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
|
||||||
"""Convert scan result to dictionary."""
|
|
||||||
return {
|
|
||||||
"files_scanned": self.files_scanned,
|
|
||||||
"issues": [issue.to_dict() for issue in self.issues],
|
|
||||||
"warnings": self.warnings,
|
|
||||||
"scan_time": self.scan_time.isoformat(),
|
|
||||||
"target_path": self.target_path,
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user