"""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, 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)