-
Notifications
You must be signed in to change notification settings - Fork 1
/
progress_bar.py
128 lines (97 loc) · 3.33 KB
/
progress_bar.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# -*- coding:utf-8 -*-
import sys
import enum
from datetime import datetime
class ProgressBar(object):
def __init__(self, max_num, unit_num=1):
self.max_num = max_num
self.unit_num = unit_num
self.current_num = 0
self.started_at = None
self.finished_at = None
@classmethod
def iteration(cls, iterable, call_back, unit_num=1):
with cls(len(iterable), unit_num) as progress_bar:
for item in iterable:
call_back(item)
progress_bar.forward()
@property
def progress(self):
return float(self.current_num) / float(self.max_num)
@property
def percentage(self):
return self.progress * 100
@property
def remaining(self):
return self.max_num - self.current_num
def is_complete(self):
return self.max_num <= self.current_num
def forward(self):
self.update(self.current_num + self.unit_num)
def back(self):
self.update(self.current_num - self.unit_num)
def update(self, num):
self.current_num = max(0, min(self.max_num, num))
def start(self):
self.update(0)
self.started_at = datetime.now()
def finish(self):
self.finished_at = datetime.now()
def __enter__(self):
self.start()
return self
def __exit__(self, exc_type, exc_value, traceback):
self.finish()
class CommandLineProgressBar(ProgressBar):
LENGTH = 30
BAR = '='
TIP = '-'
UNDER = '.'
MessageType = enum.Enum(
'MessageType',
'''
COURSE
COMPLETE
WARNING
FAIL
'''
)
def update(self, num):
super(CommandLineProgressBar, self).update(num)
if self.is_complete():
self._write_complete()
return
self._write_course()
def finish(self):
super(CommandLineProgressBar, self).finish()
if not self.is_complete():
self._write_fail()
self._line_brake()
def _get_str(self):
bar = int(self.LENGTH * self.progress)
return '[{bar}{tip}{under}] {percentage}% ({current}/{max})'.format(
bar=self.BAR * bar,
tip=self.TIP if bar < self.LENGTH else self.BAR,
under=self.UNDER * (self.LENGTH - bar),
percentage=int(self.percentage),
current=self.current_num,
max=self.max_num)
def _get_message_format(self, message_type=None):
return {
self.MessageType.COURSE.value: '\r\033[94m{message}\033[0m',
self.MessageType.COMPLETE.value: '\r\033[92m{message}\033[0m',
self.MessageType.WARNING.value: '\r\033[93m{message}\033[0m',
self.MessageType.FAIL.value: '\r\033[91m{message}\033[0m',
}.get(message_type) or '\r{message}'
def _write(self, message, message_type=None):
message_format = self._get_message_format(message_type)
sys.stderr.write(message_format.format(message=message))
sys.stderr.flush()
def _write_course(self):
self._write(self._get_str(), self.MessageType.COURSE.value)
def _write_fail(self):
self._write(self._get_str(), self.MessageType.FAIL.value)
def _write_complete(self):
self._write(self._get_str(), self.MessageType.COMPLETE.value)
def _line_brake(self):
self._write('\n')