Coverage for /Volumes/workspace/python-progressbar/.tox/py38/lib/python3.8/site-packages/progressbar/bar.py : 100%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from __future__ import absolute_import
2from __future__ import division
3from __future__ import unicode_literals
4from __future__ import with_statement
6import sys
7import math
8import os
9import time
10import timeit
11import logging
12import warnings
13from datetime import datetime
14from copy import deepcopy
15try: # pragma: no cover
16 from collections import abc
17except ImportError: # pragma: no cover
18 import collections as abc
20from python_utils import converters
22import six
24from . import widgets
25from . import widgets as widgets_module # Avoid name collision
26from . import base
27from . import utils
30logger = logging.getLogger(__name__)
33class ProgressBarMixinBase(object):
35 def __init__(self, **kwargs):
36 self._finished = False
38 def start(self, **kwargs):
39 pass
41 def update(self, value=None):
42 pass
44 def finish(self): # pragma: no cover
45 self._finished = True
47 def __del__(self):
48 if not self._finished: # pragma: no cover
49 try:
50 self.finish()
51 except Exception:
52 pass
55class ProgressBarBase(abc.Iterable, ProgressBarMixinBase):
56 pass
59class DefaultFdMixin(ProgressBarMixinBase):
61 def __init__(self, fd=sys.stderr, is_terminal=None, line_breaks=None,
62 enable_colors=None, **kwargs):
63 if fd is sys.stdout:
64 fd = utils.streams.original_stdout
66 elif fd is sys.stderr:
67 fd = utils.streams.original_stderr
69 self.fd = fd
70 self.is_ansi_terminal = utils.is_ansi_terminal(fd)
72 # Check if this is an interactive terminal
73 self.is_terminal = utils.is_terminal(
74 fd, is_terminal or self.is_ansi_terminal)
76 # Check if it should overwrite the current line (suitable for
77 # iteractive terminals) or write line breaks (suitable for log files)
78 if line_breaks is None:
79 line_breaks = utils.env_flag('PROGRESSBAR_LINE_BREAKS', not
80 self.is_terminal)
81 self.line_breaks = line_breaks
83 # Check if ANSI escape characters are enabled (suitable for iteractive
84 # terminals), or should be stripped off (suitable for log files)
85 if enable_colors is None:
86 enable_colors = utils.env_flag('PROGRESSBAR_ENABLE_COLORS',
87 self.is_ansi_terminal)
89 self.enable_colors = enable_colors
91 ProgressBarMixinBase.__init__(self, **kwargs)
93 def update(self, *args, **kwargs):
94 ProgressBarMixinBase.update(self, *args, **kwargs)
96 line = converters.to_unicode(self._format_line())
97 if not self.enable_colors:
98 line = utils.no_color(line)
100 if self.line_breaks:
101 line = line.rstrip() + '\n'
102 else:
103 line = '\r' + line
105 try: # pragma: no cover
106 self.fd.write(line)
107 except UnicodeEncodeError: # pragma: no cover
108 self.fd.write(line.encode('ascii', 'replace'))
110 def finish(self, *args, **kwargs): # pragma: no cover
111 if self._finished:
112 return
114 end = kwargs.pop('end', '\n')
115 ProgressBarMixinBase.finish(self, *args, **kwargs)
117 if end and not self.line_breaks:
118 self.fd.write(end)
120 self.fd.flush()
123class ResizableMixin(ProgressBarMixinBase):
125 def __init__(self, term_width=None, **kwargs):
126 ProgressBarMixinBase.__init__(self, **kwargs)
128 self.signal_set = False
129 if term_width:
130 self.term_width = term_width
131 else: # pragma: no cover
132 try:
133 self._handle_resize()
134 import signal
135 self._prev_handle = signal.getsignal(signal.SIGWINCH)
136 signal.signal(signal.SIGWINCH, self._handle_resize)
137 self.signal_set = True
138 except Exception:
139 pass
141 def _handle_resize(self, signum=None, frame=None):
142 'Tries to catch resize signals sent from the terminal.'
144 w, h = utils.get_terminal_size()
145 self.term_width = w
147 def finish(self): # pragma: no cover
148 ProgressBarMixinBase.finish(self)
149 if self.signal_set:
150 try:
151 import signal
152 signal.signal(signal.SIGWINCH, self._prev_handle)
153 except Exception: # pragma no cover
154 pass
157class StdRedirectMixin(DefaultFdMixin):
159 def __init__(self, redirect_stderr=False, redirect_stdout=False, **kwargs):
160 DefaultFdMixin.__init__(self, **kwargs)
161 self.redirect_stderr = redirect_stderr
162 self.redirect_stdout = redirect_stdout
163 self._stdout = self.stdout = sys.stdout
164 self._stderr = self.stderr = sys.stderr
166 def start(self, *args, **kwargs):
167 if self.redirect_stdout:
168 utils.streams.wrap_stdout()
170 if self.redirect_stderr:
171 utils.streams.wrap_stderr()
173 self._stdout = utils.streams.original_stdout
174 self._stderr = utils.streams.original_stderr
176 self.stdout = utils.streams.stdout
177 self.stderr = utils.streams.stderr
179 utils.streams.start_capturing(self)
180 DefaultFdMixin.start(self, *args, **kwargs)
182 def update(self, value=None):
183 if not self.line_breaks and utils.streams.needs_clear():
184 self.fd.write('\r' + ' ' * self.term_width + '\r')
186 utils.streams.flush()
187 DefaultFdMixin.update(self, value=value)
189 def finish(self, end='\n'):
190 DefaultFdMixin.finish(self, end=end)
191 utils.streams.stop_capturing(self)
192 if self.redirect_stdout:
193 utils.streams.unwrap_stdout()
195 if self.redirect_stderr:
196 utils.streams.unwrap_stderr()
199class ProgressBar(StdRedirectMixin, ResizableMixin, ProgressBarBase):
201 '''The ProgressBar class which updates and prints the bar.
203 Args:
204 min_value (int): The minimum/start value for the progress bar
205 max_value (int): The maximum/end value for the progress bar.
206 Defaults to `_DEFAULT_MAXVAL`
207 widgets (list): The widgets to render, defaults to the result of
208 `default_widget()`
209 left_justify (bool): Justify to the left if `True` or the right if
210 `False`
211 initial_value (int): The value to start with
212 poll_interval (float): The update interval in seconds.
213 Note that if your widgets include timers or animations, the actual
214 interval may be smaller (faster updates). Also note that updates
215 never happens faster than `min_poll_interval` which can be used for
216 reduced output in logs
217 min_poll_interval (float): The minimum update interval in seconds.
218 The bar will _not_ be updated faster than this, despite changes in
219 the progress, unless `force=True`. This is limited to be at least
220 `_MINIMUM_UPDATE_INTERVAL`. If available, it is also bound by the
221 environment variable PROGRESSBAR_MINIMUM_UPDATE_INTERVAL
222 widget_kwargs (dict): The default keyword arguments for widgets
223 custom_len (function): Method to override how the line width is
224 calculated. When using non-latin characters the width
225 calculation might be off by default
226 max_error (bool): When True the progressbar will raise an error if it
227 goes beyond it's set max_value. Otherwise the max_value is simply
228 raised when needed
229 prefix (str): Prefix the progressbar with the given string
230 suffix (str): Prefix the progressbar with the given string
231 variables (dict): User-defined variables variables that can be used
232 from a label using `format='{variables.my_var}'`. These values can
233 be updated using `bar.update(my_var='newValue')` This can also be
234 used to set initial values for variables' widgets
236 A common way of using it is like:
238 >>> progress = ProgressBar().start()
239 >>> for i in range(100):
240 ... progress.update(i + 1)
241 ... # do something
242 ...
243 >>> progress.finish()
245 You can also use a ProgressBar as an iterator:
247 >>> progress = ProgressBar()
248 >>> some_iterable = range(100)
249 >>> for i in progress(some_iterable):
250 ... # do something
251 ... pass
252 ...
254 Since the progress bar is incredibly customizable you can specify
255 different widgets of any type in any order. You can even write your own
256 widgets! However, since there are already a good number of widgets you
257 should probably play around with them before moving on to create your own
258 widgets.
260 The term_width parameter represents the current terminal width. If the
261 parameter is set to an integer then the progress bar will use that,
262 otherwise it will attempt to determine the terminal width falling back to
263 80 columns if the width cannot be determined.
265 When implementing a widget's update method you are passed a reference to
266 the current progress bar. As a result, you have access to the
267 ProgressBar's methods and attributes. Although there is nothing preventing
268 you from changing the ProgressBar you should treat it as read only.
270 Useful methods and attributes include (Public API):
271 - value: current progress (min_value <= value <= max_value)
272 - max_value: maximum (and final) value
273 - end_time: not None if the bar has finished (reached 100%)
274 - start_time: the time when start() method of ProgressBar was called
275 - seconds_elapsed: seconds elapsed since start_time and last call to
276 update
277 '''
279 _DEFAULT_MAXVAL = base.UnknownLength
280 # update every 50 milliseconds (up to a 20 times per second)
281 _MINIMUM_UPDATE_INTERVAL = 0.050
283 def __init__(self, min_value=0, max_value=None, widgets=None,
284 left_justify=True, initial_value=0, poll_interval=None,
285 widget_kwargs=None, custom_len=utils.len_color,
286 max_error=True, prefix=None, suffix=None, variables=None,
287 min_poll_interval=None, **kwargs):
288 '''
289 Initializes a progress bar with sane defaults
290 '''
291 StdRedirectMixin.__init__(self, **kwargs)
292 ResizableMixin.__init__(self, **kwargs)
293 ProgressBarBase.__init__(self, **kwargs)
294 if not max_value and kwargs.get('maxval') is not None:
295 warnings.warn('The usage of `maxval` is deprecated, please use '
296 '`max_value` instead', DeprecationWarning)
297 max_value = kwargs.get('maxval')
299 if not poll_interval and kwargs.get('poll'):
300 warnings.warn('The usage of `poll` is deprecated, please use '
301 '`poll_interval` instead', DeprecationWarning)
302 poll_interval = kwargs.get('poll')
304 if max_value:
305 if min_value > max_value:
306 raise ValueError('Max value needs to be bigger than the min '
307 'value')
308 self.min_value = min_value
309 self.max_value = max_value
310 self.max_error = max_error
311 self.widgets = deepcopy(widgets)
312 self.prefix = prefix
313 self.suffix = suffix
314 self.widget_kwargs = widget_kwargs or {}
315 self.left_justify = left_justify
316 self.value = initial_value
317 self._iterable = None
318 self.custom_len = custom_len
319 self.init()
321 # Convert a given timedelta to a floating point number as internal
322 # interval. We're not using timedelta's internally for two reasons:
323 # 1. Backwards compatibility (most important one)
324 # 2. Performance. Even though the amount of time it takes to compare a
325 # timedelta with a float versus a float directly is negligible, this
326 # comparison is run for _every_ update. With billions of updates
327 # (downloading a 1GiB file for example) this adds up.
328 poll_interval = utils.deltas_to_seconds(poll_interval, default=None)
329 min_poll_interval = utils.deltas_to_seconds(min_poll_interval,
330 default=None)
331 self._MINIMUM_UPDATE_INTERVAL = utils.deltas_to_seconds(
332 self._MINIMUM_UPDATE_INTERVAL)
334 # Note that the _MINIMUM_UPDATE_INTERVAL sets the minimum in case of
335 # low values.
336 self.poll_interval = poll_interval
337 self.min_poll_interval = max(
338 min_poll_interval or self._MINIMUM_UPDATE_INTERVAL,
339 self._MINIMUM_UPDATE_INTERVAL,
340 float(os.environ.get('PROGRESSBAR_MINIMUM_UPDATE_INTERVAL', 0)),
341 )
343 # A dictionary of names that can be used by Variable and FormatWidget
344 self.variables = utils.AttributeDict(variables or {})
345 for widget in (self.widgets or []):
346 if isinstance(widget, widgets_module.VariableMixin):
347 if widget.name not in self.variables:
348 self.variables[widget.name] = None
350 @property
351 def dynamic_messages(self): # pragma: no cover
352 return self.variables
354 @dynamic_messages.setter
355 def dynamic_messages(self, value): # pragma: no cover
356 self.variables = value
358 def init(self):
359 '''
360 (re)initialize values to original state so the progressbar can be
361 used (again)
362 '''
363 self.previous_value = None
364 self.last_update_time = None
365 self.start_time = None
366 self.updates = 0
367 self.end_time = None
368 self.extra = dict()
369 self._last_update_timer = timeit.default_timer()
371 @property
372 def percentage(self):
373 '''Return current percentage, returns None if no max_value is given
375 >>> progress = ProgressBar()
376 >>> progress.max_value = 10
377 >>> progress.min_value = 0
378 >>> progress.value = 0
379 >>> progress.percentage
380 0.0
381 >>>
382 >>> progress.value = 1
383 >>> progress.percentage
384 10.0
385 >>> progress.value = 10
386 >>> progress.percentage
387 100.0
388 >>> progress.min_value = -10
389 >>> progress.percentage
390 100.0
391 >>> progress.value = 0
392 >>> progress.percentage
393 50.0
394 >>> progress.value = 5
395 >>> progress.percentage
396 75.0
397 >>> progress.value = -5
398 >>> progress.percentage
399 25.0
400 >>> progress.max_value = None
401 >>> progress.percentage
402 '''
403 if self.max_value is None or self.max_value is base.UnknownLength:
404 return None
405 elif self.max_value:
406 todo = self.value - self.min_value
407 total = self.max_value - self.min_value
408 percentage = todo / total
409 else:
410 percentage = 1
412 return percentage * 100
414 def get_last_update_time(self):
415 if self._last_update_time:
416 return datetime.fromtimestamp(self._last_update_time)
418 def set_last_update_time(self, value):
419 if value:
420 self._last_update_time = time.mktime(value.timetuple())
421 else:
422 self._last_update_time = None
424 last_update_time = property(get_last_update_time, set_last_update_time)
426 def data(self):
427 '''
429 Returns:
430 dict:
431 - `max_value`: The maximum value (can be None with
432 iterators)
433 - `start_time`: Start time of the widget
434 - `last_update_time`: Last update time of the widget
435 - `end_time`: End time of the widget
436 - `value`: The current value
437 - `previous_value`: The previous value
438 - `updates`: The total update count
439 - `total_seconds_elapsed`: The seconds since the bar started
440 - `seconds_elapsed`: The seconds since the bar started modulo
441 60
442 - `minutes_elapsed`: The minutes since the bar started modulo
443 60
444 - `hours_elapsed`: The hours since the bar started modulo 24
445 - `days_elapsed`: The hours since the bar started
446 - `time_elapsed`: The raw elapsed `datetime.timedelta` object
447 - `percentage`: Percentage as a float or `None` if no max_value
448 is available
449 - `dynamic_messages`: Deprecated, use `variables` instead.
450 - `variables`: Dictionary of user-defined variables for the
451 :py:class:`~progressbar.widgets.Variable`'s
453 '''
454 self._last_update_time = time.time()
455 self._last_update_timer = timeit.default_timer()
456 elapsed = self.last_update_time - self.start_time
457 # For Python 2.7 and higher we have _`timedelta.total_seconds`, but we
458 # want to support older versions as well
459 total_seconds_elapsed = utils.deltas_to_seconds(elapsed)
460 return dict(
461 # The maximum value (can be None with iterators)
462 max_value=self.max_value,
463 # Start time of the widget
464 start_time=self.start_time,
465 # Last update time of the widget
466 last_update_time=self.last_update_time,
467 # End time of the widget
468 end_time=self.end_time,
469 # The current value
470 value=self.value,
471 # The previous value
472 previous_value=self.previous_value,
473 # The total update count
474 updates=self.updates,
475 # The seconds since the bar started
476 total_seconds_elapsed=total_seconds_elapsed,
477 # The seconds since the bar started modulo 60
478 seconds_elapsed=(elapsed.seconds % 60) +
479 (elapsed.microseconds / 1000000.),
480 # The minutes since the bar started modulo 60
481 minutes_elapsed=(elapsed.seconds / 60) % 60,
482 # The hours since the bar started modulo 24
483 hours_elapsed=(elapsed.seconds / (60 * 60)) % 24,
484 # The hours since the bar started
485 days_elapsed=(elapsed.seconds / (60 * 60 * 24)),
486 # The raw elapsed `datetime.timedelta` object
487 time_elapsed=elapsed,
488 # Percentage as a float or `None` if no max_value is available
489 percentage=self.percentage,
490 # Dictionary of user-defined
491 # :py:class:`progressbar.widgets.Variable`'s
492 variables=self.variables,
493 # Deprecated alias for `variables`
494 dynamic_messages=self.variables,
495 )
497 def default_widgets(self):
498 if self.max_value:
499 return [
500 widgets.Percentage(**self.widget_kwargs),
501 ' ', widgets.SimpleProgress(
502 format='(%s)' % widgets.SimpleProgress.DEFAULT_FORMAT,
503 **self.widget_kwargs),
504 ' ', widgets.Bar(**self.widget_kwargs),
505 ' ', widgets.Timer(**self.widget_kwargs),
506 ' ', widgets.AdaptiveETA(**self.widget_kwargs),
507 ]
508 else:
509 return [
510 widgets.AnimatedMarker(**self.widget_kwargs),
511 ' ', widgets.BouncingBar(**self.widget_kwargs),
512 ' ', widgets.Counter(**self.widget_kwargs),
513 ' ', widgets.Timer(**self.widget_kwargs),
514 ]
516 def __call__(self, iterable, max_value=None):
517 'Use a ProgressBar to iterate through an iterable'
518 if max_value is not None:
519 self.max_value = max_value
520 elif self.max_value is None:
521 try:
522 self.max_value = len(iterable)
523 except TypeError: # pragma: no cover
524 self.max_value = base.UnknownLength
526 self._iterable = iter(iterable)
527 return self
529 def __iter__(self):
530 return self
532 def __next__(self):
533 try:
534 value = next(self._iterable)
535 if self.start_time is None:
536 self.start()
537 else:
538 self.update(self.value + 1)
539 return value
540 except StopIteration:
541 self.finish()
542 raise
543 except GeneratorExit: # pragma: no cover
544 self.finish(dirty=True)
545 raise
547 def __exit__(self, exc_type, exc_value, traceback):
548 self.finish(dirty=bool(exc_type))
550 def __enter__(self):
551 return self
553 # Create an alias so that Python 2.x won't complain about not being
554 # an iterator.
555 next = __next__
557 def __iadd__(self, value):
558 'Updates the ProgressBar by adding a new value.'
559 self.update(self.value + value)
560 return self
562 def _format_widgets(self):
563 result = []
564 expanding = []
565 width = self.term_width
566 data = self.data()
568 for index, widget in enumerate(self.widgets):
569 if isinstance(widget, widgets.WidgetBase) \
570 and not widget.check_size(self):
571 continue
572 elif isinstance(widget, widgets.AutoWidthWidgetBase):
573 result.append(widget)
574 expanding.insert(0, index)
575 elif isinstance(widget, six.string_types):
576 result.append(widget)
577 width -= self.custom_len(widget)
578 else:
579 widget_output = converters.to_unicode(widget(self, data))
580 result.append(widget_output)
581 width -= self.custom_len(widget_output)
583 count = len(expanding)
584 while expanding:
585 portion = max(int(math.ceil(width * 1. / count)), 0)
586 index = expanding.pop()
587 widget = result[index]
588 count -= 1
590 widget_output = widget(self, data, portion)
591 width -= self.custom_len(widget_output)
592 result[index] = widget_output
594 return result
596 @classmethod
597 def _to_unicode(cls, args):
598 for arg in args:
599 yield converters.to_unicode(arg)
601 def _format_line(self):
602 'Joins the widgets and justifies the line'
604 widgets = ''.join(self._to_unicode(self._format_widgets()))
606 if self.left_justify:
607 return widgets.ljust(self.term_width)
608 else:
609 return widgets.rjust(self.term_width)
611 def _needs_update(self):
612 'Returns whether the ProgressBar should redraw the line.'
613 delta = timeit.default_timer() - self._last_update_timer
614 if delta < self.min_poll_interval:
615 # Prevent updating too often
616 return False
617 elif self.poll_interval and delta > self.poll_interval:
618 # Needs to redraw timers and animations
619 return True
621 # Update if value increment is not large enough to
622 # add more bars to progressbar (according to current
623 # terminal width)
624 try:
625 divisor = self.max_value / self.term_width # float division
626 if self.value // divisor != self.previous_value // divisor:
627 return True
628 except Exception:
629 # ignore any division errors
630 pass
632 # No need to redraw yet
633 return False
635 def update(self, value=None, force=False, **kwargs):
636 'Updates the ProgressBar to a new value.'
637 if self.start_time is None:
638 self.start()
639 return self.update(value, force=force, **kwargs)
641 if value is not None and value is not base.UnknownLength:
642 if self.max_value is base.UnknownLength:
643 # Can't compare against unknown lengths so just update
644 pass
645 elif self.min_value <= value <= self.max_value: # pragma: no cover
646 # Correct value, let's accept
647 pass
648 elif self.max_error:
649 raise ValueError(
650 'Value %s is out of range, should be between %s and %s'
651 % (value, self.min_value, self.max_value))
652 else:
653 self.max_value = value
655 self.previous_value = self.value
656 self.value = value
658 # Save the updated values for dynamic messages
659 variables_changed = False
660 for key in kwargs:
661 if key not in self.variables:
662 raise TypeError(
663 'update() got an unexpected keyword ' +
664 'argument {0!r}'.format(key))
665 elif self.variables[key] != kwargs[key]:
666 self.variables[key] = kwargs[key]
667 variables_changed = True
669 if self._needs_update() or variables_changed or force:
670 self.updates += 1
671 ResizableMixin.update(self, value=value)
672 ProgressBarBase.update(self, value=value)
673 StdRedirectMixin.update(self, value=value)
675 # Only flush if something was actually written
676 self.fd.flush()
678 def start(self, max_value=None, init=True):
679 '''Starts measuring time, and prints the bar at 0%.
681 It returns self so you can use it like this:
683 Args:
684 max_value (int): The maximum value of the progressbar
685 reinit (bool): Initialize the progressbar, this is useful if you
686 wish to reuse the same progressbar but can be disabled if
687 data needs to be passed along to the next run
689 >>> pbar = ProgressBar().start()
690 >>> for i in range(100):
691 ... # do something
692 ... pbar.update(i+1)
693 ...
694 >>> pbar.finish()
695 '''
696 if init:
697 self.init()
699 # Prevent multiple starts
700 if self.start_time is not None: # pragma: no cover
701 return self
703 if max_value is not None:
704 self.max_value = max_value
706 if self.max_value is None:
707 self.max_value = self._DEFAULT_MAXVAL
709 StdRedirectMixin.start(self, max_value=max_value)
710 ResizableMixin.start(self, max_value=max_value)
711 ProgressBarBase.start(self, max_value=max_value)
713 # Constructing the default widgets is only done when we know max_value
714 if self.widgets is None:
715 self.widgets = self.default_widgets()
717 if self.prefix:
718 self.widgets.insert(0, widgets.FormatLabel(
719 self.prefix, new_style=True))
721 if self.suffix:
722 self.widgets.append(widgets.FormatLabel(
723 self.suffix, new_style=True))
725 for widget in self.widgets:
726 interval = getattr(widget, 'INTERVAL', None)
727 if interval is not None:
728 interval = utils.deltas_to_seconds(interval)
730 self.poll_interval = min(
731 self.poll_interval or interval,
732 interval,
733 )
735 self.num_intervals = max(100, self.term_width)
736 # The `next_update` is kept for compatibility with external libs:
737 # https://github.com/WoLpH/python-progressbar/issues/207
738 self.next_update = 0
740 if self.max_value is not base.UnknownLength and self.max_value < 0:
741 raise ValueError('max_value out of range, got %r' % self.max_value)
743 self.start_time = self.last_update_time = datetime.now()
744 self._last_update_timer = timeit.default_timer()
745 self.update(self.min_value, force=True)
747 return self
749 def finish(self, end='\n', dirty=False):
750 '''
751 Puts the ProgressBar bar in the finished state.
753 Also flushes and disables output buffering if this was the last
754 progressbar running.
756 Args:
757 end (str): The string to end the progressbar with, defaults to a
758 newline
759 dirty (bool): When True the progressbar kept the current state and
760 won't be set to 100 percent
761 '''
763 if not dirty:
764 self.end_time = datetime.now()
765 self.update(self.max_value, force=True)
767 StdRedirectMixin.finish(self, end=end)
768 ResizableMixin.finish(self)
769 ProgressBarBase.finish(self)
772class DataTransferBar(ProgressBar):
773 '''A progress bar with sensible defaults for downloads etc.
775 This assumes that the values its given are numbers of bytes.
776 '''
777 def default_widgets(self):
778 if self.max_value:
779 return [
780 widgets.Percentage(),
781 ' of ', widgets.DataSize('max_value'),
782 ' ', widgets.Bar(),
783 ' ', widgets.Timer(),
784 ' ', widgets.AdaptiveETA(),
785 ]
786 else:
787 return [
788 widgets.AnimatedMarker(),
789 ' ', widgets.DataSize(),
790 ' ', widgets.Timer(),
791 ]
794class NullBar(ProgressBar):
796 '''
797 Progress bar that does absolutely nothing. Useful for single verbosity
798 flags
799 '''
801 def start(self, *args, **kwargs):
802 return self
804 def update(self, *args, **kwargs):
805 return self
807 def finish(self, *args, **kwargs):
808 return self