10 from abc
import ABCMeta, abstractmethod
12 AbstractWidget = object
13 abstractmethod =
lambda fn: fn
15 AbstractWidget = ABCMeta(
'AbstractWidget', (object,), {})
18 '''The base class for all widgets 20 The ProgressBar will call the widget's update value when the widget should 21 be updated. The widget's size may change between calls, but the widget may 22 display incorrectly if the size changes drastically and repeatedly. 24 The boolean TIME_SENSITIVE informs the ProgressBar that it should be 25 updated more often because it is time sensitive. 28 TIME_SENSITIVE =
False 33 '''Updates the widget. 35 pbar - a reference to the calling ProgressBar 38 'Widget which displays the elapsed seconds.' 40 __slots__ = (
'format',)
48 'Formats time as the string "HH:MM:SS".' 50 return str(datetime.timedelta(seconds=
int(seconds)))
54 'Updates the widget to show the elapsed time.' 58 '''The base class for all variable width widgets. 60 This widget is much like the \\hfill command in TeX, it will expand to 61 fill the line. You can use more than one in the same line, and they will 62 all have the same width, and together will fill the line. 67 '''Updates the widget providing the total width the widget must fill. 69 pbar - a reference to the calling ProgressBar 70 width - The total width the widget must fill 72 class Bar(WidgetHFill):
73 'A progress bar which stretches to fill the line.' 75 __slots__ = (
'marker',
'left',
'right',
'fill',
'fill_left')
77 def __init__(self, marker='#', left='|', right='|', fill=' ',
79 '''Creates a customizable progress bar. 81 marker - string or updatable object to use as a marker 82 left - string or updatable object to use as a left border 83 right - string or updatable object to use as a right border 84 fill - character to use for the empty part of the progress bar 85 fill_left - whether to fill from the left or the right 95 'Updates the progress bar and its subcomponents' 100 width -= len(left) + len(right)
103 marked *=
int(pbar.currval / pbar.maxval * width)
108 return '%s%s%s' % (left, marked.ljust(width, self.
fill), right)
110 return '%s%s%s' % (left, marked.rjust(width, self.
fill), right)
113 'Updates the progress bar and its subcomponents' 118 width -= len(left) + len(right)
120 if pbar.finished:
return '%s%s%s' % (left, width * marker, right)
122 position =
int(pbar.currval % (width * 2 - 1))
123 if position > width: position = width * 2 - position
124 lpad = self.
fill * (position - 1)
125 rpad = self.
fill * (width - len(marker) - len(lpad))
128 if not self.
fill_left: rpad, lpad = lpad, rpad
130 return '%s%s%s%s%s' % (left, lpad, marker, rpad, right)
133 'Displays a formatted label' 136 'elapsed': (
'seconds_elapsed', Timer.format_time),
137 'finished': (
'finished',
None),
138 'last_update': (
'last_update_time',
None),
139 'max': (
'maxval',
None),
140 'seconds': (
'seconds_elapsed',
None),
141 'start': (
'start_time',
None),
142 'value': (
'currval',
None)
145 __slots__ = (
'format',)
151 for name, (key, transform)
in self.mapping.items():
153 value = getattr(pbar, key)
155 if transform
is None:
156 context[name] = value
161 return self.
format % context
164 '''The ProgressBar class which updates and prints the bar. 166 A common way of using it is like: 167 >>> pbar = ProgressBar().start() 168 >>> for i in range(100): 174 You can also use a ProgressBar as an iterator: 175 >>> progress = ProgressBar() 176 >>> for i in progress(some_iterable): 180 Since the progress bar is incredibly customizable you can specify 181 different widgets of any type in any order. You can even write your own 182 widgets! However, since there are already a good number of widgets you 183 should probably play around with them before moving on to create your own 186 The term_width parameter represents the current terminal width. If the 187 parameter is set to an integer then the progress bar will use that, 188 otherwise it will attempt to determine the terminal width falling back to 189 80 columns if the width cannot be determined. 191 When implementing a widget's update method you are passed a reference to 192 the current progress bar. As a result, you have access to the 193 ProgressBar's methods and attributes. Although there is nothing preventing 194 you from changing the ProgressBar you should treat it as read only. 196 Useful methods and attributes include (Public API): 197 - currval: current progress (0 <= currval <= maxval) 198 - maxval: maximum (and final) value 199 - finished: True if the bar has finished (reached 100%) 200 - start_time: the time when start() method of ProgressBar was called 201 - seconds_elapsed: seconds elapsed since start_time and last call to 203 - percentage(): progress in percent [0..100] 206 __slots__ = (
'currval',
'fd',
'finished',
'last_update_time',
207 'left_justify',
'maxval',
'next_update',
'num_intervals',
208 'poll',
'seconds_elapsed',
'signal_set',
'start_time',
209 'term_width',
'update_interval',
'widgets',
'_time_sensitive',
212 _DEFAULT_MAXVAL = 100
213 _DEFAULT_TERMSIZE = 80
215 def __init__(self, maxval=None, widgets=None, term_width=None, poll=1,
216 left_justify=
True, fd=sys.stderr):
217 '''Initializes a progress bar with sane defaults''' 225 if term_width
is not None:
232 except (SystemExit, KeyboardInterrupt):
raise 248 'Use a ProgressBar to iterate through an iterable' 251 self.
maxval = len(iterable)
254 self.
maxval = UnknownLength
270 except StopIteration:
281 'Tries to find the term_width from the environment.' 287 'Tries to catch resize signals sent from the terminal.' 289 h, w =
array(
'h', ioctl(self.
fd, termios.TIOCGWINSZ,
'\0' * 8))[:2]
294 'Returns the progress as a percentage.' 297 percent = property(percentage)
305 for index, widget
in enumerate(self.
widgets):
306 if isinstance(widget, WidgetHFill):
307 result.append(widget)
308 expanding.insert(0, index)
311 result.append(widget)
314 count = len(expanding)
316 portion =
max(
int(math.ceil(width * 1. / count)), 0)
317 index = expanding.pop()
320 widget = result[index].
update(self, portion)
322 result[index] = widget
328 'Joins the widgets and justifies the line' 337 'Returns whether the ProgressBar should redraw the line.' 345 'Checks all widgets for the time sensitive bit' 352 'Updates the ProgressBar to a new value.' 354 if value
is not None and value
is not UnknownLength:
355 if (self.
maxval is not UnknownLength
356 and not 0 <= value <= self.
maxval):
358 raise ValueError(
'Value out of range')
365 raise RuntimeError(
'You must call "start" before calling "update"')
375 '''Starts measuring time, and prints the bar at 0%. 377 It returns self so you can use it like this: 378 >>> pbar = ProgressBar().start() 379 >>> for i in range(100): 392 if self.
maxval is not UnknownLength:
393 if self.
maxval < 0:
raise ValueError(
'Value out of range')
404 'Puts the ProgressBar bar in the finished state.' 410 signal.signal(signal.SIGWINCH, signal.SIG_DFL)
412 if hasattr(updatable,
'update'):
return updatable.update(pbar)
413 else:
return updatable
def __call__(self, iterable)
def update(self, pbar, width)
def _update_widgets(self)
def format_updatable(updatable, pbar)
def __init__(self, format='Elapsed Time:%s')
def update(self, pbar, width)
def __init__(self, maxval=None, widgets=None, term_width=None, poll=1, left_justify=True, fd=sys.stderr)
bool any(const std::vector< T > &v, const T &what)
def _handle_resize(self, signum=None, frame=None)
PROGRESSBAR Classes END ####.
static std::string join(char **cmd)
def __init__(self, marker='#', left='|', right='|', fill=' ', fill_left=True)
def update(self, value=None)
def _format_widgets(self)