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