Source code for pycsamt.pipeline._richview
"""Live rich.table.Table rendering for ``progress_style="rich"``.
Kept separate from ``_pipeline.py`` so the run loop only has to call
:func:`make_rich_live` once and mutate the returned row dicts — the table
itself is always rebuilt from scratch on each repaint (``rich.table.Table``
has no supported in-place cell-update API), which is the standard idiom for
driving a changing table through :class:`rich.live.Live`.
"""
from __future__ import annotations
from typing import Any
__all__ = ["make_rich_live"]
_STATUS_STYLE = {
"pending": None,
"running": "yellow",
"OK": "bold green",
"ERR": "bold red",
}
[docs]
def make_rich_live(pipeline_name: str, steps: list[tuple[str, Any]]):
"""Return ``(live, rows, render)`` for a pipeline about to run *steps*.
*rows* is a list of plain dicts, one per step, pre-populated as
``"pending"`` — mutate a row's fields, then call ``live.update(render())``
to repaint. *live* has already been ``.start()``-ed.
"""
from rich.live import Live
from rich.table import Table
rows: list[dict[str, str]] = [
{
"idx": str(i),
"label": label,
"code": step.spec.code,
"status": "pending",
"elapsed": "",
"sites": "",
"cached": "",
}
for i, (label, step) in enumerate(steps, start=1)
]
def render() -> Table:
table = Table(title=f"{pipeline_name} ({len(rows)} step(s))")
table.add_column("#", justify="right")
table.add_column("Step")
table.add_column("Code")
table.add_column("Status")
table.add_column("Time", justify="right")
table.add_column("Sites")
table.add_column("Cached")
for r in rows:
style = _STATUS_STYLE.get(r["status"])
status_text = f"[{style}]{r['status']}[/{style}]" if style else r["status"]
table.add_row(
r["idx"], r["label"], r["code"], status_text,
r["elapsed"], r["sites"], r["cached"],
)
return table
live = Live(render(), refresh_per_second=4, transient=False)
live.start()
return live, rows, render