87 lines
2.9 KiB
Python
87 lines
2.9 KiB
Python
"""Renderers for the ResultTable API.
|
|
|
|
This module provides a Rich-based Renderer implementation that returns a
|
|
`rich.table.Table` renderable. The implementation is intentionally small and
|
|
focused on the command-line display use-case; keep logic side-effect-free where
|
|
possible and let callers decide whether to `Console.print()` or capture output.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Dict, Iterable, Optional
|
|
|
|
from SYS.result_table_api import ColumnSpec, ResultModel, ResultTable, Renderer
|
|
|
|
|
|
class RichRenderer(Renderer):
|
|
"""Rich renderer implementing the `Renderer` protocol.
|
|
|
|
Usage:
|
|
from rich.console import Console
|
|
table = RichRenderer().render(rows, columns, meta)
|
|
Console().print(table)
|
|
"""
|
|
|
|
def render(self, rows: Iterable[ResultModel], columns: Iterable[ColumnSpec], meta: Optional[Dict[str, Any]] = None) -> Any: # pragma: no cover - simple wrapper
|
|
try:
|
|
from rich.table import Table as RichTable
|
|
except Exception as exc:
|
|
raise RuntimeError("rich is required for RichRenderer") from exc
|
|
|
|
table = RichTable(show_header=True, header_style="bold")
|
|
cols = list(columns)
|
|
for col in cols:
|
|
table.add_column(col.header)
|
|
|
|
for r in rows:
|
|
cells = []
|
|
for col in cols:
|
|
try:
|
|
raw = col.extractor(r)
|
|
if col.format_fn:
|
|
try:
|
|
cell = col.format_fn(raw)
|
|
except Exception:
|
|
cell = str(raw or "")
|
|
else:
|
|
cell = str(raw or "")
|
|
except Exception:
|
|
cell = ""
|
|
cells.append(cell)
|
|
table.add_row(*cells)
|
|
|
|
return table
|
|
|
|
|
|
# Small convenience function
|
|
|
|
def render_to_console(rows: Iterable[ResultModel], columns: Iterable[ColumnSpec], meta: Optional[Dict[str, Any]] = None) -> None:
|
|
try:
|
|
from rich.console import Console
|
|
except Exception:
|
|
# If rich isn't present, fall back to simple text output
|
|
for r in rows:
|
|
print(" ".join(str((col.extractor(r) or "")) for col in columns))
|
|
return
|
|
|
|
table = RichRenderer().render(rows, columns, meta)
|
|
Console().print(table)
|
|
|
|
|
|
def render_result_table(table: ResultTable, renderer: Optional[Renderer] = None) -> Any:
|
|
"""Render a ResultTable with the provided renderer (RichRenderer by default)."""
|
|
|
|
rend = renderer or RichRenderer()
|
|
return rend.render(table.rows, table.columns, table.meta)
|
|
|
|
|
|
def render_result_table_to_console(table: ResultTable, renderer: Optional[Renderer] = None) -> None:
|
|
try:
|
|
from rich.console import Console
|
|
except Exception:
|
|
for r in table.rows:
|
|
print(" ".join(str((col.extractor(r) or "")) for col in table.columns))
|
|
return
|
|
|
|
console = Console()
|
|
console.print(render_result_table(table, renderer))
|