# -*- coding: utf-8 -*- import sys, time from array import array from calculate.lib.cl_lang import setLocalTranslate setLocalTranslate('calculate_console',sys.modules[__name__]) try: from fcntl import ioctl import termios except ImportError: pass import signal class ProgressBarWidgetHFill(object): def update(self, pbar, width): pass class ETA(object): "Widget for the Estimated Time of Arrival" def format_time(self, seconds): return time.strftime('%H:%M:%S', time.gmtime(seconds)) def update(self, pbar): if pbar.finished: return _('Time').decode('utf-8') + ': %s' \ %self.format_time(pbar.seconds_elapsed) else: return _('Time').decode('utf-8') + ': %s' \ %self.format_time(pbar.seconds_elapsed) class Percentage(object): "Just the percentage done." def update(self, pbar): return '%3d%%' % pbar.percentage() class Bar(ProgressBarWidgetHFill): "The bar of progress. It will strech to fill the line." def __init__(self, marker='=', left='[', right=']'): self.marker = marker self.left = left self.right = right def _format_marker(self, pbar): if isinstance(self.marker, (str, unicode)): return self.marker else: return self.marker.update(pbar) def update(self, pbar, width): percent = pbar.percentage() cwidth = width - len(self.left) - len(self.right) marked_width = int(percent * cwidth / 100) m = self._format_marker(pbar) bar = (self.left + (m*(marked_width-1)+'>').ljust(cwidth)+self.right) return bar default_widgets = [Percentage(), ' ', Bar()] class ProgressBar(object): def __init__(self, maxval=100, widgets=default_widgets, term_width=None, fd=sys.stderr): assert maxval > 0 self.maxval = maxval self.widgets = widgets self.fd = fd self.signal_set = False if term_width is None: try: self.handle_resize(None,None) signal.signal(signal.SIGWINCH, self.handle_resize) self.signal_set = True except: self.term_width = 99 else: self.term_width = term_width self.currval = 0 self.finished = False self.prev_percentage = -1 self.start_time = None self.seconds_elapsed = 0 def handle_resize(self, signum, frame): h, self.term_width = array('h', ioctl(self.fd,termios.TIOCGWINSZ, '\0'*8))[:2] def percentage(self): "Returns the percentage of the progress." return self.currval*100.0 / self.maxval def _format_widgets(self): r = [] hfill_inds = [] num_hfill = 0 currwidth = 0 for i, w in enumerate(self.widgets): if isinstance(w, ProgressBarWidgetHFill): r.append(w) hfill_inds.append(i) num_hfill += 1 elif isinstance(w, (str, unicode)): r.append(w) currwidth += len(w) else: weval = w.update(self) currwidth += len(weval) r.append(weval) for iw in hfill_inds: r[iw] = r[iw].update(self, (self.term_width-currwidth)/num_hfill) return r def _format_line(self): return ''.join(self._format_widgets()).ljust(self.term_width) def update(self, value): "Updates the progress bar to a new value." assert 0 <= value <= self.maxval self.currval = value if self.finished: return if not self.start_time: self.start_time = time.time() self.seconds_elapsed = time.time() - self.start_time self.prev_percentage = self.percentage() if value != self.maxval: self.fd.write(self._format_line() + '\r') else: self.finished = True self.fd.write(self._format_line() + '\n') def start(self): self.update(0) return self def finish(self): """Used to tell the progress is finished.""" self.update(self.maxval) if self.signal_set: signal.signal(signal.SIGWINCH, signal.SIG_DFL)