Package madgraph :: Package various :: Module progressbar
[hide private]
[frames] | no frames]

Source Code for Module madgraph.various.progressbar

  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 
 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 Exception: 224 self.term_width = 79 225 else: 226 self.term_width = term_width 227 228 self.currval = 0 229 self.finished = False 230 self.prev_percentage = -1 231 self.start_time = None 232 self.seconds_elapsed = 0
233
234 - def handle_resize(self, signum, frame):
235 h,w=array('h', ioctl(self.fd,termios.TIOCGWINSZ,'\0'*8))[:2] 236 self.term_width = w
237
238 - def percentage(self):
239 "Returns the percentage of the progress." 240 return self.currval*100.0 / self.maxval
241
242 - def _format_widgets(self):
243 r = [] 244 hfill_inds = [] 245 num_hfill = 0 246 currwidth = 0 247 for i, w in enumerate(self.widgets): 248 if isinstance(w, ProgressBarWidgetHFill): 249 r.append(w) 250 hfill_inds.append(i) 251 num_hfill += 1 252 elif isinstance(w, (str, unicode)): 253 r.append(w) 254 currwidth += len(w) 255 else: 256 weval = w.update(self) 257 currwidth += len(weval) 258 r.append(weval) 259 for iw in hfill_inds: 260 r[iw] = r[iw].update(self, (self.term_width-currwidth)//num_hfill) 261 return r
262
263 - def _format_line(self):
264 return ''.join(self._format_widgets()).ljust(self.term_width)
265
266 - def _need_update(self):
267 return int(self.percentage()) != int(self.prev_percentage)
268
269 - def update(self, value):
270 "Updates the progress bar to a new value." 271 assert 0 <= value <= self.maxval 272 self.currval = value 273 if not self._need_update() or self.finished: 274 return 275 if not self.start_time: 276 self.start_time = time.time() 277 self.seconds_elapsed = time.time() - self.start_time 278 self.prev_percentage = self.percentage() 279 if value != self.maxval: 280 self.fd.write(self._format_line() + '\r') 281 else: 282 self.finished = True 283 self.fd.write(self._format_line() + '\n')
284
285 - def start(self):
286 """Start measuring time, and prints the bar at 0%. 287 288 It returns self so you can use it like this: 289 >>> pbar = ProgressBar().start() 290 >>> for i in xrange(100): 291 ... # do something 292 ... pbar.update(i+1) 293 ... 294 >>> pbar.finish() 295 """ 296 self.update(0) 297 return self
298
299 - def finish(self):
300 """Used to tell the progress is finished.""" 301 self.update(self.maxval) 302 self.fd.flush() 303 if self.signal_set: 304 signal.signal(signal.SIGWINCH, signal.SIG_DFL)
305 306 # a suitable full made package
307 -class progbar(ProgressBar):
308
309 - def __init__(self,name,max_step):
310 """ a practicla definition of a progressbar this one is une in MW""" 311 312 widgets = [name+': ', Percentage(), ' ', Bar('>'), 313 ' ', ETA(), ' '] 314 if max_step: 315 ProgressBar.__init__(self,widgets=widgets, maxval=max_step) 316 self.start() 317 self.maxval=max_step 318 self.actual_step=0
319
320 - def update(self,value=-1):
321 if value<0: 322 self.actual_step+=1 323 else: 324 self.actual_step=value 325 326 if self.maxval: 327 ProgressBar.update(self,self.actual_step)
328
329 - def finish(self):
330 331 if self.maxval: 332 ProgressBar.finish(self)
333 334 335 336 if __name__=='__main__': 337 import os 338 import time
339 - def exampleVal():
340 widgets = ['ValTest', Percentage(), ' ', Bar(),' ', ETA(), ' '] 341 pbar = ProgressBar(widgets=widgets, maxval=100).start() 342 for i in range(100): 343 time.sleep(0.02) 344 # do something 345 pbar.update(1*i+1) 346 pbar.finish() 347 print
348
349 - def example1():
350 widgets = ['Test: ', Percentage(), ' ', Bar(marker=RotatingMarker()), 351 ' ', ETA(), ' ', FileTransferSpeed()] 352 pbar = ProgressBar(widgets=widgets, maxval=10000000).start() 353 for i in range(1000000): 354 # do something 355 pbar.update(10*i+1) 356 pbar.finish() 357 print
358
359 - def example2():
360 class CrazyFileTransferSpeed(FileTransferSpeed): 361 "It's bigger between 45 and 80 percent" 362 def update(self, pbar): 363 if 45 < pbar.percentage() < 80: 364 return 'Bigger Now ' + FileTransferSpeed.update(self,pbar) 365 else: 366 return FileTransferSpeed.update(self,pbar)
367 368 widgets = [CrazyFileTransferSpeed(),' <<<', Bar(), '>>> ', Percentage(),' ', ETA()] 369 pbar = ProgressBar(widgets=widgets, maxval=10000000) 370 # maybe do something 371 pbar.start() 372 for i in range(2000000): 373 # do something 374 pbar.update(5*i+1) 375 pbar.finish() 376 print 377
378 - def example3():
379 widgets = [Bar('>'), ' ', ETA(), ' ', ReverseBar('<')] 380 pbar = ProgressBar(widgets=widgets, maxval=10000000).start() 381 for i in range(1000000): 382 # do something 383 pbar.update(10*i+1) 384 pbar.finish() 385 print
386
387 - def example4():
388 widgets = ['Test: ', Percentage(), ' ', 389 Bar(marker='0',left='[',right=']'), 390 ' ', ETA(), ' ', FileTransferSpeed()] 391 pbar = ProgressBar(widgets=widgets, maxval=500) 392 pbar.start() 393 for i in range(100,500+1,50): 394 time.sleep(0.2) 395 pbar.update(i) 396 pbar.finish() 397 print
398 399 exampleVal() 400 example1() 401 example2() 402 example3() 403 example4() 404