Coverage for muutils / logger / timing.py: 55%
40 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-18 02:51 -0700
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-18 02:51 -0700
1from __future__ import annotations
3import time
4from types import TracebackType
5from typing import Literal
8class TimerContext:
9 """context manager for timing code"""
11 def __init__(self) -> None:
12 self.start_time: float
13 self.end_time: float
14 self.elapsed_time: float
16 def __enter__(self) -> "TimerContext":
17 self.start_time = time.time()
18 return self
20 def __exit__(
21 self,
22 exc_type: type[BaseException] | None,
23 exc_val: BaseException | None,
24 exc_tb: TracebackType | None,
25 ) -> Literal[False]:
26 self.end_time = time.time()
27 self.elapsed_time = self.end_time - self.start_time
28 return False
31def filter_time_str(time: str) -> str:
32 """assuming format `h:mm:ss`, clips off the hours if its 0"""
33 if (len(time) == 7) and (time[0] == "0"):
34 return time[3:]
35 else:
36 return time
39class ProgressEstimator:
40 """estimates progress and can give a progress bar"""
42 def __init__(
43 self,
44 n_total: int,
45 pbar_fill: str = "█",
46 pbar_empty: str = " ",
47 pbar_bounds: tuple[str, str] = ("|", "|"),
48 ):
49 self.n_total: int = n_total
50 self.starttime: float = time.time()
51 self.pbar_fill: str = pbar_fill
52 self.pbar_empty: str = pbar_empty
53 self.pbar_bounds: tuple[str, str] = pbar_bounds
54 self.total_str_len: int = len(str(n_total))
56 def get_timing_raw(self, i: int) -> dict[str, float]:
57 """returns dict(elapsed, per_iter, remaining, percent)"""
58 elapsed: float = time.time() - self.starttime
59 per_iter: float = elapsed / i
60 return dict(
61 elapsed=elapsed,
62 per_iter=per_iter,
63 remaining=(self.n_total - i) * per_iter,
64 percent=i / self.n_total,
65 )
67 def get_pbar(
68 self,
69 i: int,
70 width: int = 30,
71 ) -> str:
72 """returns a progress bar"""
73 percent_filled: float = i / self.n_total
74 # round to nearest integer
75 n_filled: int = int(round(percent_filled * width))
76 return "".join(
77 [
78 self.pbar_bounds[0],
79 self.pbar_fill * n_filled,
80 self.pbar_empty * (width - n_filled),
81 self.pbar_bounds[1],
82 ]
83 )
85 def get_progress_default(self, i: int) -> str:
86 """returns a progress string"""
87 timing_raw: dict[str, float] = self.get_timing_raw(i)
89 percent_str: str = str(int(timing_raw["percent"] * 100)).ljust(2)
90 # TODO: get_progress_default
91 # iters_str: str = f"{str(i).ljust(self.total_str_len)}/{self.n_total}"
92 # timing_str: str
93 return f"{percent_str}% {self.get_pbar(i)}"