dashboard/app/render.py

69 lines
1.7 KiB
Python

from datetime import timedelta
from pathlib import Path
from typing import Any
from jinja2 import Environment, FileSystemLoader, select_autoescape
BASE = Path(__file__).resolve().parent.parent
def humanize(value: float | str | None) -> str:
if value is None:
return ""
n = float(value)
for unit in ("B", "KiB", "MiB", "GiB", "TiB"):
if abs(n) < 1024 or unit == "TiB":
if unit == "B":
return f"{int(n)} B"
return f"{n:.1f} {unit}"
n /= 1024
return f"{n:.1f} TiB"
def rate(value: float | str | None) -> str:
if value is None:
return ""
n = float(value)
for unit in ("B/s", "KiB/s", "MiB/s", "GiB/s"):
if abs(n) < 1024 or unit == "GiB/s":
if unit == "B/s":
return f"{int(n)} B/s"
return f"{n:.1f} {unit}"
n /= 1024
return f"{n:.1f} GiB/s"
def uptime_str(seconds: float | None) -> str:
if seconds is None:
return ""
td = timedelta(seconds=int(seconds))
days, rem = divmod(td.seconds, 86400)
hours, rem = divmod(rem, 3600)
minutes = rem // 60
parts: list[str] = []
if days:
parts.append(f"{days}d")
if days or hours:
parts.append(f"{hours}h")
parts.append(f"{minutes}m")
return " ".join(parts)
def pct(value: float | None) -> str:
if value is None:
return ""
return f"{value:.0f}%"
env = Environment(
loader=FileSystemLoader(BASE / "templates"),
autoescape=select_autoescape(("html", "j2")),
)
env.filters["humanize"] = humanize
env.filters["rate"] = rate
env.filters["uptime"] = uptime_str
env.filters["pct"] = pct
def render(name: str, **kwargs: Any) -> str:
return env.get_template(name).render(**kwargs)