Skip to content

Commit 6177bec

Browse files
committed
Add dash.py
1 parent 3756e75 commit 6177bec

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed

src/paperoni/dash.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
from contextlib import asynccontextmanager
2+
from dataclasses import dataclass, field
3+
from typing import Literal
4+
5+
from outsight import Fixture
6+
from rich.console import Console, Group, RenderableType as Renderable
7+
from rich.live import Live
8+
from rich.progress import BarColumn, Progress, TextColumn
9+
from rich.rule import Rule
10+
from rich.table import Table
11+
12+
13+
@dataclass
14+
class History[T]:
15+
values: list[T] = field(default_factory=list)
16+
display: Literal["short", "long"] = "long"
17+
18+
def __rich__(self):
19+
lines = [
20+
f"[bold white]{v}[/bold white]" if i == 0 else f"[dim]{v}[/dim]"
21+
for i, v in enumerate(reversed(self.values))
22+
]
23+
joiner = " " if self.display == "short" else "\n"
24+
return joiner.join(lines)
25+
26+
27+
@dataclass(eq=False)
28+
class Dash(Fixture):
29+
data: dict[str, object] = field(default_factory=dict)
30+
live: Live = None
31+
fade_time: float = 10
32+
33+
@property
34+
def scope(self):
35+
return "global"
36+
37+
def __post_init__(self):
38+
self.progress = Progress(
39+
TextColumn(" [bold blue]{task.fields[name]}", justify="right"),
40+
BarColumn(bar_width=None),
41+
"[progress.percentage]{task.percentage:>3.0f}%",
42+
"•",
43+
TextColumn("{task.completed}/{task.total}"),
44+
expand=True,
45+
transient=True,
46+
)
47+
self.progress_bars = {}
48+
49+
def make_table(self):
50+
table = Table(show_header=False, box=None)
51+
table.add_column("Key", style="cyan", no_wrap=True, width=20)
52+
table.add_column("Value", no_wrap=True)
53+
for key, value in self.data.items():
54+
table.add_row(
55+
str(key), value if isinstance(value, Renderable) else str(value)
56+
)
57+
return table
58+
59+
def make_display(self):
60+
components = []
61+
if self.data:
62+
components.append(Rule())
63+
components.append(self.make_table())
64+
components.append(self.progress)
65+
if self.data:
66+
components.append(Rule())
67+
return Group(*components)
68+
69+
def __setitem__(self, key, value):
70+
self.data[key] = value
71+
if self.live:
72+
self.live.update(self.make_display())
73+
74+
def add_progress(self, name, current, total):
75+
if name not in self.progress_bars:
76+
task_id = self.progress.add_task("", name=name, total=total)
77+
self.progress_bars[name] = task_id
78+
else:
79+
task_id = self.progress_bars[name]
80+
self.progress.update(task_id, completed=current, total=total)
81+
82+
@asynccontextmanager
83+
async def context(self):
84+
if self.live:
85+
yield self
86+
else:
87+
console = Console()
88+
with Live(self.make_display(), console=console, refresh_per_second=4) as live:
89+
self.live = live
90+
yield self

0 commit comments

Comments
 (0)