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  from __future__ import absolute_import 
 43  from __future__ import print_function 
 44  import six 
 45  from six.moves import range 
 46  __author__ = "Nilton Volpato" 
 47  __author_email__ = "first-name dot last-name @ gmail.com" 
 48  __date__ = "2006-05-07" 
 49  __version__ = "2.2" 
 50   
 51  # Changelog 
 52  # 
 53  # 2006-05-07: v2.2 fixed bug in windows 
 54  # 2005-12-04: v2.1 autodetect terminal width, added start method 
 55  # 2005-12-04: v2.0 everything is now a widget (wow!) 
 56  # 2005-12-03: v1.0 rewrite using widgets 
 57  # 2005-06-02: v0.5 rewrite 
 58  # 2004-??-??: v0.1 first version 
 59   
 60   
 61  import sys, time 
 62  from array import array 
 63  try: 
 64      from fcntl import ioctl 
 65      import termios 
 66  except ImportError: 
 67      pass 
 68  import signal 
 69   
70 -class ProgressBarWidget(object):
71 """This is an element of ProgressBar formatting. 72 73 The ProgressBar object will call it's update value when an update 74 is needed. It's size may change between call, but the results will 75 not be good if the size changes drastically and repeatedly. 76 """
77 - def update(self, pbar):
78 """Returns the string representing the widget. 79 80 The parameter pbar is a reference to the calling ProgressBar, 81 where one can access attributes of the class for knowing how 82 the update must be made. 83 84 At least this function must be overriden.""" 85 pass
86
87 -class ProgressBarWidgetHFill(object):
88 """This is a variable width element of ProgressBar formatting. 89 90 The ProgressBar object will call it's update value, informing the 91 width this object must the made. This is like TeX \\hfill, it will 92 expand to fill the line. You can use more than one in the same 93 line, and they will all have the same width, and together will 94 fill the line. 95 """
96 - def update(self, pbar, width):
97 """Returns the string representing the widget. 98 99 The parameter pbar is a reference to the calling ProgressBar, 100 where one can access attributes of the class for knowing how 101 the update must be made. The parameter width is the total 102 horizontal width the widget must have. 103 104 At least this function must be overriden.""" 105 pass
106 107
108 -class ETA(ProgressBarWidget):
109 "Widget for the Estimated Time of Arrival"
110 - def format_time(self, seconds):
111 return time.strftime('%H:%M:%S', time.gmtime(seconds))
112 - def update(self, pbar):
113 if pbar.currval == 0: 114 return 'ETA: --:--:--' 115 elif pbar.finished: 116 return 'Time: %s' % self.format_time(pbar.seconds_elapsed) 117 else: 118 elapsed = pbar.seconds_elapsed 119 eta = elapsed * pbar.maxval / pbar.currval - elapsed 120 return 'ETA: %s' % self.format_time(eta)
121
122 -class FileTransferSpeed(ProgressBarWidget):
123 "Widget for showing the transfer speed (useful for file transfers)."
124 - def __init__(self):
125 self.fmt = '%6.2f %s' 126 self.units = ['B','K','M','G','T','P']
127 - def update(self, pbar):
128 if pbar.seconds_elapsed < 2e-6:#== 0: 129 bps = 0.0 130 else: 131 bps = float(pbar.currval) / pbar.seconds_elapsed 132 spd = bps 133 for u in self.units: 134 if spd < 1000: 135 break 136 spd /= 1000 137 return self.fmt % (spd, u+'/s')
138
139 -class RotatingMarker(ProgressBarWidget):
140 "A rotating marker for filling the bar of progress."
141 - def __init__(self, markers='|/-\\'):
142 self.markers = markers 143 self.curmark = -1
144 - def update(self, pbar):
145 if pbar.finished: 146 return self.markers[0] 147 self.curmark = (self.curmark + 1)%len(self.markers) 148 return self.markers[self.curmark]
149
150 -class Percentage(ProgressBarWidget):
151 "Just the percentage done."
152 - def update(self, pbar):
153 return '%3d%%' % pbar.percentage()
154
155 -class Bar(ProgressBarWidgetHFill):
156 "The bar of progress. It will strech to fill the line."
157 - def __init__(self, marker='#', left='|', right='|'):
158 self.marker = marker 159 self.left = left 160 self.right = right
161 - def _format_marker(self, pbar):
162 if isinstance(self.marker, (str, six.text_type)): 163 return self.marker 164 else: 165 return self.marker.update(pbar)
166 - def update(self, pbar, width):
167 percent = pbar.percentage() 168 cwidth = width - len(self.left) - len(self.right) 169 marked_width = int(percent * cwidth / 100) 170 m = self._format_marker(pbar) 171 bar = (self.left + (m*marked_width).ljust(cwidth) + self.right) 172 return bar
173
174 -class ReverseBar(Bar):
175 "The reverse bar of progress, or bar of regress. :)"
176 - def update(self, pbar, width):
177 percent = pbar.percentage() 178 cwidth = width - len(self.left) - len(self.right) 179 marked_width = int(percent * cwidth / 100) 180 m = self._format_marker(pbar) 181 bar = (self.left + (m*marked_width).rjust(cwidth) + self.right) 182 return bar
183 184 default_widgets = [Percentage(), ' ', Bar()]
185 -class ProgressBar(object):
186 """This is the ProgressBar class, it updates and prints the bar. 187 188 The term_width parameter may be an integer. Or None, in which case 189 it will try to guess it, if it fails it will default to 80 columns. 190 191 The simple use is like this: 192 >>> pbar = ProgressBar().start() 193 >>> for i in xrange(100): 194 ... # do something 195 ... pbar.update(i+1) 196 ... 197 >>> pbar.finish() 198 199 But anything you want to do is possible (well, almost anything). 200 You can supply different widgets of any type in any order. And you 201 can even write your own widgets! There are many widgets already 202 shipped and you should experiment with them. 203 204 When implementing a widget update method you may access any 205 attribute or function of the ProgressBar object calling the 206 widget's update method. The most important attributes you would 207 like to access are: 208 - currval: current value of the progress, 0 <= currval <= maxval 209 - maxval: maximum (and final) value of the progress 210 - finished: True if the bar is have finished (reached 100%), False o/w 211 - start_time: first time update() method of ProgressBar was called 212 - seconds_elapsed: seconds elapsed since start_time 213 - percentage(): percentage of the progress (this is a method) 214 """
215 - def __init__(self, maxval=100, widgets=default_widgets, term_width=None, 216 fd=sys.stderr):
217 assert maxval >= 0 218 self.maxval = maxval 219 self.widgets = widgets 220 self.fd = fd 221 self.signal_set = False 222 if term_width is None: 223 try: 224 self.handle_resize(None,None) 225 signal.signal(signal.SIGWINCH, self.handle_resize) 226 self.signal_set = True 227 except Exception: 228 self.term_width = 79 229 else: 230 self.term_width = term_width 231 232 self.currval = 0 233 self.finished = False 234 self.prev_percentage = -1 235 self.start_time = None 236 self.seconds_elapsed = 0
237
238 - def handle_resize(self, signum, frame):
239 h,w=array('h', ioctl(self.fd,termios.TIOCGWINSZ,'\0'*8))[:2] 240 self.term_width = w
241
242 - def percentage(self):
243 "Returns the percentage of the progress." 244 return self.currval*100.0 / self.maxval
245
246 - def _format_widgets(self):
247 r = [] 248 hfill_inds = [] 249 num_hfill = 0 250 currwidth = 0 251 for i, w in enumerate(self.widgets): 252 if isinstance(w, ProgressBarWidgetHFill): 253 r.append(w) 254 hfill_inds.append(i) 255 num_hfill += 1 256 elif isinstance(w, (str, six.text_type)): 257 r.append(w) 258 currwidth += len(w) 259 else: 260 weval = w.update(self) 261 currwidth += len(weval) 262 r.append(weval) 263 for iw in hfill_inds: 264 r[iw] = r[iw].update(self, (self.term_width-currwidth)//num_hfill) 265 return r
266
267 - def _format_line(self):
268 return ''.join(self._format_widgets()).ljust(self.term_width)
269
270 - def _need_update(self):
271 return int(self.percentage()) != int(self.prev_percentage)
272
273 - def update(self, value):
274 "Updates the progress bar to a new value." 275 assert 0 <= value <= self.maxval 276 self.currval = value 277 if not self._need_update() or self.finished: 278 return 279 if not self.start_time: 280 self.start_time = time.time() 281 self.seconds_elapsed = time.time() - self.start_time 282 self.prev_percentage = self.percentage() 283 if value != self.maxval: 284 self.fd.write(self._format_line() + '\r') 285 else: 286 self.finished = True 287 self.fd.write(self._format_line() + '\n')
288
289 - def start(self):
290 """Start measuring time, and prints the bar at 0%. 291 292 It returns self so you can use it like this: 293 >>> pbar = ProgressBar().start() 294 >>> for i in xrange(100): 295 ... # do something 296 ... pbar.update(i+1) 297 ... 298 >>> pbar.finish() 299 """ 300 self.update(0) 301 return self
302
303 - def finish(self):
304 """Used to tell the progress is finished.""" 305 self.update(self.maxval) 306 self.fd.flush() 307 if self.signal_set: 308 signal.signal(signal.SIGWINCH, signal.SIG_DFL)
309 310 # a suitable full made package
311 -class progbar(ProgressBar):
312
313 - def __init__(self,name,max_step):
314 """ a practicla definition of a progressbar this one is une in MW""" 315 316 widgets = [name+': ', Percentage(), ' ', Bar('>'), 317 ' ', ETA(), ' '] 318 if max_step: 319 ProgressBar.__init__(self,widgets=widgets, maxval=max_step) 320 self.start() 321 self.maxval=max_step 322 self.actual_step=0
323
324 - def update(self,value=-1):
325 if value<0: 326 self.actual_step+=1 327 else: 328 self.actual_step=value 329 330 if self.maxval: 331 ProgressBar.update(self,self.actual_step)
332
333 - def finish(self):
334 335 if self.maxval: 336 ProgressBar.finish(self)
337 338 339 340 if __name__=='__main__': 341 import os 342 import time
343 - def exampleVal():
344 widgets = ['ValTest', Percentage(), ' ', Bar(),' ', ETA(), ' '] 345 pbar = ProgressBar(widgets=widgets, maxval=100).start() 346 for i in range(100): 347 time.sleep(0.02) 348 # do something 349 pbar.update(1*i+1) 350 pbar.finish() 351 print()
352
353 - def example1():
354 widgets = ['Test: ', Percentage(), ' ', Bar(marker=RotatingMarker()), 355 ' ', ETA(), ' ', FileTransferSpeed()] 356 pbar = ProgressBar(widgets=widgets, maxval=10000000).start() 357 for i in range(1000000): 358 # do something 359 pbar.update(10*i+1) 360 pbar.finish() 361 print()
362
363 - def example2():
364 class CrazyFileTransferSpeed(FileTransferSpeed): 365 "It's bigger between 45 and 80 percent" 366 def update(self, pbar): 367 if 45 < pbar.percentage() < 80: 368 return 'Bigger Now ' + FileTransferSpeed.update(self,pbar) 369 else: 370 return FileTransferSpeed.update(self,pbar)
371 372 widgets = [CrazyFileTransferSpeed(),' <<<', Bar(), '>>> ', Percentage(),' ', ETA()] 373 pbar = ProgressBar(widgets=widgets, maxval=10000000) 374 # maybe do something 375 pbar.start() 376 for i in range(2000000): 377 # do something 378 pbar.update(5*i+1) 379 pbar.finish() 380 print() 381
382 - def example3():
383 widgets = [Bar('>'), ' ', ETA(), ' ', ReverseBar('<')] 384 pbar = ProgressBar(widgets=widgets, maxval=10000000).start() 385 for i in range(1000000): 386 # do something 387 pbar.update(10*i+1) 388 pbar.finish() 389 print()
390
391 - def example4():
392 widgets = ['Test: ', Percentage(), ' ', 393 Bar(marker='0',left='[',right=']'), 394 ' ', ETA(), ' ', FileTransferSpeed()] 395 pbar = ProgressBar(widgets=widgets, maxval=500) 396 pbar.start() 397 for i in range(100,500+1,50): 398 time.sleep(0.2) 399 pbar.update(i) 400 pbar.finish() 401 print()
402 403 exampleVal() 404 example1() 405 example2() 406 example3() 407 example4() 408