1#!/usr/bin/env python
2
3from __future__ import print_function
4
5import use_lldb_suite
6
7import sys
8import time
9
10
11class ProgressBar(object):
12    """ProgressBar class holds the options of the progress bar.
13    The options are:
14        start   State from which start the progress. For example, if start is
15                5 and the end is 10, the progress of this state is 50%
16        end     State in which the progress has terminated.
17        width   --
18        fill    String to use for "filled" used to represent the progress
19        blank   String to use for "filled" used to represent remaining space.
20        format  Format
21        incremental
22    """
23    light_block = chr(0x2591).encode("utf-8")
24    solid_block = chr(0x2588).encode("utf-8")
25    solid_right_arrow = chr(0x25BA).encode("utf-8")
26
27    def __init__(self,
28                 start=0,
29                 end=10,
30                 width=12,
31                 fill=chr(0x25C9).encode("utf-8"),
32                 blank=chr(0x25CC).encode("utf-8"),
33                 marker=chr(0x25CE).encode("utf-8"),
34                 format='[%(fill)s%(marker)s%(blank)s] %(progress)s%%',
35                 incremental=True):
36        super(ProgressBar, self).__init__()
37
38        self.start = start
39        self.end = end
40        self.width = width
41        self.fill = fill
42        self.blank = blank
43        self.marker = marker
44        self.format = format
45        self.incremental = incremental
46        self.step = 100 / float(width)  # fix
47        self.reset()
48
49    def __add__(self, increment):
50        increment = self._get_progress(increment)
51        if 100 > self.progress + increment:
52            self.progress += increment
53        else:
54            self.progress = 100
55        return self
56
57    def complete(self):
58        self.progress = 100
59        return self
60
61    def __str__(self):
62        progressed = int(self.progress / self.step)  # fix
63        fill = progressed * self.fill
64        blank = (self.width - progressed) * self.blank
65        return self.format % {
66            'fill': fill,
67            'blank': blank,
68            'marker': self.marker,
69            'progress': int(
70                self.progress)}
71
72    __repr__ = __str__
73
74    def _get_progress(self, increment):
75        return float(increment * 100) / self.end
76
77    def reset(self):
78        """Resets the current progress to the start point"""
79        self.progress = self._get_progress(self.start)
80        return self
81
82
83class AnimatedProgressBar(ProgressBar):
84    """Extends ProgressBar to allow you to use it straighforward on a script.
85    Accepts an extra keyword argument named `stdout` (by default use sys.stdout)
86    and may be any file-object to which send the progress status.
87    """
88
89    def __init__(self,
90                 start=0,
91                 end=10,
92                 width=12,
93                 fill=chr(0x25C9).encode("utf-8"),
94                 blank=chr(0x25CC).encode("utf-8"),
95                 marker=chr(0x25CE).encode("utf-8"),
96                 format='[%(fill)s%(marker)s%(blank)s] %(progress)s%%',
97                 incremental=True,
98                 stdout=sys.stdout):
99        super(
100            AnimatedProgressBar,
101            self).__init__(
102            start,
103            end,
104            width,
105            fill,
106            blank,
107            marker,
108            format,
109            incremental)
110        self.stdout = stdout
111
112    def show_progress(self):
113        if hasattr(self.stdout, 'isatty') and self.stdout.isatty():
114            self.stdout.write('\r')
115        else:
116            self.stdout.write('\n')
117        self.stdout.write(str(self))
118        self.stdout.flush()
119
120
121class ProgressWithEvents(AnimatedProgressBar):
122    """Extends AnimatedProgressBar to allow you to track a set of events that
123       cause the progress to move. For instance, in a deletion progress bar, you
124       can track files that were nuked and files that the user doesn't have access to
125    """
126
127    def __init__(self,
128                 start=0,
129                 end=10,
130                 width=12,
131                 fill=chr(0x25C9).encode("utf-8"),
132                 blank=chr(0x25CC).encode("utf-8"),
133                 marker=chr(0x25CE).encode("utf-8"),
134                 format='[%(fill)s%(marker)s%(blank)s] %(progress)s%%',
135                 incremental=True,
136                 stdout=sys.stdout):
137        super(
138            ProgressWithEvents,
139            self).__init__(
140            start,
141            end,
142            width,
143            fill,
144            blank,
145            marker,
146            format,
147            incremental,
148            stdout)
149        self.events = {}
150
151    def add_event(self, event):
152        if event in self.events:
153            self.events[event] += 1
154        else:
155            self.events[event] = 1
156
157    def show_progress(self):
158        isatty = hasattr(self.stdout, 'isatty') and self.stdout.isatty()
159        if isatty:
160            self.stdout.write('\r')
161        else:
162            self.stdout.write('\n')
163        self.stdout.write(str(self))
164        if len(self.events) == 0:
165            return
166        self.stdout.write('\n')
167        for key in list(self.events.keys()):
168            self.stdout.write(str(key) + ' = ' + str(self.events[key]) + ' ')
169        if isatty:
170            self.stdout.write('\033[1A')
171        self.stdout.flush()
172
173
174if __name__ == '__main__':
175    p = AnimatedProgressBar(end=200, width=200)
176
177    while True:
178        p + 5
179        p.show_progress()
180        time.sleep(0.3)
181        if p.progress == 100:
182            break
183    print()  # new line
184