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
if self.total is not None:
28
self.percent = 100.0 * current / total
31
if self.total is not None:
32
return "%i of %i %s %.1f%%" % (self.current, self.total, self.units,
35
return "%i %s" (self.current, self.units)
37
class ProgressBar(object):
42
def __call__(self, progress):
43
if self.start is None:
44
self.start = datetime.datetime.now()
45
progress_bar(progress, start_time=self.start)
47
def divide_timedelta(delt, divisor):
48
"""Divides a timedelta object"""
49
return datetime.timedelta(float(delt.days)/divisor,
50
float(delt.seconds)/divisor,
51
float(delt.microseconds)/divisor)
56
return str(datetime.timedelta(delt.days, delt.seconds))
58
def get_eta(start_time, progress, enough_samples=20):
59
if start_time is None or progress.current == 0:
61
elif progress.current < enough_samples:
63
elapsed = datetime.datetime.now() - start_time
64
total_duration = divide_timedelta((elapsed) * long(progress.total),
66
if elapsed < total_duration:
67
eta = total_duration - elapsed
69
eta = total_duration - total_duration
72
def progress_bar(progress, start_time=None):
73
eta = get_eta(start_time, progress)
74
if start_time is not None:
75
eta_str = " "+str_tdelta(eta)
79
fmt = " %i of %i %s (%.1f%%)"
80
f = fmt % (progress.total, progress.total, progress.units, 100.0)
83
if start_time is not None:
85
markers = int (float(cols) * progress.current / progress.total)
86
txt = fmt % (progress.current, progress.total, progress.units,
88
sys.stderr.write("\r[%s%s]%s%s" % ('='*markers, ' '*(cols-markers), txt,
91
def clear_progress_bar():
92
sys.stderr.write('\r%s\r' % (' '*79))
94
def spinner_str(progress, show_text=False):
96
Produces the string for a textual "spinner" progress indicator
97
:param progress: an object represinting current progress
98
:param show_text: If true, show progress text as well
99
:return: The spinner string
101
>>> spinner_str(Progress("baloons", 0))
103
>>> spinner_str(Progress("baloons", 5))
105
>>> spinner_str(Progress("baloons", 6), show_text=True)
108
positions = ('|', '/', '-', '\\')
109
text = positions[progress.current % 4]
111
text+=" %i %s" % (progress.current, progress.units)
114
def spinner(progress, show_text=False, output=sys.stderr):
116
Update a spinner progress indicator on an output
117
:param progress: The progress to display
118
:param show_text: If true, show text as well as spinner
119
:param output: The output to write to
121
>>> spinner(Progress("baloons", 6), show_text=True, output=sys.stdout)
124
output.write('\r%s' % spinner_str(progress, show_text))
128
result = doctest.testmod()
131
print "All tests passed"
133
print "No tests to run"
134
if __name__ == "__main__":