1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/tests/lib/progressbar.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,109 @@ 1.4 +# Text progress bar library, like curl or scp. 1.5 + 1.6 +from datetime import datetime, timedelta 1.7 +import math 1.8 +import sys 1.9 + 1.10 +if sys.platform.startswith('win'): 1.11 + from terminal_win import Terminal 1.12 +else: 1.13 + from terminal_unix import Terminal 1.14 + 1.15 +class NullProgressBar(object): 1.16 + def update(self, current, data): pass 1.17 + def poke(self): pass 1.18 + def finish(self, complete=True): pass 1.19 + def beginline(self): pass 1.20 + def message(self, msg): sys.stdout.write(msg + '\n') 1.21 + def update_granularity(self): return timedelta.max 1.22 + 1.23 +class ProgressBar(object): 1.24 + def __init__(self, limit, fmt): 1.25 + assert self.conservative_isatty() 1.26 + 1.27 + self.prior = None 1.28 + self.atLineStart = True 1.29 + self.counters_fmt = fmt # [{str:str}] Describtion of how to lay out each 1.30 + # field in the counters map. 1.31 + self.limit = limit # int: The value of 'current' equal to 100%. 1.32 + self.limit_digits = int(math.ceil(math.log10(self.limit))) # int: max digits in limit 1.33 + self.t0 = datetime.now() # datetime: The start time. 1.34 + 1.35 + # Compute the width of the counters and build the format string. 1.36 + self.counters_width = 1 # [ 1.37 + for layout in self.counters_fmt: 1.38 + self.counters_width += self.limit_digits 1.39 + self.counters_width += 1 # | (or ']' for the last one) 1.40 + 1.41 + self.barlen = 64 - self.counters_width 1.42 + 1.43 + def update_granularity(self): 1.44 + return timedelta(seconds=0.1) 1.45 + 1.46 + def update(self, current, data): 1.47 + # Record prior for poke. 1.48 + self.prior = (current, data) 1.49 + self.atLineStart = False 1.50 + 1.51 + # Build counters string. 1.52 + sys.stdout.write('\r[') 1.53 + for layout in self.counters_fmt: 1.54 + Terminal.set_color(layout['color']) 1.55 + sys.stdout.write(('%' + str(self.limit_digits) + 'd') % data[layout['value']]) 1.56 + Terminal.reset_color() 1.57 + if layout != self.counters_fmt[-1]: 1.58 + sys.stdout.write('|') 1.59 + else: 1.60 + sys.stdout.write('] ') 1.61 + 1.62 + # Build the bar. 1.63 + pct = int(100.0 * current / self.limit) 1.64 + sys.stdout.write('%3d%% ' % pct) 1.65 + 1.66 + barlen = int(1.0 * self.barlen * current / self.limit) - 1 1.67 + bar = '=' * barlen + '>' + ' ' * (self.barlen - barlen - 1) 1.68 + sys.stdout.write(bar + '|') 1.69 + 1.70 + # Update the bar. 1.71 + dt = datetime.now() - self.t0 1.72 + dt = dt.seconds + dt.microseconds * 1e-6 1.73 + sys.stdout.write('%6.1fs' % dt) 1.74 + Terminal.clear_right() 1.75 + 1.76 + # Force redisplay, since we didn't write a \n. 1.77 + sys.stdout.flush() 1.78 + 1.79 + def poke(self): 1.80 + if not self.prior: 1.81 + return 1.82 + self.update(*self.prior) 1.83 + 1.84 + def finish(self, complete=True): 1.85 + final_count = self.limit if complete else self.prior[0] 1.86 + self.update(final_count, self.prior[1]) 1.87 + sys.stdout.write('\n') 1.88 + 1.89 + def beginline(self): 1.90 + if not self.atLineStart: 1.91 + sys.stdout.write('\n') 1.92 + self.atLineStart = True 1.93 + 1.94 + def message(self, msg): 1.95 + self.beginline() 1.96 + sys.stdout.write(msg) 1.97 + sys.stdout.write('\n') 1.98 + 1.99 + @staticmethod 1.100 + def conservative_isatty(): 1.101 + """ 1.102 + Prefer erring on the side of caution and not using terminal commands if 1.103 + the current output stream may be a file. We explicitly check for the 1.104 + Android platform because terminal commands work poorly over ADB's 1.105 + redirection. 1.106 + """ 1.107 + try: 1.108 + import android 1.109 + return False 1.110 + except ImportError: 1.111 + return sys.stdout.isatty() 1.112 + return False