Skip to content

Commit 3ffdf66

Browse files
author
nilton.volpato
committed
import of progressbar 2.2 into googlecode
0 parents  commit 3ffdf66

File tree

4 files changed

+421
-0
lines changed

4 files changed

+421
-0
lines changed

progressbar/LICENSE

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
progressbar - Text progressbar library for python.
2+
Copyright (C) 2005 Nilton Volpato
3+
4+
This library is free software; you can redistribute it and/or
5+
modify it under the terms of the GNU Lesser General Public
6+
License as published by the Free Software Foundation; either
7+
version 2.1 of the License, or (at your option) any later version.
8+
9+
This library 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 GNU
12+
Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public
15+
License along with this library; if not, write to the Free Software
16+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

progressbar/MANIFEST.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
include README MANIFEST MANIFEST.in LICENSE
2+
include setup.py
3+
include progressbar.py

progressbar/progressbar.py

Lines changed: 370 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,370 @@
1+
#!/usr/bin/python
2+
# -*- coding: iso-8859-1 -*-
3+
#
4+
# progressbar - Text progressbar library for python.
5+
# Copyright (c) 2005 Nilton Volpato
6+
#
7+
# This library is free software; you can redistribute it and/or
8+
# modify it under the terms of the GNU Lesser General Public
9+
# License as published by the Free Software Foundation; either
10+
# version 2.1 of the License, or (at your option) any later version.
11+
#
12+
# This library is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
# Lesser General Public License for more details.
16+
#
17+
# You should have received a copy of the GNU Lesser General Public
18+
# License along with this library; if not, write to the Free Software
19+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
21+
22+
"""Text progressbar library for python.
23+
24+
This library provides a text mode progressbar. This is tipically used
25+
to display the progress of a long running operation, providing a
26+
visual clue that processing is underway.
27+
28+
The ProgressBar class manages the progress, and the format of the line
29+
is given by a number of widgets. A widget is an object that may
30+
display diferently depending on the state of the progress. There are
31+
three types of widget:
32+
- a string, which always shows itself;
33+
- a ProgressBarWidget, which may return a diferent value every time
34+
it's update method is called; and
35+
- a ProgressBarWidgetHFill, which is like ProgressBarWidget, except it
36+
expands to fill the remaining width of the line.
37+
38+
The progressbar module is very easy to use, yet very powerful. And
39+
automatically supports features like auto-resizing when available.
40+
"""
41+
42+
__author__ = "Nilton Volpato"
43+
__author_email__ = "first-name dot last-name @ gmail.com"
44+
__date__ = "2006-05-07"
45+
__version__ = "2.2"
46+
47+
# Changelog
48+
#
49+
# 2006-05-07: v2.2 fixed bug in windows
50+
# 2005-12-04: v2.1 autodetect terminal width, added start method
51+
# 2005-12-04: v2.0 everything is now a widget (wow!)
52+
# 2005-12-03: v1.0 rewrite using widgets
53+
# 2005-06-02: v0.5 rewrite
54+
# 2004-??-??: v0.1 first version
55+
56+
57+
import sys, time, os
58+
from array import array
59+
try:
60+
from fcntl import ioctl
61+
import termios
62+
except ImportError:
63+
pass
64+
import signal
65+
66+
class ProgressBarWidget(object):
67+
"""This is an element of ProgressBar formatting.
68+
69+
The ProgressBar object will call it's update value when an update
70+
is needed. It's size may change between call, but the results will
71+
not be good if the size changes drastically and repeatedly.
72+
"""
73+
def update(self, pbar):
74+
"""Returns the string representing the widget.
75+
76+
The parameter pbar is a reference to the calling ProgressBar,
77+
where one can access attributes of the class for knowing how
78+
the update must be made.
79+
80+
At least this function must be overriden."""
81+
pass
82+
83+
class ProgressBarWidgetHFill(object):
84+
"""This is a variable width element of ProgressBar formatting.
85+
86+
The ProgressBar object will call it's update value, informing the
87+
width this object must the made. This is like TeX \\hfill, it will
88+
expand to fill the line. You can use more than one in the same
89+
line, and they will all have the same width, and together will
90+
fill the line.
91+
"""
92+
def update(self, pbar, width):
93+
"""Returns the string representing the widget.
94+
95+
The parameter pbar is a reference to the calling ProgressBar,
96+
where one can access attributes of the class for knowing how
97+
the update must be made. The parameter width is the total
98+
horizontal width the widget must have.
99+
100+
At least this function must be overriden."""
101+
pass
102+
103+
104+
class ETA(ProgressBarWidget):
105+
"Widget for the Estimated Time of Arrival"
106+
def format_time(self, seconds):
107+
return time.strftime('%H:%M:%S', time.gmtime(seconds))
108+
def update(self, pbar):
109+
if pbar.currval == 0:
110+
return 'ETA: --:--:--'
111+
elif pbar.finished:
112+
return 'Time: %s' % self.format_time(pbar.seconds_elapsed)
113+
else:
114+
elapsed = pbar.seconds_elapsed
115+
eta = elapsed * pbar.maxval / pbar.currval - elapsed
116+
return 'ETA: %s' % self.format_time(eta)
117+
118+
class FileTransferSpeed(ProgressBarWidget):
119+
"Widget for showing the transfer speed (useful for file transfers)."
120+
def __init__(self):
121+
self.fmt = '%6.2f %s'
122+
self.units = ['B','K','M','G','T','P']
123+
def update(self, pbar):
124+
if pbar.seconds_elapsed < 2e-6:#== 0:
125+
bps = 0.0
126+
else:
127+
bps = float(pbar.currval) / pbar.seconds_elapsed
128+
spd = bps
129+
for u in self.units:
130+
if spd < 1000:
131+
break
132+
spd /= 1000
133+
return self.fmt % (spd, u+'/s')
134+
135+
class RotatingMarker(ProgressBarWidget):
136+
"A rotating marker for filling the bar of progress."
137+
def __init__(self, markers='|/-\\'):
138+
self.markers = markers
139+
self.curmark = -1
140+
def update(self, pbar):
141+
if pbar.finished:
142+
return self.markers[0]
143+
self.curmark = (self.curmark + 1)%len(self.markers)
144+
return self.markers[self.curmark]
145+
146+
class Percentage(ProgressBarWidget):
147+
"Just the percentage done."
148+
def update(self, pbar):
149+
return '%3d%%' % pbar.percentage()
150+
151+
class Bar(ProgressBarWidgetHFill):
152+
"The bar of progress. It will strech to fill the line."
153+
def __init__(self, marker='#', left='|', right='|'):
154+
self.marker = marker
155+
self.left = left
156+
self.right = right
157+
def _format_marker(self, pbar):
158+
if isinstance(self.marker, (str, unicode)):
159+
return self.marker
160+
else:
161+
return self.marker.update(pbar)
162+
def update(self, pbar, width):
163+
percent = pbar.percentage()
164+
cwidth = width - len(self.left) - len(self.right)
165+
marked_width = int(percent * cwidth / 100)
166+
m = self._format_marker(pbar)
167+
bar = (self.left + (m*marked_width).ljust(cwidth) + self.right)
168+
return bar
169+
170+
class ReverseBar(Bar):
171+
"The reverse bar of progress, or bar of regress. :)"
172+
def update(self, pbar, width):
173+
percent = pbar.percentage()
174+
cwidth = width - len(self.left) - len(self.right)
175+
marked_width = int(percent * cwidth / 100)
176+
m = self._format_marker(pbar)
177+
bar = (self.left + (m*marked_width).rjust(cwidth) + self.right)
178+
return bar
179+
180+
default_widgets = [Percentage(), ' ', Bar()]
181+
class ProgressBar(object):
182+
"""This is the ProgressBar class, it updates and prints the bar.
183+
184+
The term_width parameter may be an integer. Or None, in which case
185+
it will try to guess it, if it fails it will default to 80 columns.
186+
187+
The simple use is like this:
188+
>>> pbar = ProgressBar().start()
189+
>>> for i in xrange(100):
190+
... # do something
191+
... pbar.update(i+1)
192+
...
193+
>>> pbar.finish()
194+
195+
But anything you want to do is possible (well, almost anything).
196+
You can supply different widgets of any type in any order. And you
197+
can even write your own widgets! There are many widgets already
198+
shipped and you should experiment with them.
199+
200+
When implementing a widget update method you may access any
201+
attribute or function of the ProgressBar object calling the
202+
widget's update method. The most important attributes you would
203+
like to access are:
204+
- currval: current value of the progress, 0 <= currval <= maxval
205+
- maxval: maximum (and final) value of the progress
206+
- finished: True if the bar is have finished (reached 100%), False o/w
207+
- start_time: first time update() method of ProgressBar was called
208+
- seconds_elapsed: seconds elapsed since start_time
209+
- percentage(): percentage of the progress (this is a method)
210+
"""
211+
def __init__(self, maxval=100, widgets=default_widgets, term_width=None,
212+
fd=sys.stderr):
213+
assert maxval > 0
214+
self.maxval = maxval
215+
self.widgets = widgets
216+
self.fd = fd
217+
self.signal_set = False
218+
if term_width is None:
219+
try:
220+
self.handle_resize(None,None)
221+
signal.signal(signal.SIGWINCH, self.handle_resize)
222+
self.signal_set = True
223+
except (SystemExit, KeyboardInterrupt):
224+
raise
225+
except:
226+
self.term_width = int(os.environ.get('COLUMNS', 80)) - 1
227+
else:
228+
self.term_width = term_width
229+
230+
self.currval = 0
231+
self.finished = False
232+
self.prev_percentage = -1
233+
self.start_time = None
234+
self.seconds_elapsed = 0
235+
236+
def handle_resize(self, signum, frame):
237+
h,w=array('h', ioctl(self.fd, termios.TIOCGWINSZ, '\0'*8))[:2]
238+
self.term_width = w
239+
240+
def percentage(self):
241+
"Returns the percentage of the progress."
242+
return self.currval*100.0 / self.maxval
243+
244+
def _format_widgets(self):
245+
r = []
246+
hfill_inds = []
247+
num_hfill = 0
248+
currwidth = 0
249+
for i, w in enumerate(self.widgets):
250+
if isinstance(w, ProgressBarWidgetHFill):
251+
r.append(w)
252+
hfill_inds.append(i)
253+
num_hfill += 1
254+
elif isinstance(w, (str, unicode)):
255+
r.append(w)
256+
currwidth += len(w)
257+
else:
258+
weval = w.update(self)
259+
currwidth += len(weval)
260+
r.append(weval)
261+
for iw in hfill_inds:
262+
r[iw] = r[iw].update(self, (self.term_width-currwidth)/num_hfill)
263+
return r
264+
265+
def _format_line(self):
266+
return ''.join(self._format_widgets()).ljust(self.term_width)
267+
268+
def _need_update(self):
269+
return int(self.percentage()) != int(self.prev_percentage)
270+
271+
def update(self, value):
272+
"Updates the progress bar to a new value."
273+
assert 0 <= value <= self.maxval
274+
self.currval = value
275+
if not self._need_update() or self.finished:
276+
return
277+
if not self.start_time:
278+
self.start_time = time.time()
279+
self.seconds_elapsed = time.time() - self.start_time
280+
self.prev_percentage = self.percentage()
281+
if value != self.maxval:
282+
self.fd.write(self._format_line() + '\r')
283+
else:
284+
self.finished = True
285+
self.fd.write(self._format_line() + '\n')
286+
287+
def start(self):
288+
"""Start measuring time, and prints the bar at 0%.
289+
290+
It returns self so you can use it like this:
291+
>>> pbar = ProgressBar().start()
292+
>>> for i in xrange(100):
293+
... # do something
294+
... pbar.update(i+1)
295+
...
296+
>>> pbar.finish()
297+
"""
298+
self.update(0)
299+
return self
300+
301+
def finish(self):
302+
"""Used to tell the progress is finished."""
303+
self.update(self.maxval)
304+
if self.signal_set:
305+
signal.signal(signal.SIGWINCH, signal.SIG_DFL)
306+
307+
308+
309+
310+
311+
312+
if __name__=='__main__':
313+
import os
314+
315+
def example1():
316+
widgets = ['Test: ', Percentage(), ' ', Bar(marker=RotatingMarker()),
317+
' ', ETA(), ' ', FileTransferSpeed()]
318+
pbar = ProgressBar(widgets=widgets, maxval=10000000).start()
319+
for i in range(1000000):
320+
# do something
321+
pbar.update(10*i+1)
322+
pbar.finish()
323+
print
324+
325+
def example2():
326+
class CrazyFileTransferSpeed(FileTransferSpeed):
327+
"It's bigger between 45 and 80 percent"
328+
def update(self, pbar):
329+
if 45 < pbar.percentage() < 80:
330+
return 'Bigger Now ' + FileTransferSpeed.update(self,pbar)
331+
else:
332+
return FileTransferSpeed.update(self,pbar)
333+
334+
widgets = [CrazyFileTransferSpeed(),' <<<', Bar(), '>>> ', Percentage(),' ', ETA()]
335+
pbar = ProgressBar(widgets=widgets, maxval=10000000)
336+
# maybe do something
337+
pbar.start()
338+
for i in range(2000000):
339+
# do something
340+
pbar.update(5*i+1)
341+
pbar.finish()
342+
print
343+
344+
def example3():
345+
widgets = [Bar('>'), ' ', ETA(), ' ', ReverseBar('<')]
346+
pbar = ProgressBar(widgets=widgets, maxval=10000000).start()
347+
for i in range(1000000):
348+
# do something
349+
pbar.update(10*i+1)
350+
pbar.finish()
351+
print
352+
353+
def example4():
354+
widgets = ['Test: ', Percentage(), ' ',
355+
Bar(marker='0',left='[',right=']'),
356+
' ', ETA(), ' ', FileTransferSpeed()]
357+
pbar = ProgressBar(widgets=widgets, maxval=500)
358+
pbar.start()
359+
for i in range(100,500+1,50):
360+
time.sleep(0.2)
361+
pbar.update(i)
362+
pbar.finish()
363+
print
364+
365+
366+
example1()
367+
example2()
368+
example3()
369+
example4()
370+

0 commit comments

Comments
 (0)