Spaces:
Sleeping
Sleeping
File size: 3,310 Bytes
78d2329 | 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 | """Shared rich console for consistent, professional terminal output.
A single `CONSOLE` instance keeps styling uniform across the codebase. rich
degrades gracefully when stdout is not a tty (e.g. SLURM log files): no
animations, plain box-drawing characters — still fully readable.
Usage:
from optgs.misc.console import CONSOLE, banner, rule, warn
banner("optgs", ["host galvani", "mode test"])
rule("Testing scene 3: room_0")
warn("Skipping batch 7 due to OOM")
"""
from __future__ import annotations
import sys
from rich import box
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.theme import Theme
OPTGS_THEME = Theme(
{
"info": "cyan",
"warning": "yellow",
"error": "bold red",
"success": "bold green",
"metric": "bold magenta",
"path": "blue underline",
"muted": "dim",
}
)
# Off-tty (SLURM logs, pipes) rich defaults to width 80, which wraps config
# rows awkwardly. Pin a wider, fixed width there; let interactive terminals
# auto-size so output adapts to the real window.
_console_kwargs: dict = {"theme": OPTGS_THEME}
if not sys.stdout.isatty():
_console_kwargs["width"] = 120
CONSOLE = Console(**_console_kwargs)
def banner(title: str, lines: list[str] | None = None, style: str = "info") -> None:
"""Print a titled panel; `lines` form the panel body."""
body = "\n".join(lines) if lines else ""
CONSOLE.print(
Panel(body, title=title, title_align="left", border_style=style, expand=False)
)
def rule(title: str, style: str = "info") -> None:
"""Print a horizontal section divider with a centered title."""
CONSOLE.rule(f"[{style}]{title}[/{style}]", style=style)
def warn(msg: str) -> None:
"""Print a styled warning line."""
CONSOLE.print(f"[warning]⚠ {msg}[/warning]")
def error(msg: str) -> None:
"""Print a styled error line."""
CONSOLE.print(f"[error]✖ {msg}[/error]")
def success(msg: str) -> None:
"""Print a styled success line."""
CONSOLE.print(f"[success]✔ {msg}[/success]")
def metrics_table(
rows: list[tuple], headers: list[str], title: str | None = None
) -> None:
"""Print a metrics table. `rows` is a list of tuples, one per row."""
table = Table(title=title, header_style="bold", box=box.SIMPLE_HEAD)
for h in headers:
table.add_column(str(h))
for row in rows:
table.add_row(*[str(c) for c in row])
CONSOLE.print(table)
def config_table(
sections: dict[str, list[tuple[str, str]]], title: str = "Config"
) -> None:
"""Print a grouped key/value table.
`sections` maps a group name to a list of (key, value) pairs. Empty groups
are skipped; group names appear as styled separator rows.
"""
table = Table(title=title, box=box.SIMPLE, show_header=False, pad_edge=False)
table.add_column("key", style="muted", no_wrap=True)
table.add_column("value")
first = True
for group, pairs in sections.items():
if not pairs:
continue
if not first:
table.add_row("", "")
first = False
table.add_row(f"[info]{group}[/info]", "")
for key, value in pairs:
table.add_row(f" {key}", str(value))
CONSOLE.print(table)
|