diff --git a/.gitignore b/.gitignore index 875204c..d7a8809 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,11 @@ .idea +.project +.settings +.pydevproject MANIFEST *.pyc .tox build/ +clint.egg-info/ +dist/ + diff --git a/AUTHORS b/AUTHORS index 9776068..4fe6b97 100644 --- a/AUTHORS +++ b/AUTHORS @@ -29,3 +29,4 @@ Patches and Suggestions - Justin Barber - Dmitry Medvinsky - Eric Anderson +- Joshua Richardson diff --git a/clint/textui/progress.py b/clint/textui/progress.py index 3ac2298..998bb92 100644 --- a/clint/textui/progress.py +++ b/clint/textui/progress.py @@ -33,43 +33,78 @@ ETA_INTERVAL = 1 #How many intervals (excluding the current one) to calculate the simple moving average ETA_SMA_WINDOW = 9 -def bar(it, label='', width=32, hide=HIDE_DEFAULT, empty_char=BAR_EMPTY_CHAR, filled_char=BAR_FILLED_CHAR, expected_size=None, every=1): - """Progress iterator. Wrap your iterables with it.""" - - def _show(_i): - if (time.time() - bar.etadelta) > ETA_INTERVAL: - bar.etadelta = time.time() - bar.ittimes = bar.ittimes[-ETA_SMA_WINDOW:]+[-(bar.start-time.time())/(_i+1)] - bar.eta = sum(bar.ittimes)/float(len(bar.ittimes)) * (count-_i) - bar.etadisp = time.strftime('%H:%M:%S', time.gmtime(bar.eta)) - x = int(width*_i/count) - if not hide: - if ((_i % every)==0 or # True every "every" updates - (_i == count)): # And when we're done +class Bar(object): + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.done() + return False # we're not surpressing exceptions + + def __init__(self, label='', width=32, hide=None, empty_char=BAR_EMPTY_CHAR, + filled_char=BAR_FILLED_CHAR, expected_size=None, every=1): + self.label = label + self.width = width + self.hide = hide + if hide is None: + try: + self.hide = not STREAM.isatty() + except AttributeError: # output does not support isatty() + self.hide = True + self.empty_char = empty_char + self.filled_char = filled_char + self.expected_size = expected_size + self.every = every + self.start = time.time() + self.ittimes = [] + self.eta = 0 + self.etadelta = time.time() + self.etadisp = time.strftime('%H:%M:%S', time.gmtime(self.eta)) + if (self.expected_size): + self.show(0) + + def show(self, progress, count=None): + if count is not None: + self.expected_size = count + if self.expected_size is None: + raise Exception("expected_size not initialized") + if (time.time() - self.etadelta) > ETA_INTERVAL: + self.etadelta = time.time() + self.ittimes = \ + self.ittimes[-ETA_SMA_WINDOW:]+\ + [-(self.start-time.time())/(progress+1)] + self.eta = \ + sum(self.ittimes)/float(len(self.ittimes)) * \ + (self.expected_size-progress) + self.etadisp = time.strftime('%H:%M:%S', time.gmtime(self.eta)) + x = int(self.width*progress/self.expected_size) + if not self.hide: + if ((progress % self.every)==0 or # True every "every" updates + (progress == self.expected_size)): # And when we're done STREAM.write(BAR_TEMPLATE % ( - label, filled_char*x, empty_char*(width-x), _i, count, bar.etadisp)) + self.label, self.filled_char*x, + self.empty_char*(self.width-x), progress, + self.expected_size, self.etadisp)) STREAM.flush() - count = len(it) if expected_size is None else expected_size - - bar.start = time.time() - bar.ittimes = [] - bar.eta = 0 - bar.etadelta = time.time() - bar.etadisp = time.strftime('%H:%M:%S', time.gmtime(bar.eta)) - - if count: - _show(0) - - for i, item in enumerate(it): - - yield item - _show(i+1) - - if not hide: + def done(self): + if not self.hide: STREAM.write('\n') STREAM.flush() +def bar(it, label='', width=32, hide=HIDE_DEFAULT, empty_char=BAR_EMPTY_CHAR, filled_char=BAR_FILLED_CHAR, expected_size=None, every=1): + """Progress iterator. Wrap your iterables with it.""" + + count = len(it) if expected_size is None else expected_size + + with Bar(label=label, width=width, hide=hide, empty_char=BAR_EMPTY_CHAR, + filled_char=BAR_FILLED_CHAR, expected_size=count, every=every) \ + as bar: + + for i, item in enumerate(it): + + yield item + bar.show(i+1) def dots(it, label='', hide=HIDE_DEFAULT, every=1): """Progress iterator. Prints a dot for each item being iterated""" diff --git a/examples/progressbar.py b/examples/progressbar.py index 26030e4..a41b6ef 100755 --- a/examples/progressbar.py +++ b/examples/progressbar.py @@ -14,6 +14,13 @@ from clint.textui import progress if __name__ == '__main__': for i in progress.bar(range(100)): sleep(random() * 0.2) + + with progress.Bar(label="nonlinear", expected_size=10) as bar: + last_val = 0 + for val in (1,2,3,9,10): + sleep(2 * (val - last_val)) + bar.show(val) + last_val = val for i in progress.dots(range(100)): sleep(random() * 0.2)