#! /bin/env python3 # encoding: utf-8 import time import sys #from . import ag #from . import gl #from . import et #from . import scn #from . import ui #from . import cmd #from . import com #from . import loop from . import core class ProgressBar: def __init__(self, width, total=1.0, unit="", prefix=None, suffix=None, show_percent=True, show_absolute=True, show_rate=True, show_etc=True, draw_on_update=True): self.width = width self.total = total self.unit = unit self.prefix = prefix self.suffix = suffix self.show_percent = show_percent self.show_absolute = show_absolute self.show_rate = show_rate self.show_etc = show_etc self.draw_on_update = draw_on_update self.percentage_printf = "%5.1f %%" self.absolute_printf_total = "%d/%d %s," self.absolute_printf = "%d %s," self.rate_printf_total = "%d %s/s," self.rate_printf = "%d %s/s" self.etc_printf = "ETA %d s" self._current = 0.0 self._ratio = 0.0 self._rate = 0.0 self._runner = 0.0 self._start = None self._longest_line = 0 @property def current(self): return self._current @current.setter def current(self, value): self._current = value self.update() if self.draw_on_update: self.draw() def update(self): if self._start is None: self._start = time.time() dt = (time.time() - self._start) if dt > 0: self._rate = self._current / dt else: self._rate = 0 if self.total is None: self._ratio = None self._etc = None self._runner = (self._runner + 0.01) % 1.0 else: self._ratio = self._current / self.total self._etc = dt * (1 / self._ratio - 1) def draw(self, overdraw=0): output = [] if self.prefix: output.append(self.prefix) if self.show_percent and self.total is not None: output.append(self.percentage_printf %(self._ratio * 100)) if self.total is None: count_full = int(self._runner * (self.width - 5)) count_empty = self.width - count_full - 5 output.append("[%s<=>%s]" %(" " * count_full, " " * count_empty)) else: count_full = int(self._ratio * (self.width - 3)) count_empty = self.width - count_full - 3 output.append("[%s>%s]" %("=" * count_full, " " * count_empty)) if self.show_absolute: if self.total is None: output.append(self.absolute_printf %(self._current, self.unit)) # TODO et.Unit else: output.append(self.absolute_printf_total %(self._current, self.total, self.unit)) if self.show_rate: if self.total is None: output.append(self.rate_printf %(self._rate, self.unit)) else: output.append(self.rate_printf_total %(self._rate, self.unit)) if self.show_etc and self.total is not None: output.append(self.etc_printf %(self._etc)) if self.suffix: output.append(self.suffix) line = " ".join(output) line_len = len(line) if line_len > self._longest_line: self._longest_line = line_len sys.stdout.write("\r%s\r" %(" " * (self._longest_line + overdraw))) sys.stdout.write(line) sys.stdout.flush() def finish(self): if self.total is not None: self.current = self.total if not self.draw_on_update: self.draw(overdraw=2) sys.stdout.write("\n") sys.stdout.flush() def __enter__(self): return self def __exit__(self, type, value, traceback): pass