[Pkg-bazaar-commits] ./bzr/unstable r649: - some cleanups for the progressbar method
Martin Pool
mbp at sourcefrog.net
Fri Apr 10 08:20:01 UTC 2009
------------------------------------------------------------
revno: 649
committer: Martin Pool <mbp at sourcefrog.net>
timestamp: Fri 2005-06-10 17:10:25 +1000
message:
- some cleanups for the progressbar method
modified:
bzrlib/progress.py
-------------- next part --------------
=== modified file 'bzrlib/progress.py'
--- a/bzrlib/progress.py 2005-06-10 07:02:15 +0000
+++ b/bzrlib/progress.py 2005-06-10 07:10:25 +0000
@@ -1,5 +1,5 @@
-# Copyright (C) 2005 Aaron Bentley
-# <aaron.bentley at utoronto.ca>
+# Copyright (C) 2005 Aaron Bentley <aaron.bentley at utoronto.ca>
+# Copyright (C) 2005 Canonical <canonical.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -15,9 +15,47 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""
+Simple text-mode progress indicator.
+
+Everyone loves ascii art!
+
+To display an indicator, create a ProgressBar object. Call it,
+passing Progress objects indicating the current state. When done,
+call clear().
+
+Progress is suppressed when output is not sent to a terminal, so as
+not to clutter log files.
+"""
+
+# TODO: remove functions in favour of keeping everything in one class
+
+
import sys
import datetime
+
+def _width():
+ """Return estimated terminal width.
+
+ TODO: Do something smart on Windows?
+
+ TODO: Is there anything that gets a better update when the window
+ is resized while the program is running?
+ """
+ import os
+ try:
+ return int(os.environ['COLUMNS'])
+ except (IndexError, KeyError, ValueError):
+ return 80
+
+
+def _supports_progress(f):
+ return hasattr(f, 'isatty') and f.isatty()
+
+
+
class Progress(object):
def __init__(self, units, current, total=None):
self.units = units
@@ -35,17 +73,30 @@
return "%i of %i %s %.1f%%" % (self.current, self.total, self.units,
self.percent)
else:
- return "%i %s" (self.current, self.units)
+ return "%i %s" (self.current, self.units)
+
+
class ProgressBar(object):
- def __init__(self):
+ def __init__(self, to_file=sys.stderr):
+ object.__init__(self)
self.start = None
- object.__init__(self)
+ self.to_file = to_file
+ self.suppressed = not _supports_progress(self.to_file)
+
def __call__(self, progress):
if self.start is None:
self.start = datetime.datetime.now()
- progress_bar(progress, start_time=self.start)
+ if not self.suppressed:
+ draw_progress_bar(progress, start_time=self.start,
+ to_file=self.to_file)
+
+ def clear(self):
+ if not self.suppressed:
+ clear_progress_bar(self.to_file)
+
+
def divide_timedelta(delt, divisor):
"""Divides a timedelta object"""
@@ -58,6 +109,7 @@
return "-:--:--"
return str(datetime.timedelta(delt.days, delt.seconds))
+
def get_eta(start_time, progress, enough_samples=20):
if start_time is None or progress.current == 0:
return None
@@ -72,7 +124,8 @@
eta = total_duration - total_duration
return eta
-def progress_bar(progress, start_time=None):
+
+def draw_progress_bar(progress, start_time=None, to_file=sys.stderr):
eta = get_eta(start_time, progress)
if start_time is not None:
eta_str = " "+str_tdelta(eta)
@@ -81,18 +134,18 @@
fmt = " %i of %i %s (%.1f%%)"
f = fmt % (progress.total, progress.total, progress.units, 100.0)
- max = len(f)
- cols = 77 - max
+ cols = _width() - 3 - len(f)
if start_time is not None:
cols -= len(eta_str)
markers = int (float(cols) * progress.current / progress.total)
txt = fmt % (progress.current, progress.total, progress.units,
progress.percent)
- sys.stderr.write("\r[%s%s]%s%s" % ('='*markers, ' '*(cols-markers), txt,
+ to_file.write("\r[%s%s]%s%s" % ('='*markers, ' '*(cols-markers), txt,
eta_str))
-def clear_progress_bar():
- sys.stderr.write('\r%s\r' % (' '*79))
+def clear_progress_bar(to_file=sys.stderr):
+ to_file.write('\r%s\r' % (' '*79))
+
def spinner_str(progress, show_text=False):
"""
@@ -114,6 +167,7 @@
text+=" %i %s" % (progress.current, progress.units)
return text
+
def spinner(progress, show_text=False, output=sys.stderr):
"""
Update a spinner progress indicator on an output
@@ -126,6 +180,7 @@
"""
output.write('\r%s' % spinner_str(progress, show_text))
+
def run_tests():
import doctest
result = doctest.testmod()
@@ -134,5 +189,15 @@
print "All tests passed"
else:
print "No tests to run"
+
+
+def demo():
+ from time import sleep
+ pb = ProgressBar()
+ for i in range(100):
+ pb(Progress('Elephanten', i, 100))
+ sleep(0.3)
+ print 'done!'
+
if __name__ == "__main__":
- run_tests()
+ demo()
More information about the Pkg-bazaar-commits
mailing list