Fix mypy type errors in source code
Some checks failed
CI/CD / lint-and-test (push) Has been cancelled
Some checks failed
CI/CD / lint-and-test (push) Has been cancelled
This commit is contained in:
141
app/local-ai-commit-reviewer/src/formatters/formatters.py
Normal file
141
app/local-ai-commit-reviewer/src/formatters/formatters.py
Normal file
@@ -0,0 +1,141 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
from rich.console import Console
|
||||
from rich.panel import Panel
|
||||
from rich.style import Style
|
||||
from rich.table import Table
|
||||
from rich.text import Text
|
||||
|
||||
from ..core import Issue, IssueCategory, IssueSeverity, ReviewResult
|
||||
|
||||
|
||||
class BaseFormatter(ABC):
|
||||
@abstractmethod
|
||||
def format(self, result: ReviewResult) -> str:
|
||||
pass
|
||||
|
||||
|
||||
class TerminalFormatter(BaseFormatter):
|
||||
def __init__(self, theme: str = "auto", show_line_numbers: bool = True):
|
||||
self.console = Console()
|
||||
self.show_line_numbers = show_line_numbers
|
||||
self.use_colors = theme != "dark" if theme == "auto" else theme == "dark"
|
||||
|
||||
def _get_severity_style(self, severity: IssueSeverity) -> Style:
|
||||
styles = {
|
||||
IssueSeverity.CRITICAL: Style(color="red", bold=True),
|
||||
IssueSeverity.WARNING: Style(color="yellow"),
|
||||
IssueSeverity.INFO: Style(color="blue"),
|
||||
}
|
||||
return styles.get(severity, Style())
|
||||
|
||||
def _get_category_icon(self, category: IssueCategory) -> str:
|
||||
icons = {
|
||||
IssueCategory.BUG: "[BUG]",
|
||||
IssueCategory.SECURITY: "[SECURITY]",
|
||||
IssueCategory.STYLE: "[STYLE]",
|
||||
IssueCategory.PERFORMANCE: "[PERF]",
|
||||
IssueCategory.DOCUMENTATION: "[DOC]",
|
||||
}
|
||||
return icons.get(category, "")
|
||||
|
||||
def _format_issue(self, issue: Issue) -> Text:
|
||||
text = Text()
|
||||
text.append(f"{issue.file}:{issue.line} ", style="dim")
|
||||
text.append(f"[{issue.severity.value.upper()}] ", self._get_severity_style(issue.severity))
|
||||
text.append(f"{self._get_category_icon(issue.category)} ")
|
||||
text.append(issue.message)
|
||||
|
||||
if issue.suggestion:
|
||||
text.append("\n Suggestion: ", style="dim")
|
||||
text.append(issue.suggestion)
|
||||
|
||||
return text
|
||||
|
||||
def format(self, result: ReviewResult) -> str:
|
||||
output: list[Panel | Table | str] = []
|
||||
|
||||
if result.error:
|
||||
output.append(Panel(
|
||||
f"[red]Error: {result.error}[/red]",
|
||||
title="Review Failed",
|
||||
expand=False
|
||||
))
|
||||
return "\n".join(str(p) for p in output)
|
||||
|
||||
summary = result.summary
|
||||
|
||||
summary_panel = Panel(
|
||||
f"[bold]Files Reviewed:[/bold] {summary.files_reviewed}\n"
|
||||
f"[bold]Lines Changed:[/bold] {summary.lines_changed}\n\n"
|
||||
f"[red]Critical:[/red] {summary.critical_count} "
|
||||
f"[yellow]Warnings:[/yellow] {summary.warning_count} "
|
||||
f"[blue]Info:[/blue] {summary.info_count}\n\n"
|
||||
f"[bold]Assessment:[/bold] {summary.overall_assessment}",
|
||||
title="Review Summary",
|
||||
expand=False
|
||||
)
|
||||
output.append(summary_panel)
|
||||
|
||||
if result.issues:
|
||||
issues_table = Table(title="Issues Found", show_header=True)
|
||||
issues_table.add_column("File", style="dim")
|
||||
issues_table.add_column("Line", justify="right", style="dim")
|
||||
issues_table.add_column("Severity", width=10)
|
||||
issues_table.add_column("Category", width=12)
|
||||
issues_table.add_column("Message")
|
||||
|
||||
for issue in result.issues:
|
||||
issues_table.add_row(
|
||||
issue.file,
|
||||
str(issue.line),
|
||||
f"[{issue.severity.value.upper()}]",
|
||||
f"[{issue.category.value.upper()}]",
|
||||
issue.message,
|
||||
style=self._get_severity_style(issue.severity)
|
||||
)
|
||||
|
||||
output.append(issues_table)
|
||||
|
||||
suggestions_panel = Panel(
|
||||
"\n".join(
|
||||
f"[bold]{issue.file}:{issue.line}[/bold]\n"
|
||||
f" {issue.message}\n"
|
||||
+ (f" [green]→ {issue.suggestion}[/green]\n" if issue.suggestion else "")
|
||||
for issue in result.issues if issue.suggestion
|
||||
),
|
||||
title="Suggestions",
|
||||
expand=False
|
||||
)
|
||||
output.append(suggestions_panel)
|
||||
|
||||
model_info = Panel(
|
||||
f"[bold]Model:[/bold] {result.model_used}\n"
|
||||
f"[bold]Tokens Used:[/bold] {result.tokens_used}\n"
|
||||
f"[bold]Mode:[/bold] {result.review_mode}",
|
||||
title="Review Info",
|
||||
expand=False
|
||||
)
|
||||
output.append(model_info)
|
||||
|
||||
return "\n".join(str(o) for o in output)
|
||||
|
||||
|
||||
class JSONFormatter(BaseFormatter):
|
||||
def format(self, result: ReviewResult) -> str:
|
||||
return result.to_json()
|
||||
|
||||
|
||||
class MarkdownFormatter(BaseFormatter):
|
||||
def format(self, result: ReviewResult) -> str:
|
||||
return result.to_markdown()
|
||||
|
||||
|
||||
def get_formatter(format_type: str = "terminal", **kwargs) -> BaseFormatter:
|
||||
formatters: dict[str, type[BaseFormatter]] = {
|
||||
"terminal": TerminalFormatter,
|
||||
"json": JSONFormatter,
|
||||
"markdown": MarkdownFormatter,
|
||||
}
|
||||
formatter_class = formatters.get(format_type, TerminalFormatter)
|
||||
return formatter_class(**kwargs) # type: ignore[arg-type]
|
||||
Reference in New Issue
Block a user