Allow custom properties in format strings

This commit is contained in:
Giorgos Verigakis
2013-11-28 13:05:05 +08:00
parent e5cffc8c72
commit 8b02a5b59f
3 changed files with 41 additions and 31 deletions

View File

@@ -14,6 +14,7 @@
from __future__ import division from __future__ import division
from datetime import timedelta
from math import ceil from math import ceil
from sys import stderr from sys import stderr
from time import time from time import time
@@ -26,16 +27,25 @@ class Infinite(object):
file = stderr file = stderr
def __init__(self, *args, **kwargs): 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.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): def update_stats(self):
# Calculate moving average # 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.avg = (dt + self.index * self.avg) / (self.index + 1) if self.avg else dt
self._ts = now self._ts = now
kv = [(key, val) for key, val in self.__dict__.items()
if not key.startswith('_')]
self.ctx.update(kv)
def update(self): def update(self):
pass pass
@@ -75,8 +81,15 @@ class Progress(Infinite):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(Progress, self).__init__(*args, **kwargs) super(Progress, self).__init__(*args, **kwargs)
self.max = kwargs.get('max', 100) self.max = kwargs.get('max', 100)
self.eta = 0 self.remaining = self.max
self.elapsed = 0
@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): def update_stats(self):
self.progress = min(1, self.index / self.max) self.progress = min(1, self.index / self.max)
@@ -88,14 +101,8 @@ class Progress(Infinite):
if self.delta: if self.delta:
dt = (now - self._ts) / self.delta dt = (now - self._ts) / self.delta
self.avg = (dt + self.index * self.avg) / (self.index + 1) if self.avg else dt 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 self._ts = now
kv = [(key, val) for key, val in self.__dict__.items()
if not key.startswith('_')]
self.ctx.update(kv)
def start(self): def start(self):
self.delta = 0 self.delta = 0
self.update_stats() self.update_stats()

View File

@@ -32,10 +32,10 @@ class Bar(WritelnMixin, Progress):
filled_length = int(self.width * self.progress) filled_length = int(self.width * self.progress)
empty_length = self.width - filled_length empty_length = self.width - filled_length
message = self.message % self.ctx message = self.message % self
bar = self.fill * filled_length bar = self.fill * filled_length
empty = self.empty_fill * empty_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, line = ''.join([message, self.bar_prefix, bar, empty, self.bar_suffix,
suffix]) suffix])
self.writeln(line) self.writeln(line)
@@ -69,11 +69,11 @@ class IncrementalBar(Bar):
empty_length = self.width - filled_length empty_length = self.width - filled_length
phase = expanded_length - (filled_length * nphases) phase = expanded_length - (filled_length * nphases)
message = self.message % self.ctx message = self.message % self
bar = self.phases[-1] * filled_length bar = self.phases[-1] * filled_length
current = self.phases[phase] if phase > 0 else '' current = self.phases[phase] if phase > 0 else ''
empty = self.empty_fill * max(0, empty_length - len(current)) 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, line = ''.join([message, self.bar_prefix, bar, current, empty,
self.bar_suffix, suffix]) self.bar_suffix, suffix])
self.writeln(line) self.writeln(line)

View File

@@ -10,13 +10,16 @@ from progress.bar import (Bar, ChargingBar, FillingSquaresBar,
from progress.spinner import Spinner, PieSpinner, MoonSpinner, LineSpinner from progress.spinner import Spinner, PieSpinner, MoonSpinner, LineSpinner
from progress.counter import Counter, Countdown, Stack, Pie from progress.counter import Counter, Countdown, Stack, Pie
for bar_cls in (Bar, ChargingBar, FillingSquaresBar, FillingCirclesBar):
for bar in (Bar, ChargingBar, FillingSquaresBar, FillingCirclesBar): suffix = '%(index)d/%(max)d [%(elapsed)d / %(eta)d]'
for i in bar(bar.__name__).iter(range(100)): bar = bar_cls(bar_cls.__name__, suffix=suffix)
for i in bar.iter(range(100)):
sleep(0.04) sleep(0.04)
for bar in (IncrementalBar, ShadyBar): for bar_cls in (IncrementalBar, ShadyBar):
for i in bar(bar.__name__).iter(range(200)): 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) sleep(0.02)
for spin in (Spinner, PieSpinner, MoonSpinner, LineSpinner): 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 singleton in (Counter, Countdown, Stack, Pie):
for i in singleton(singleton.__name__ + ' ').iter(range(100)): for i in singleton(singleton.__name__ + ' ').iter(range(100)):
sleep(0.04) sleep(0.03)
print() print()
bar = IncrementalBar('Random', backtrack=True, suffix='') bar = IncrementalBar('Random', backtrack=True, suffix='')