From e62f5657a57b875c0ab6b2b4ef23758118f7fe9c Mon Sep 17 00:00:00 2001 From: Joshua Richardson Date: Tue, 11 Feb 2014 20:25:15 -0800 Subject: [PATCH 1/4] Added ability to "update" the progress bar without iterating over every value. --- AUTHORS | 1 + clint/textui/progress.py | 133 ++++++++++++++++++++++++++++++--------- examples/progressbar.py | 8 +++ 3 files changed, 112 insertions(+), 30 deletions(-) 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..ebca43e 100644 --- a/clint/textui/progress.py +++ b/clint/textui/progress.py @@ -33,42 +33,115 @@ ETA_INTERVAL = 1 #How many intervals (excluding the current one) to calculate the simple moving average ETA_SMA_WINDOW = 9 +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 % ( + self.label, self.filled_char*x, + self.empty_char*(self.width-x), progress, + self.expected_size, self.etadisp)) + STREAM.flush() + + 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.""" - 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 - STREAM.write(BAR_TEMPLATE % ( - label, filled_char*x, empty_char*(width-x), _i, count, bar.etadisp)) - STREAM.flush() - 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: - bar.start = time.time() - bar.ittimes = [] - bar.eta = 0 - bar.etadelta = time.time() - bar.etadisp = time.strftime('%H:%M:%S', time.gmtime(bar.eta)) + for i, item in enumerate(it): + + yield item + bar.show(i+1) - if count: - _show(0) - - for i, item in enumerate(it): - - yield item - _show(i+1) - - if not 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.""" +# +# 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 +# STREAM.write(BAR_TEMPLATE % ( +# label, filled_char*x, empty_char*(width-x), _i, count, bar.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: +# STREAM.write('\n') +# STREAM.flush() def dots(it, label='', hide=HIDE_DEFAULT, every=1): diff --git a/examples/progressbar.py b/examples/progressbar.py index 26030e4..b200eab 100755 --- a/examples/progressbar.py +++ b/examples/progressbar.py @@ -14,6 +14,14 @@ 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: + bar.show(0) + 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) From 4b98c465193dc95ea8ec0d3a1fac81a5836be3a3 Mon Sep 17 00:00:00 2001 From: Joshua Richardson Date: Tue, 11 Feb 2014 20:28:06 -0800 Subject: [PATCH 2/4] Remove commented-out implementation. --- clint/textui/progress.py | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/clint/textui/progress.py b/clint/textui/progress.py index ebca43e..998bb92 100644 --- a/clint/textui/progress.py +++ b/clint/textui/progress.py @@ -106,44 +106,6 @@ def bar(it, label='', width=32, hide=HIDE_DEFAULT, empty_char=BAR_EMPTY_CHAR, fi yield item bar.show(i+1) -# 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 -# STREAM.write(BAR_TEMPLATE % ( -# label, filled_char*x, empty_char*(width-x), _i, count, bar.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: -# STREAM.write('\n') -# STREAM.flush() - - def dots(it, label='', hide=HIDE_DEFAULT, every=1): """Progress iterator. Prints a dot for each item being iterated""" From 00b522510c397e80c775cae3bf872f8f7520fcaa Mon Sep 17 00:00:00 2001 From: Joshua Richardson Date: Tue, 11 Feb 2014 20:49:17 -0800 Subject: [PATCH 3/4] Don't need to call show(0), since that's done automatically in the __init__() function. --- examples/progressbar.py | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/progressbar.py b/examples/progressbar.py index b200eab..a41b6ef 100755 --- a/examples/progressbar.py +++ b/examples/progressbar.py @@ -16,7 +16,6 @@ if __name__ == '__main__': sleep(random() * 0.2) with progress.Bar(label="nonlinear", expected_size=10) as bar: - bar.show(0) last_val = 0 for val in (1,2,3,9,10): sleep(2 * (val - last_val)) From c5dbe0708ebecdd3d4f07c68413092d27a851068 Mon Sep 17 00:00:00 2001 From: Joshua Richardson Date: Fri, 21 Feb 2014 11:26:11 -0800 Subject: [PATCH 4/4] Extended .gitignore. --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) 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/ +