File size: 6,240 Bytes
350babd | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | from rich.console import Console
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn, TaskProgressColumn, TimeElapsedColumn
from rich.panel import Panel
from rich.table import Table
from rich.live import Live
from rich.layout import Layout
from rich.text import Text
from contextlib import contextmanager
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class ProgressStats:
"""Statistics for progress display."""
total_entries: int = 0
processed: int = 0
success: int = 0
warnings: int = 0
errors: int = 0
current_entry: str = ""
current_task: str = ""
class ProgressDisplay:
"""Rich terminal progress display."""
def __init__(self):
self.console = Console()
self.stats = ProgressStats()
self._progress: Optional[Progress] = None
self._live: Optional[Live] = None
self._main_task = None
def _create_stats_table(self) -> Table:
"""Create a statistics table."""
table = Table(show_header=False, box=None, padding=(0, 2))
table.add_column("Label", style="dim")
table.add_column("Value", style="bold")
table.add_row("π Total Entries", str(self.stats.total_entries))
table.add_row("β
Success", f"[green]{self.stats.success}[/green]")
table.add_row("β οΈ Warnings", f"[yellow]{self.stats.warnings}[/yellow]")
table.add_row("β Errors", f"[red]{self.stats.errors}[/red]")
return table
def _create_display(self) -> Panel:
"""Create the main display panel."""
layout = Layout()
# Status text
status_text = Text()
status_text.append("Current: ", style="dim")
status_text.append(self.stats.current_entry or "N/A", style="cyan bold")
status_text.append("\n")
status_text.append("Task: ", style="dim")
status_text.append(self.stats.current_task or "Initializing...", style="white")
return Panel(
status_text,
title="[bold blue]π Bibliography Checker[/bold blue]",
border_style="blue"
)
@contextmanager
def progress_context(self, total: int, description: str = "Processing"):
"""Context manager for progress display."""
self.stats.total_entries = total
with Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
BarColumn(bar_width=40),
TaskProgressColumn(),
TimeElapsedColumn(),
console=self.console,
transient=False
) as progress:
self._progress = progress
self._main_task = progress.add_task(description, total=total)
try:
yield self
finally:
self._progress = None
self._main_task = None
def update(self, entry_key: str = "", task: str = "", advance: int = 0):
"""Update progress display."""
if entry_key:
self.stats.current_entry = entry_key
if task:
self.stats.current_task = task
if self._progress and self._main_task is not None:
desc = f"[cyan]{entry_key}[/cyan] - {task}" if entry_key else task
self._progress.update(self._main_task, description=desc, advance=advance)
self.stats.processed += advance
def mark_success(self):
"""Mark current entry as successful."""
self.stats.success += 1
def mark_warning(self):
"""Mark current entry with warning."""
self.stats.warnings += 1
def mark_error(self):
"""Mark current entry as error."""
self.stats.errors += 1
def print_header(self, title: str):
"""Print a section header."""
self.console.print()
self.console.print(Panel(
f"[bold]{title}[/bold]",
border_style="blue",
expand=False
))
def print_status(self, message: str, style: str = ""):
"""Print a status message."""
self.console.print(f" {message}", style=style)
def print_success(self, message: str):
"""Print a success message."""
self.console.print(f" [green]β[/green] {message}")
def print_warning(self, message: str):
"""Print a warning message."""
self.console.print(f" [yellow]β [/yellow] {message}")
def print_error(self, message: str):
"""Print an error message."""
self.console.print(f" [red]β[/red] {message}")
def print_info(self, message: str):
"""Print an info message."""
self.console.print(f" [blue]βΉ[/blue] {message}")
def print_detailed_summary(self, bib_stats: dict, output_dir: str):
"""Print bibliography issue summary (bib-only)."""
self.console.print()
bib_table = Table(show_header=True, header_style="bold cyan", box=None, padding=(0, 1))
bib_table.add_column("π Bibliography Issues", style="white")
bib_table.add_column("Count", justify="right", style="bold red")
if bib_stats:
for label, value in bib_stats.items():
bib_table.add_row(label, str(value))
else:
bib_table.add_row("[green]No issues found[/green]", "0")
summary_panel = Panel(
bib_table,
title="[bold]π Bibliography Summary[/bold]",
border_style="blue",
padding=(1, 2),
)
self.console.print(summary_panel)
guide_table = Table(show_header=True, header_style="bold green", box=None, padding=(0, 2))
guide_table.add_column("File Name", style="cyan")
guide_table.add_column("Description", style="dim")
guide_table.add_row("bibliography_report.md", "Metadata verification and issues for each bib entry")
self.console.print(Panel(
guide_table,
title="[bold green]Output Directory[/bold green]",
subtitle=f"Location: [blue underline]{output_dir}[/blue underline]",
border_style="green",
padding=(1, 1),
))
|