1#!/usr/bin/python
2
3from __future__ import print_function
4
5import use_lldb_suite
6import six
7
8import sys
9import time
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 = six.unichr(0x2591).encode("utf-8")
24    solid_block = six.unichr(0x2588).encode("utf-8")
25    solid_right_arrow = six.unichr(0x25BA).encode("utf-8")
26
27    def __init__(self,
28                 start=0,
29                 end=10,
30                 width=12,
31                 fill=six.unichr(0x25C9).encode("utf-8"),
32                 blank=six.unichr(0x25CC).encode("utf-8"),
33                 marker=six.unichr(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 % {'fill': fill, 'blank': blank, 'marker': self.marker, 'progress': int(self.progress)}
66
67    __repr__ = __str__
68
69    def _get_progress(self, increment):
70        return float(increment * 100) / self.end
71
72    def reset(self):
73        """Resets the current progress to the start point"""
74        self.progress = self._get_progress(self.start)
75        return self
76
77
78class AnimatedProgressBar(ProgressBar):
79    """Extends ProgressBar to allow you to use it straighforward on a script.
80    Accepts an extra keyword argument named `stdout` (by default use sys.stdout)
81    and may be any file-object to which send the progress status.
82    """
83    def __init__(self,
84                 start=0,
85                 end=10,
86                 width=12,
87                 fill=six.unichr(0x25C9).encode("utf-8"),
88                 blank=six.unichr(0x25CC).encode("utf-8"),
89                 marker=six.unichr(0x25CE).encode("utf-8"),
90                 format='[%(fill)s%(marker)s%(blank)s] %(progress)s%%',
91                 incremental=True,
92                 stdout=sys.stdout):
93        super(AnimatedProgressBar, self).__init__(start,end,width,fill,blank,marker,format,incremental)
94        self.stdout = stdout
95
96    def show_progress(self):
97        if hasattr(self.stdout, 'isatty') and self.stdout.isatty():
98            self.stdout.write('\r')
99        else:
100            self.stdout.write('\n')
101        self.stdout.write(str(self))
102        self.stdout.flush()
103
104class ProgressWithEvents(AnimatedProgressBar):
105    """Extends AnimatedProgressBar to allow you to track a set of events that
106       cause the progress to move. For instance, in a deletion progress bar, you
107       can track files that were nuked and files that the user doesn't have access to
108    """
109    def __init__(self,
110                 start=0,
111                 end=10,
112                 width=12,
113                 fill=six.unichr(0x25C9).encode("utf-8"),
114                 blank=six.unichr(0x25CC).encode("utf-8"),
115                 marker=six.unichr(0x25CE).encode("utf-8"),
116                 format='[%(fill)s%(marker)s%(blank)s] %(progress)s%%',
117                 incremental=True,
118                 stdout=sys.stdout):
119        super(ProgressWithEvents, self).__init__(start,end,width,fill,blank,marker,format,incremental,stdout)
120        self.events = {}
121
122    def add_event(self,event):
123        if event in self.events:
124            self.events[event] += 1
125        else:
126            self.events[event] = 1
127
128    def show_progress(self):
129        isatty = hasattr(self.stdout, 'isatty') and self.stdout.isatty()
130        if isatty:
131            self.stdout.write('\r')
132        else:
133            self.stdout.write('\n')
134        self.stdout.write(str(self))
135        if len(self.events) == 0:
136            return
137        self.stdout.write('\n')
138        for key in list(self.events.keys()):
139            self.stdout.write(str(key) + ' = ' + str(self.events[key]) + ' ')
140        if isatty:
141            self.stdout.write('\033[1A')
142        self.stdout.flush()
143
144
145if __name__ == '__main__':
146    p = AnimatedProgressBar(end=200, width=200)
147
148    while True:
149        p + 5
150        p.show_progress()
151        time.sleep(0.3)
152        if p.progress == 100:
153            break
154    print() #new line