########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Lib/ProgressIndicator.py,v 1.8 2005/04/18 23:17:57 jkloth Exp $
"""
Progress indicator
Copyright 2004 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""
import sys, time, os
from Ft.Lib import Terminal
class ProgressIndicator:
"""
A progress indicator intended for terminal output (relies on ^H).
Indicator style, given as constructor argument, can be
0: percentage; 1: bar; or 2: both. Default is 0.
If using styles 1 or 2, an optional width argument
for the bar portion can also be given (default 60).
Example usage:
# First emit whatever prefaces the indicator, if desired
print " status:",
sys.__stdout__.flush()
# Create a new indicator
p = ProgressIndicator(2)
p.newIndicator()
# With each iteration through a task, or as often as you want,
# call updateProgress(), passing 2 numbers: amount completed,
# and total amount to do.
limit = 300000
for i in range(limit):
p.updateProgress(i, limit)
print
"""
if os.name == 'nt' or os.name == 'dos':
# dark/light shades... thanks Oleg Broytmann.
# OK for all MS-DOS codepages except 864 (Arabic) & 874 (Thai)
# and python doesn't seem to mind writing the non-ASCII chars.
_hashchar = '\xb2'
_blankchar = '\xb0'
elif (os.environ.get('LANG', '').endswith('.UTF-8') and
os.environ.get('TERM') == "xterm"):
# UTF-8 enabled terminal
# 25% => x2591
# 50% => x2592
# 75% => x2593
# 100% => x2588
_hashchar = u'\u2588'.encode('UTF-8')
_blankchar = u'\u2591'.encode('UTF-8')
else:
_hashchar = '*'
_blankchar = ' '
_current = 0
_total = 0
def __init__(self, prefix, stream=sys.stdout):
if type(prefix) == type(u''):
# avoid possible UnicodeError during output
self.prefix = prefix.encode('ascii','replace')
else:
self.prefix = prefix
self._tty = Terminal.Terminal(stream)
self._writetty = self._tty.writetty
self._flushtty = self._tty.flush
return
def newIndicator(self, total):
"""
Start a new indicator at 00%.
Optional style and width arguments are same as constructor.
"""
self._current = 0
self._total = total
self._showProgress()
return
def _erase(self):
self._writetty("\r")
def message(self,message):
# left-justify message within column width, padding or trimming as
# required.
columns = self._tty.columns()
message = '%-*.*s' % (columns, columns, message)
self._erase()
self._writetty(message + '\n');
self._showProgress()
def updateProgress(self, cur):
"""
Update an existing indicator to reflect given progress.
Arguments are amount completed so far, and total to do.
For example, if 4 out of 30 have been completed, call
updateProgress(4,30).
"""
self._current = cur
self._erase()
self._showProgress()
return
def _showProgress(self):
barwidth = self._tty.columns() - 3 - len(self.prefix) - 4
hashwidth = int(float(self._current+1)/self._total * (barwidth - 2))
pct = int((self._current+1)*100/self._total)
self._writetty("%s |%s%s %s%%" % (
self.prefix,
self._hashchar * hashwidth,
self._blankchar * (barwidth - hashwidth - 2) + "|",
" " * (pct < 100) + "%02d" % pct))
self._flushtty()
return
class AutoProgressIndicator(ProgressIndicator):
def __init__(self, prefix, total, step=1, stream=sys.stdout):
ProgressIndicator.__init__(self, prefix, stream)
self.newIndicator(total)
self._step = 1
return
def advance(self):
self.updateProgress(self._current + self._step)
return
|