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
PROGRESSBAR Classes END ####.
const T & max(const T &a, const T &b)
static std::string join(char **cmd)