1*515bc8c1Sserge-sans-paille#!/usr/bin/env python
26c29ca7dSZachary Turner
36c29ca7dSZachary Turnerfrom __future__ import print_function
46c29ca7dSZachary Turner
56c29ca7dSZachary Turnerimport use_lldb_suite
66c29ca7dSZachary Turnerimport six
76c29ca7dSZachary Turner
86c29ca7dSZachary Turnerimport sys
96c29ca7dSZachary Turnerimport time
106c29ca7dSZachary Turner
11b9c1b51eSKate Stone
126c29ca7dSZachary Turnerclass ProgressBar(object):
136c29ca7dSZachary Turner    """ProgressBar class holds the options of the progress bar.
146c29ca7dSZachary Turner    The options are:
156c29ca7dSZachary Turner        start   State from which start the progress. For example, if start is
166c29ca7dSZachary Turner                5 and the end is 10, the progress of this state is 50%
176c29ca7dSZachary Turner        end     State in which the progress has terminated.
186c29ca7dSZachary Turner        width   --
196c29ca7dSZachary Turner        fill    String to use for "filled" used to represent the progress
206c29ca7dSZachary Turner        blank   String to use for "filled" used to represent remaining space.
216c29ca7dSZachary Turner        format  Format
226c29ca7dSZachary Turner        incremental
236c29ca7dSZachary Turner    """
246c29ca7dSZachary Turner    light_block = six.unichr(0x2591).encode("utf-8")
256c29ca7dSZachary Turner    solid_block = six.unichr(0x2588).encode("utf-8")
266c29ca7dSZachary Turner    solid_right_arrow = six.unichr(0x25BA).encode("utf-8")
276c29ca7dSZachary Turner
286c29ca7dSZachary Turner    def __init__(self,
296c29ca7dSZachary Turner                 start=0,
306c29ca7dSZachary Turner                 end=10,
316c29ca7dSZachary Turner                 width=12,
326c29ca7dSZachary Turner                 fill=six.unichr(0x25C9).encode("utf-8"),
336c29ca7dSZachary Turner                 blank=six.unichr(0x25CC).encode("utf-8"),
346c29ca7dSZachary Turner                 marker=six.unichr(0x25CE).encode("utf-8"),
356c29ca7dSZachary Turner                 format='[%(fill)s%(marker)s%(blank)s] %(progress)s%%',
366c29ca7dSZachary Turner                 incremental=True):
376c29ca7dSZachary Turner        super(ProgressBar, self).__init__()
386c29ca7dSZachary Turner
396c29ca7dSZachary Turner        self.start = start
406c29ca7dSZachary Turner        self.end = end
416c29ca7dSZachary Turner        self.width = width
426c29ca7dSZachary Turner        self.fill = fill
436c29ca7dSZachary Turner        self.blank = blank
446c29ca7dSZachary Turner        self.marker = marker
456c29ca7dSZachary Turner        self.format = format
466c29ca7dSZachary Turner        self.incremental = incremental
476c29ca7dSZachary Turner        self.step = 100 / float(width)  # fix
486c29ca7dSZachary Turner        self.reset()
496c29ca7dSZachary Turner
506c29ca7dSZachary Turner    def __add__(self, increment):
516c29ca7dSZachary Turner        increment = self._get_progress(increment)
526c29ca7dSZachary Turner        if 100 > self.progress + increment:
536c29ca7dSZachary Turner            self.progress += increment
546c29ca7dSZachary Turner        else:
556c29ca7dSZachary Turner            self.progress = 100
566c29ca7dSZachary Turner        return self
576c29ca7dSZachary Turner
586c29ca7dSZachary Turner    def complete(self):
596c29ca7dSZachary Turner        self.progress = 100
606c29ca7dSZachary Turner        return self
616c29ca7dSZachary Turner
626c29ca7dSZachary Turner    def __str__(self):
636c29ca7dSZachary Turner        progressed = int(self.progress / self.step)  # fix
646c29ca7dSZachary Turner        fill = progressed * self.fill
656c29ca7dSZachary Turner        blank = (self.width - progressed) * self.blank
66b9c1b51eSKate Stone        return self.format % {
67b9c1b51eSKate Stone            'fill': fill,
68b9c1b51eSKate Stone            'blank': blank,
69b9c1b51eSKate Stone            'marker': self.marker,
70b9c1b51eSKate Stone            'progress': int(
71b9c1b51eSKate Stone                self.progress)}
726c29ca7dSZachary Turner
736c29ca7dSZachary Turner    __repr__ = __str__
746c29ca7dSZachary Turner
756c29ca7dSZachary Turner    def _get_progress(self, increment):
766c29ca7dSZachary Turner        return float(increment * 100) / self.end
776c29ca7dSZachary Turner
786c29ca7dSZachary Turner    def reset(self):
796c29ca7dSZachary Turner        """Resets the current progress to the start point"""
806c29ca7dSZachary Turner        self.progress = self._get_progress(self.start)
816c29ca7dSZachary Turner        return self
826c29ca7dSZachary Turner
836c29ca7dSZachary Turner
846c29ca7dSZachary Turnerclass AnimatedProgressBar(ProgressBar):
856c29ca7dSZachary Turner    """Extends ProgressBar to allow you to use it straighforward on a script.
866c29ca7dSZachary Turner    Accepts an extra keyword argument named `stdout` (by default use sys.stdout)
876c29ca7dSZachary Turner    and may be any file-object to which send the progress status.
886c29ca7dSZachary Turner    """
89b9c1b51eSKate Stone
906c29ca7dSZachary Turner    def __init__(self,
916c29ca7dSZachary Turner                 start=0,
926c29ca7dSZachary Turner                 end=10,
936c29ca7dSZachary Turner                 width=12,
946c29ca7dSZachary Turner                 fill=six.unichr(0x25C9).encode("utf-8"),
956c29ca7dSZachary Turner                 blank=six.unichr(0x25CC).encode("utf-8"),
966c29ca7dSZachary Turner                 marker=six.unichr(0x25CE).encode("utf-8"),
976c29ca7dSZachary Turner                 format='[%(fill)s%(marker)s%(blank)s] %(progress)s%%',
986c29ca7dSZachary Turner                 incremental=True,
996c29ca7dSZachary Turner                 stdout=sys.stdout):
100b9c1b51eSKate Stone        super(
101b9c1b51eSKate Stone            AnimatedProgressBar,
102b9c1b51eSKate Stone            self).__init__(
103b9c1b51eSKate Stone            start,
104b9c1b51eSKate Stone            end,
105b9c1b51eSKate Stone            width,
106b9c1b51eSKate Stone            fill,
107b9c1b51eSKate Stone            blank,
108b9c1b51eSKate Stone            marker,
109b9c1b51eSKate Stone            format,
110b9c1b51eSKate Stone            incremental)
1116c29ca7dSZachary Turner        self.stdout = stdout
1126c29ca7dSZachary Turner
1136c29ca7dSZachary Turner    def show_progress(self):
1146c29ca7dSZachary Turner        if hasattr(self.stdout, 'isatty') and self.stdout.isatty():
1156c29ca7dSZachary Turner            self.stdout.write('\r')
1166c29ca7dSZachary Turner        else:
1176c29ca7dSZachary Turner            self.stdout.write('\n')
1186c29ca7dSZachary Turner        self.stdout.write(str(self))
1196c29ca7dSZachary Turner        self.stdout.flush()
1206c29ca7dSZachary Turner
121b9c1b51eSKate Stone
1226c29ca7dSZachary Turnerclass ProgressWithEvents(AnimatedProgressBar):
1236c29ca7dSZachary Turner    """Extends AnimatedProgressBar to allow you to track a set of events that
1246c29ca7dSZachary Turner       cause the progress to move. For instance, in a deletion progress bar, you
1256c29ca7dSZachary Turner       can track files that were nuked and files that the user doesn't have access to
1266c29ca7dSZachary Turner    """
127b9c1b51eSKate Stone
1286c29ca7dSZachary Turner    def __init__(self,
1296c29ca7dSZachary Turner                 start=0,
1306c29ca7dSZachary Turner                 end=10,
1316c29ca7dSZachary Turner                 width=12,
1326c29ca7dSZachary Turner                 fill=six.unichr(0x25C9).encode("utf-8"),
1336c29ca7dSZachary Turner                 blank=six.unichr(0x25CC).encode("utf-8"),
1346c29ca7dSZachary Turner                 marker=six.unichr(0x25CE).encode("utf-8"),
1356c29ca7dSZachary Turner                 format='[%(fill)s%(marker)s%(blank)s] %(progress)s%%',
1366c29ca7dSZachary Turner                 incremental=True,
1376c29ca7dSZachary Turner                 stdout=sys.stdout):
138b9c1b51eSKate Stone        super(
139b9c1b51eSKate Stone            ProgressWithEvents,
140b9c1b51eSKate Stone            self).__init__(
141b9c1b51eSKate Stone            start,
142b9c1b51eSKate Stone            end,
143b9c1b51eSKate Stone            width,
144b9c1b51eSKate Stone            fill,
145b9c1b51eSKate Stone            blank,
146b9c1b51eSKate Stone            marker,
147b9c1b51eSKate Stone            format,
148b9c1b51eSKate Stone            incremental,
149b9c1b51eSKate Stone            stdout)
1506c29ca7dSZachary Turner        self.events = {}
1516c29ca7dSZachary Turner
1526c29ca7dSZachary Turner    def add_event(self, event):
1536c29ca7dSZachary Turner        if event in self.events:
1546c29ca7dSZachary Turner            self.events[event] += 1
1556c29ca7dSZachary Turner        else:
1566c29ca7dSZachary Turner            self.events[event] = 1
1576c29ca7dSZachary Turner
1586c29ca7dSZachary Turner    def show_progress(self):
1596c29ca7dSZachary Turner        isatty = hasattr(self.stdout, 'isatty') and self.stdout.isatty()
1606c29ca7dSZachary Turner        if isatty:
1616c29ca7dSZachary Turner            self.stdout.write('\r')
1626c29ca7dSZachary Turner        else:
1636c29ca7dSZachary Turner            self.stdout.write('\n')
1646c29ca7dSZachary Turner        self.stdout.write(str(self))
1656c29ca7dSZachary Turner        if len(self.events) == 0:
1666c29ca7dSZachary Turner            return
1676c29ca7dSZachary Turner        self.stdout.write('\n')
1686c29ca7dSZachary Turner        for key in list(self.events.keys()):
1696c29ca7dSZachary Turner            self.stdout.write(str(key) + ' = ' + str(self.events[key]) + ' ')
1706c29ca7dSZachary Turner        if isatty:
1716c29ca7dSZachary Turner            self.stdout.write('\033[1A')
1726c29ca7dSZachary Turner        self.stdout.flush()
1736c29ca7dSZachary Turner
1746c29ca7dSZachary Turner
1756c29ca7dSZachary Turnerif __name__ == '__main__':
1766c29ca7dSZachary Turner    p = AnimatedProgressBar(end=200, width=200)
1776c29ca7dSZachary Turner
1786c29ca7dSZachary Turner    while True:
1796c29ca7dSZachary Turner        p + 5
1806c29ca7dSZachary Turner        p.show_progress()
1816c29ca7dSZachary Turner        time.sleep(0.3)
1826c29ca7dSZachary Turner        if p.progress == 100:
1836c29ca7dSZachary Turner            break
1846c29ca7dSZachary Turner    print()  # new line
185