diff --git a/progress/__init__.py b/progress/__init__.py index 515b31f..b4d16dc 100644 --- a/progress/__init__.py +++ b/progress/__init__.py @@ -14,6 +14,7 @@ from __future__ import division +from datetime import timedelta from math import ceil from sys import stderr from time import time @@ -26,16 +27,25 @@ class Infinite(object): file = stderr def __init__(self, *args, **kwargs): - self.ctx = {} - for key, val in kwargs.items(): - if hasattr(self, key): - setattr(self, key, val) - else: - self.ctx[key] = val - - self.index = 0 self.avg = 0 - self._ts = time() + self.index = 0 + self.start_ts = time() + self._ts = self.start_ts + for key, val in kwargs.items(): + setattr(self, key, val) + + def __getitem__(self, key): + if key.startswith('_'): + return None + return getattr(self, key, None) + + @property + def elapsed(self): + return int(time() - self.start_ts) + + @property + def elapsed_td(self): + return timedelta(seconds=self.elapsed) def update_stats(self): # Calculate moving average @@ -44,10 +54,6 @@ class Infinite(object): self.avg = (dt + self.index * self.avg) / (self.index + 1) if self.avg else dt self._ts = now - kv = [(key, val) for key, val in self.__dict__.items() - if not key.startswith('_')] - self.ctx.update(kv) - def update(self): pass @@ -75,8 +81,15 @@ class Progress(Infinite): def __init__(self, *args, **kwargs): super(Progress, self).__init__(*args, **kwargs) self.max = kwargs.get('max', 100) - self.eta = 0 - self.elapsed = 0 + self.remaining = self.max + + @property + def eta(self): + return int(ceil(self.avg * self.remaining)) + + @property + def eta_td(self): + return timedelta(seconds=self.eta) def update_stats(self): self.progress = min(1, self.index / self.max) @@ -88,14 +101,8 @@ class Progress(Infinite): if self.delta: dt = (now - self._ts) / self.delta self.avg = (dt + self.index * self.avg) / (self.index + 1) if self.avg else dt - self.eta = int(ceil(self.avg * self.remaining)) - self.elapsed += now - self._ts self._ts = now - kv = [(key, val) for key, val in self.__dict__.items() - if not key.startswith('_')] - self.ctx.update(kv) - def start(self): self.delta = 0 self.update_stats() diff --git a/progress/bar.py b/progress/bar.py index 311b47a..8ce1461 100644 --- a/progress/bar.py +++ b/progress/bar.py @@ -32,10 +32,10 @@ class Bar(WritelnMixin, Progress): filled_length = int(self.width * self.progress) empty_length = self.width - filled_length - message = self.message % self.ctx + message = self.message % self bar = self.fill * filled_length empty = self.empty_fill * empty_length - suffix = self.suffix % self.ctx + suffix = self.suffix % self line = ''.join([message, self.bar_prefix, bar, empty, self.bar_suffix, suffix]) self.writeln(line) @@ -69,11 +69,11 @@ class IncrementalBar(Bar): empty_length = self.width - filled_length phase = expanded_length - (filled_length * nphases) - message = self.message % self.ctx + message = self.message % self bar = self.phases[-1] * filled_length current = self.phases[phase] if phase > 0 else '' empty = self.empty_fill * max(0, empty_length - len(current)) - suffix = self.suffix % self.ctx + suffix = self.suffix % self line = ''.join([message, self.bar_prefix, bar, current, empty, self.bar_suffix, suffix]) self.writeln(line) diff --git a/test_progress.py b/test_progress.py index e87b670..f70c6a3 100755 --- a/test_progress.py +++ b/test_progress.py @@ -10,13 +10,16 @@ from progress.bar import (Bar, ChargingBar, FillingSquaresBar, from progress.spinner import Spinner, PieSpinner, MoonSpinner, LineSpinner from progress.counter import Counter, Countdown, Stack, Pie - -for bar in (Bar, ChargingBar, FillingSquaresBar, FillingCirclesBar): - for i in bar(bar.__name__).iter(range(100)): +for bar_cls in (Bar, ChargingBar, FillingSquaresBar, FillingCirclesBar): + suffix = '%(index)d/%(max)d [%(elapsed)d / %(eta)d]' + bar = bar_cls(bar_cls.__name__, suffix=suffix) + for i in bar.iter(range(100)): sleep(0.04) -for bar in (IncrementalBar, ShadyBar): - for i in bar(bar.__name__).iter(range(200)): +for bar_cls in (IncrementalBar, ShadyBar): + suffix = '%(percent)d%% [%(elapsed_td)s / %(eta_td)s]' + bar = bar_cls(bar_cls.__name__, suffix=suffix) + for i in bar.iter(range(200)): sleep(0.02) for spin in (Spinner, PieSpinner, MoonSpinner, LineSpinner): @@ -26,7 +29,7 @@ for spin in (Spinner, PieSpinner, MoonSpinner, LineSpinner): for singleton in (Counter, Countdown, Stack, Pie): for i in singleton(singleton.__name__ + ' ').iter(range(100)): - sleep(0.04) + sleep(0.03) print() bar = IncrementalBar('Random', backtrack=True, suffix='')