1
# Copyright (C) 2005 Aaron Bentley
2
# <aaron.bentley@utoronto.ca>
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
class Progress(object):
22
def __init__(self, units, current, total=None):
24
self.current = current
27
def _get_percent(self):
28
if self.total is not None and self.current is not None:
29
return 100.0 * self.current / self.total
31
percent = property(_get_percent)
34
if self.total is not None:
35
return "%i of %i %s %.1f%%" % (self.current, self.total, self.units,
38
return "%i %s" (self.current, self.units)
40
class ProgressBar(object):
45
def __call__(self, progress):
46
if self.start is None:
47
self.start = datetime.datetime.now()
48
progress_bar(progress, start_time=self.start)
50
def divide_timedelta(delt, divisor):
51
"""Divides a timedelta object"""
52
return datetime.timedelta(float(delt.days)/divisor,
53
float(delt.seconds)/divisor,
54
float(delt.microseconds)/divisor)
59
return str(datetime.timedelta(delt.days, delt.seconds))
61
def get_eta(start_time, progress, enough_samples=20):
62
if start_time is None or progress.current == 0:
64
elif progress.current < enough_samples:
66
elapsed = datetime.datetime.now() - start_time
67
total_duration = divide_timedelta((elapsed) * long(progress.total),
69
if elapsed < total_duration:
70
eta = total_duration - elapsed
72
eta = total_duration - total_duration
75
def progress_bar(progress, start_time=None):
76
eta = get_eta(start_time, progress)
77
if start_time is not None:
78
eta_str = " "+str_tdelta(eta)
82
fmt = " %i of %i %s (%.1f%%)"
83
f = fmt % (progress.total, progress.total, progress.units, 100.0)
86
if start_time is not None:
88
markers = int (float(cols) * progress.current / progress.total)
89
txt = fmt % (progress.current, progress.total, progress.units,
91
sys.stderr.write("\r[%s%s]%s%s" % ('='*markers, ' '*(cols-markers), txt,
94
def clear_progress_bar():
95
sys.stderr.write('\r%s\r' % (' '*79))
97
def spinner_str(progress, show_text=False):
99
Produces the string for a textual "spinner" progress indicator
100
:param progress: an object represinting current progress
101
:param show_text: If true, show progress text as well
102
:return: The spinner string
104
>>> spinner_str(Progress("baloons", 0))
106
>>> spinner_str(Progress("baloons", 5))
108
>>> spinner_str(Progress("baloons", 6), show_text=True)
111
positions = ('|', '/', '-', '\\')
112
text = positions[progress.current % 4]
114
text+=" %i %s" % (progress.current, progress.units)
117
def spinner(progress, show_text=False, output=sys.stderr):
119
Update a spinner progress indicator on an output
120
:param progress: The progress to display
121
:param show_text: If true, show text as well as spinner
122
:param output: The output to write to
124
>>> spinner(Progress("baloons", 6), show_text=True, output=sys.stdout)
127
output.write('\r%s' % spinner_str(progress, show_text))
131
result = doctest.testmod()
134
print "All tests passed"
136
print "No tests to run"
137
if __name__ == "__main__":