-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconsole_progress.py
More file actions
59 lines (51 loc) · 1.85 KB
/
Copy pathconsole_progress.py
File metadata and controls
59 lines (51 loc) · 1.85 KB
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
"""Small dependency-free progress reporting for long command-line analyses."""
from __future__ import annotations
import sys
import time
class ProgressBar:
"""Print a compact progress bar at five-percentage-point intervals."""
def __init__(self, label: str, total: int, enabled: bool = True) -> None:
self.label = label
self.total = total
self.enabled = enabled and total > 0
self.completed = 0
self.started = time.perf_counter()
self.last_percent = -1
if self.enabled:
self._display(force=True)
def advance(self) -> None:
if not self.enabled:
return
self.completed = min(self.completed + 1, self.total)
self._display(force=self.completed == self.total)
def finish(self) -> None:
if not self.enabled:
return
if self.completed < self.total:
self.completed = self.total
self._display(force=True)
sys.stderr.flush()
self.enabled = False
def _display(self, force: bool = False) -> None:
percent = int(100 * self.completed / self.total)
if (
not force
and self.last_percent >= 0
and percent // 5 == self.last_percent // 5
):
return
self.last_percent = percent
width = 30
filled = int(width * self.completed / self.total)
bar = "#" * filled + "-" * (width - filled)
elapsed = time.perf_counter() - self.started
if self.completed:
eta = elapsed * (self.total - self.completed) / self.completed
eta_text = f"; ETA {eta:.0f}s"
else:
eta_text = ""
sys.stderr.write(
f"{self.label}: [{bar}] {percent:3d}% "
f"({self.completed}/{self.total}; {elapsed:.0f}s{eta_text})\n"
)
sys.stderr.flush()