import sys try: import curses except ImportError: pass class ProgressMeter(object): """An abstract object which prints out progress messages.""" def newstage(self, title, length): """Called when a new part of the scanning has been reached. title is a human-readable description of the part, length is the estimated length of the part - the total count that will be passed to "progress" eventually.""" raise NotImplementedError def progress(self, amount): """Called when the part has progressed by "amount" units (out of "length" that was passed to newstage).""" raise NotImplementedError def endstage(self): """Called at the end of each stage.""" raise NotImplementedError def finished(self): """Called when there are no more stages.""" raise NotImplementedError class ConsoleProgressMeter(object): """A text-mode progress bar for the scanner, that moves the cursor about to print a percentage and a bar.""" def __init__(self): # Use curses to get the terminal width. try: curses.setupterm() self.width = curses.tigetnum("cols") - 1 except: raise IOError, "curses not available - " + \ "try using PlainProgressMeter" def newstage(self, desc, length): print desc self.length = length self.total = 0 self.redraw() def progress(self, amount): self.total += amount self.redraw() def endstage(self): print print def finished(self): pass def redraw(self): # The width we can use, excluding room for the percentage # (5 characters) and [, ] and > mainwidth = self.width - 8 # Percentage complete percentage = self.total * 100 // self.length # Number of characters complete squares = self.total * mainwidth // self.length percentage_str = (str(percentage) + "%").ljust(5) filled_bar = "=" * squares empty_bar = " " * (mainwidth - squares) print "\r" + percentage_str + "[" + filled_bar + ">" + \ empty_bar + "]", sys.stdout.flush() class PlainProgressMeter(object): """A text-mode progress reporting thingy for the scanner, that does nothing very exciting apart from print dots.""" def newstage(self, desc, length): sys.stdout.write(desc) sys.stdout.write("..") sys.stdout.flush() def progress(self, amount): sys.stdout.write(".") sys.stdout.flush() def endstage(self): print def finished(self): pass def meter(): """Returns a (hopefully) appropriate meter.""" try: return ConsoleProgressMeter() except IOError: return PlainProgressMeter()