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

Source Code for Module madgraph.various.misc

   1  ################################################################################ 
   2  # 
   3  # Copyright (c) 2009 The MadGraph5_aMC@NLO Development team and Contributors 
   4  # 
   5  # This file is a part of the MadGraph5_aMC@NLO project, an application which  
   6  # automatically generates Feynman diagrams and matrix elements for arbitrary 
   7  # high-energy processes in the Standard Model and beyond. 
   8  # 
   9  # It is subject to the MadGraph5_aMC@NLO license which should accompany this  
  10  # distribution. 
  11  # 
  12  # For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch 
  13  # 
  14  ################################################################################ 
  15  """A set of functions performing routine administrative I/O tasks.""" 
  16   
  17  import contextlib 
  18  import itertools 
  19  import logging 
  20  import os 
  21  import re 
  22  import signal 
  23  import subprocess 
  24  import sys 
  25  import StringIO 
  26  import sys 
  27  import optparse 
  28  import time 
  29  import shutil 
  30  import traceback 
  31  import gzip as ziplib 
  32  from distutils.version import LooseVersion, StrictVersion 
  33   
  34  try: 
  35      # Use in MadGraph 
  36      import madgraph 
  37  except Exception, error: 
  38      # Use in MadEvent 
  39      import internal 
  40      from internal import MadGraph5Error, InvalidCmd 
  41      import internal.files as files 
  42      MADEVENT = True     
  43  else: 
  44      from madgraph import MadGraph5Error, InvalidCmd 
  45      import madgraph.iolibs.files as files 
  46      MADEVENT = False 
  47   
  48       
  49  logger = logging.getLogger('cmdprint.ext_program') 
  50  logger_stderr = logging.getLogger('madevent.misc') 
  51  pjoin = os.path.join 
52 53 #=============================================================================== 54 # parse_info_str 55 #=============================================================================== 56 -def parse_info_str(fsock):
57 """Parse a newline separated list of "param=value" as a dictionnary 58 """ 59 60 info_dict = {} 61 pattern = re.compile("(?P<name>\w*)\s*=\s*(?P<value>.*)", 62 re.IGNORECASE | re.VERBOSE) 63 for entry in fsock: 64 entry = entry.strip() 65 if len(entry) == 0: continue 66 m = pattern.match(entry) 67 if m is not None: 68 info_dict[m.group('name')] = m.group('value') 69 else: 70 raise IOError, "String %s is not a valid info string" % entry 71 72 return info_dict
73
74 75 -def glob(name, path=''):
76 """call to glob.glob with automatic security on path""" 77 import glob as glob_module 78 path = re.sub('(?P<name>\?|\*|\[|\])', '[\g<name>]', path) 79 return glob_module.glob(pjoin(path, name))
80
81 #=============================================================================== 82 # mute_logger (designed to be a decorator) 83 #=============================================================================== 84 -def mute_logger(names=['madgraph','ALOHA','cmdprint','madevent'], levels=[50,50,50,50]):
85 """change the logger level and restore those at their initial value at the 86 end of the function decorated.""" 87 def control_logger(f): 88 def restore_old_levels(names, levels): 89 for name, level in zip(names, levels): 90 log_module = logging.getLogger(name) 91 log_module.setLevel(level)
92 93 def f_with_no_logger(self, *args, **opt): 94 old_levels = [] 95 for name, level in zip(names, levels): 96 log_module = logging.getLogger(name) 97 old_levels.append(log_module.level) 98 log_module.setLevel(level) 99 try: 100 out = f(self, *args, **opt) 101 restore_old_levels(names, old_levels) 102 return out 103 except: 104 restore_old_levels(names, old_levels) 105 raise 106 107 return f_with_no_logger 108 return control_logger 109 110 PACKAGE_INFO = {}
111 #=============================================================================== 112 # get_pkg_info 113 #=============================================================================== 114 -def get_pkg_info(info_str=None):
115 """Returns the current version information of the MadGraph5_aMC@NLO package, 116 as written in the VERSION text file. If the file cannot be found, 117 a dictionary with empty values is returned. As an option, an info 118 string can be passed to be read instead of the file content. 119 """ 120 global PACKAGE_INFO 121 122 if info_str: 123 info_dict = parse_info_str(StringIO.StringIO(info_str)) 124 return info_dict 125 126 if PACKAGE_INFO: 127 return PACKAGE_INFO 128 129 elif MADEVENT: 130 info_dict ={} 131 info_dict['version'] = open(pjoin(internal.__path__[0],'..','..','MGMEVersion.txt')).read().strip() 132 info_dict['date'] = '20xx-xx-xx' 133 PACKAGE_INFO = info_dict 134 else: 135 if PACKAGE_INFO: 136 return PACKAGE_INFO 137 info_dict = files.read_from_file(os.path.join(madgraph.__path__[0], 138 "VERSION"), 139 parse_info_str, 140 print_error=False) 141 PACKAGE_INFO = info_dict 142 143 return info_dict
144
145 #=============================================================================== 146 # get_time_info 147 #=============================================================================== 148 -def get_time_info():
149 """Returns the present time info for use in MG5 command history header. 150 """ 151 152 creation_time = time.asctime() 153 time_info = {'time': creation_time, 154 'fill': ' ' * (26 - len(creation_time))} 155 156 return time_info
157
158 159 #=============================================================================== 160 # Test the compatibility of a given version of MA5 with this version of MG5 161 #=============================================================================== 162 -def is_MA5_compatible_with_this_MG5(ma5path):
163 """ Returns None if compatible or, it not compatible, a string explaining 164 why it is so.""" 165 166 ma5_version = None 167 try: 168 for line in open(pjoin(ma5path,'version.txt'),'r').read().split('\n'): 169 if line.startswith('MA5 version :'): 170 ma5_version=LooseVersion(line[13:].strip()) 171 break 172 except: 173 ma5_version = None 174 175 if ma5_version is None: 176 reason = "No MadAnalysis5 version number could be read from the path supplied '%s'."%ma5path 177 reason += "\nThe specified version of MadAnalysis5 will not be active in your session." 178 return reason 179 180 mg5_version = None 181 try: 182 info = get_pkg_info() 183 mg5_version = LooseVersion(info['version']) 184 except: 185 mg5_version = None 186 187 # If version not reckognized, then carry on as it's probably a development version 188 if not mg5_version: 189 return None 190 191 if mg5_version < LooseVersion("2.6.1") and ma5_version >= LooseVersion("1.6.32"): 192 reason = "This active MG5aMC version is too old (v%s) for your selected version of MadAnalysis5 (v%s)"%(mg5_version,ma5_version) 193 reason += "\nUpgrade MG5aMC or re-install MA5 from within MG5aMC to fix this compatibility issue." 194 reason += "\nThe specified version of MadAnalysis5 will not be active in your session." 195 return reason 196 197 if mg5_version >= LooseVersion("2.6.1") and ma5_version < LooseVersion("1.6.32"): 198 reason = "Your selected version of MadAnalysis5 (v%s) is too old for this active version of MG5aMC (v%s)."%(ma5_version,mg5_version) 199 reason += "\nRe-install MA5 from within MG5aMC to fix this compatibility issue." 200 reason += "\nThe specified version of MadAnalysis5 will not be active in your session." 201 return reason 202 203 return None
204
205 #=============================================================================== 206 # Find the subdirectory which includes the files ending with a given extension 207 #=============================================================================== 208 -def find_includes_path(start_path, extension):
209 """Browse the subdirectories of the path 'start_path' and returns the first 210 one found which contains at least one file ending with the string extension 211 given in argument.""" 212 213 if not os.path.isdir(start_path): 214 return None 215 subdirs=[pjoin(start_path,dir) for dir in os.listdir(start_path)] 216 for subdir in subdirs: 217 if os.path.isfile(subdir): 218 if os.path.basename(subdir).endswith(extension): 219 return start_path 220 elif os.path.isdir(subdir): 221 path = find_includes_path(subdir, extension) 222 if path: 223 return path 224 return None
225
226 #=============================================================================== 227 # Given the path of a ninja installation, this function determines if it 228 # supports quadruple precision or not. 229 #=============================================================================== 230 -def get_ninja_quad_prec_support(ninja_lib_path):
231 """ Get whether ninja supports quad prec in different ways""" 232 233 # First try with the ninja-config executable if present 234 ninja_config = os.path.abspath(pjoin( 235 ninja_lib_path,os.pardir,'bin','ninja-config')) 236 if os.path.exists(ninja_config): 237 try: 238 p = Popen([ninja_config, '-quadsupport'], stdout=subprocess.PIPE, 239 stderr=subprocess.PIPE) 240 output, error = p.communicate() 241 return 'TRUE' in output.upper() 242 except Exception: 243 pass 244 245 # If no ninja-config is present, then simply use the presence of 246 # 'quadninja' in the include 247 return False
248
249 #=============================================================================== 250 # find a executable 251 #=============================================================================== 252 -def which(program):
253 def is_exe(fpath): 254 return os.path.exists(fpath) and os.access(\ 255 os.path.realpath(fpath), os.X_OK)
256 257 if not program: 258 return None 259 260 fpath, fname = os.path.split(program) 261 if fpath: 262 if is_exe(program): 263 return program 264 else: 265 for path in os.environ["PATH"].split(os.pathsep): 266 exe_file = os.path.join(path, program) 267 if is_exe(exe_file): 268 return exe_file 269 return None 270
271 -def has_f2py():
272 has_f2py = False 273 if which('f2py'): 274 has_f2py = True 275 elif sys.version_info[1] == 6: 276 if which('f2py-2.6'): 277 has_f2py = True 278 elif which('f2py2.6'): 279 has_f2py = True 280 else: 281 if which('f2py-2.7'): 282 has_f2py = True 283 elif which('f2py2.7'): 284 has_f2py = True 285 return has_f2py
286
287 #=============================================================================== 288 # Activate dependencies if possible. Mainly for tests 289 #=============================================================================== 290 291 -def deactivate_dependence(dependency, cmd=None, log = None):
292 """ Make sure to turn off some dependency of MG5aMC. """ 293 294 def tell(msg): 295 if log == 'stdout': 296 print msg 297 elif callable(log): 298 log(msg)
299 300 301 if dependency in ['pjfry','golem','samurai','ninja','collier']: 302 if cmd.options[dependency] not in ['None',None,'']: 303 tell("Deactivating MG5_aMC dependency '%s'"%dependency) 304 cmd.options[dependency] = None 305
306 -def activate_dependence(dependency, cmd=None, log = None, MG5dir=None):
307 """ Checks whether the specfieid MG dependency can be activated if it was 308 not turned off in MG5 options.""" 309 310 def tell(msg): 311 if log == 'stdout': 312 print msg 313 elif callable(log): 314 log(msg)
315 316 if cmd is None: 317 cmd = MGCmd.MasterCmd() 318 319 if dependency=='pjfry': 320 if cmd.options['pjfry'] in ['None',None,''] or \ 321 (cmd.options['pjfry'] == 'auto' and which_lib('libpjfry.a') is None) or\ 322 which_lib(pjoin(cmd.options['pjfry'],'libpjfry.a')) is None: 323 tell("Installing PJFry...") 324 cmd.do_install('PJFry') 325 326 if dependency=='golem': 327 if cmd.options['golem'] in ['None',None,''] or\ 328 (cmd.options['golem'] == 'auto' and which_lib('libgolem.a') is None) or\ 329 which_lib(pjoin(cmd.options['golem'],'libgolem.a')) is None: 330 tell("Installing Golem95...") 331 cmd.do_install('Golem95') 332 333 if dependency=='samurai': 334 raise MadGraph5Error, 'Samurai cannot yet be automatically installed.' 335 336 if dependency=='ninja': 337 if cmd.options['ninja'] in ['None',None,''] or\ 338 (cmd.options['ninja'] == './HEPTools/lib' and not MG5dir is None and\ 339 which_lib(pjoin(MG5dir,cmd.options['ninja'],'libninja.a')) is None): 340 tell("Installing ninja...") 341 cmd.do_install('ninja') 342 343 if dependency=='collier': 344 if cmd.options['collier'] in ['None',None,''] or\ 345 (cmd.options['collier'] == 'auto' and which_lib('libcollier.a') is None) or\ 346 which_lib(pjoin(cmd.options['collier'],'libcollier.a')) is None: 347 tell("Installing COLLIER...") 348 cmd.do_install('collier') 349
350 #=============================================================================== 351 # find a library 352 #=============================================================================== 353 -def which_lib(lib):
354 def is_lib(fpath): 355 return os.path.exists(fpath) and os.access(fpath, os.R_OK)
356 357 if not lib: 358 return None 359 360 fpath, fname = os.path.split(lib) 361 if fpath: 362 if is_lib(lib): 363 return lib 364 else: 365 locations = sum([os.environ[env_path].split(os.pathsep) for env_path in 366 ["DYLD_LIBRARY_PATH","LD_LIBRARY_PATH","LIBRARY_PATH","PATH"] 367 if env_path in os.environ],[]) 368 for path in locations: 369 lib_file = os.path.join(path, lib) 370 if is_lib(lib_file): 371 return lib_file 372 return None 373
374 #=============================================================================== 375 # Return Nice display for a random variable 376 #=============================================================================== 377 -def nice_representation(var, nb_space=0):
378 """ Return nice information on the current variable """ 379 380 #check which data to put: 381 info = [('type',type(var)),('str', var)] 382 if hasattr(var, 'func_doc'): 383 info.append( ('DOC', var.func_doc) ) 384 if hasattr(var, '__doc__'): 385 info.append( ('DOC', var.__doc__) ) 386 if hasattr(var, '__dict__'): 387 info.append( ('ATTRIBUTE', var.__dict__.keys() )) 388 389 spaces = ' ' * nb_space 390 391 outstr='' 392 for name, value in info: 393 outstr += '%s%3s : %s\n' % (spaces,name, value) 394 395 return outstr
396 397 # 398 # Decorator for re-running a crashing function automatically. 399 # 400 wait_once = False
401 -def multiple_try(nb_try=5, sleep=20):
402 403 def deco_retry(f): 404 def deco_f_retry(*args, **opt): 405 for i in range(nb_try): 406 try: 407 return f(*args, **opt) 408 except KeyboardInterrupt: 409 raise 410 except Exception, error: 411 global wait_once 412 if not wait_once: 413 text = """Start waiting for update. (more info in debug mode)""" 414 logger.info(text) 415 logger_stderr.debug('fail to do %s function with %s args. %s try on a max of %s (%s waiting time)' % 416 (str(f), ', '.join([str(a) for a in args]), i+1, nb_try, sleep * (i+1))) 417 logger_stderr.debug('error is %s' % str(error)) 418 if __debug__: logger_stderr.debug('and occurred at :'+traceback.format_exc()) 419 wait_once = True 420 time.sleep(sleep * (i+1)) 421 422 if __debug__: 423 raise 424 raise error.__class__, '[Fail %i times] \n %s ' % (i+1, error)
425 return deco_f_retry 426 return deco_retry 427
428 #=============================================================================== 429 # helper for scan. providing a nice formatted string for the scan name 430 #=============================================================================== 431 -def get_scan_name(first, last):
432 """return a name of the type xxxx[A-B]yyy 433 where xxx and yyy are the common part between the two names. 434 """ 435 436 # find the common string at the beginning 437 base = [first[i] for i in range(len(first)) if first[:i+1] == last[:i+1]] 438 # remove digit even if in common 439 while base and base[0].isdigit(): 440 base = base[1:] 441 # find the common string at the end 442 end = [first[-(i+1)] for i in range(len(first)) if first[-(i+1):] == last[-(i+1):]] 443 # remove digit even if in common 444 while end and end[-1].isdigit(): 445 end = end[:-1] 446 end.reverse() 447 #convert to string 448 base, end = ''.join(base), ''.join(end) 449 if end: 450 name = "%s[%s-%s]%s" % (base, first[len(base):-len(end)], last[len(base):-len(end)],end) 451 else: 452 name = "%s[%s-%s]%s" % (base, first[len(base):], last[len(base):],end) 453 return name
454
455 #=============================================================================== 456 # Compiler which returns smart output error in case of trouble 457 #=============================================================================== 458 -def compile(arg=[], cwd=None, mode='fortran', job_specs = True, nb_core=1 ,**opt):
459 """compile a given directory""" 460 461 if 'nocompile' in opt: 462 if opt['nocompile'] == True: 463 if not arg: 464 return 465 if cwd: 466 executable = pjoin(cwd, arg[0]) 467 else: 468 executable = arg[0] 469 if os.path.exists(executable): 470 return 471 del opt['nocompile'] 472 473 cmd = ['make'] 474 try: 475 if nb_core > 1: 476 cmd.append('-j%s' % nb_core) 477 cmd += arg 478 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, 479 stderr=subprocess.STDOUT, cwd=cwd, **opt) 480 (out, err) = p.communicate() 481 except OSError, error: 482 if cwd and not os.path.exists(cwd): 483 raise OSError, 'Directory %s doesn\'t exists. Impossible to run make' % cwd 484 else: 485 error_text = "Impossible to compile %s directory\n" % cwd 486 error_text += "Trying to launch make command returns:\n" 487 error_text += " " + str(error) + "\n" 488 error_text += "In general this means that your computer is not able to compile." 489 if sys.platform == "darwin": 490 error_text += "Note that MacOSX doesn\'t have gmake/gfortan install by default.\n" 491 error_text += "Xcode contains gmake. For gfortran we advise: http://hpc.sourceforge.net/" 492 raise MadGraph5Error, error_text 493 494 if p.returncode: 495 # Check that makefile exists 496 if not cwd: 497 cwd = os.getcwd() 498 all_file = [f.lower() for f in os.listdir(cwd)] 499 if 'makefile' not in all_file and '-f' not in arg: 500 raise OSError, 'no makefile present in %s' % os.path.realpath(cwd) 501 502 if mode == 'fortran' and not (which('g77') or which('gfortran')): 503 error_msg = 'A fortran compiler (g77 or gfortran) is required to create this output.\n' 504 error_msg += 'Please install g77 or gfortran on your computer and retry.' 505 raise MadGraph5Error, error_msg 506 elif mode == 'cpp' and not which('g++'): 507 error_msg ='A C++ compiler (g++) is required to create this output.\n' 508 error_msg += 'Please install g++ (which is part of the gcc package) on your computer and retry.' 509 raise MadGraph5Error, error_msg 510 511 # Check if this is due to the need of gfortran 4.6 for quadruple precision 512 if any(tag.upper() in out.upper() for tag in ['real(kind=16)','real*16', 513 'complex*32']) and mode == 'fortran' and not \ 514 ''.join(get_gfortran_version().split('.')) >= '46': 515 if not which('gfortran'): 516 raise MadGraph5Error, 'The fortran compiler gfortran v4.6 or later '+\ 517 'is required to compile %s.\nPlease install it and retry.'%cwd 518 else: 519 logger_stderr.error('ERROR, you could not compile %s because'%cwd+\ 520 ' your version of gfortran is older than 4.6. MadGraph5_aMC@NLO will carry on,'+\ 521 ' but will not be able to compile an executable.') 522 return p.returncode 523 # Other reason 524 error_text = 'A compilation Error occurs ' 525 if cwd: 526 error_text += 'when trying to compile %s.\n' % cwd 527 error_text += 'The compilation fails with the following output message:\n' 528 error_text += ' '+out.replace('\n','\n ')+'\n' 529 error_text += 'Please try to fix this compilations issue and retry.\n' 530 error_text += 'Help might be found at https://answers.launchpad.net/mg5amcnlo.\n' 531 error_text += 'If you think that this is a bug, you can report this at https://bugs.launchpad.net/mg5amcnlo' 532 raise MadGraph5Error, error_text 533 return p.returncode
534
535 -def get_gfortran_version(compiler='gfortran'):
536 """ Returns the gfortran version as a string. 537 Returns '0' if it failed.""" 538 try: 539 p = Popen([compiler, '-dumpversion'], stdout=subprocess.PIPE, 540 stderr=subprocess.PIPE) 541 output, error = p.communicate() 542 version_finder=re.compile(r"(?P<version>\d[\d.]*)") 543 version = version_finder.search(output).group('version') 544 return version 545 except Exception: 546 return '0'
547
548 -def mod_compilator(directory, new='gfortran', current=None, compiler_type='gfortran'):
549 #define global regular expression 550 if type(directory)!=list: 551 directory=[directory] 552 553 #search file 554 file_to_change=find_makefile_in_dir(directory) 555 if compiler_type == 'gfortran': 556 comp_re = re.compile('^(\s*)FC\s*=\s*(.+)\s*$') 557 var = 'FC' 558 elif compiler_type == 'cpp': 559 comp_re = re.compile('^(\s*)CXX\s*=\s*(.+)\s*$') 560 var = 'CXX' 561 else: 562 MadGraph5Error, 'Unknown compiler type: %s' % compiler_type 563 564 mod = False 565 for name in file_to_change: 566 lines = open(name,'r').read().split('\n') 567 for iline, line in enumerate(lines): 568 result = comp_re.match(line) 569 if result: 570 if new != result.group(2) and '$' not in result.group(2): 571 mod = True 572 lines[iline] = result.group(1) + var + "=" + new 573 elif compiler_type == 'gfortran' and line.startswith('DEFAULT_F_COMPILER'): 574 lines[iline] = "DEFAULT_F_COMPILER = %s" % new 575 elif compiler_type == 'cpp' and line.startswith('DEFAULT_CPP_COMPILER'): 576 lines[iline] = "DEFAULT_CPP_COMPILER = %s" % new 577 578 if mod: 579 open(name,'w').write('\n'.join(lines)) 580 # reset it to change the next file 581 mod = False
582
583 -def pid_exists(pid):
584 """Check whether pid exists in the current process table. 585 UNIX only. 586 https://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid-in-python 587 """ 588 import errno 589 590 if pid < 0: 591 return False 592 if pid == 0: 593 # According to "man 2 kill" PID 0 refers to every process 594 # in the process group of the calling process. 595 # On certain systems 0 is a valid PID but we have no way 596 # to know that in a portable fashion. 597 raise ValueError('invalid PID 0') 598 try: 599 os.kill(pid, 0) 600 except OSError as err: 601 if err.errno == errno.ESRCH: 602 # ESRCH == No such process 603 return False 604 elif err.errno == errno.EPERM: 605 # EPERM clearly means there's a process to deny access to 606 return True 607 else: 608 # According to "man 2 kill" possible error values are 609 # (EINVAL, EPERM, ESRCH) 610 raise 611 else: 612 return True
613
614 615 616 #=============================================================================== 617 # mute_logger (designed to work as with statement) 618 #=============================================================================== 619 -class MuteLogger(object):
620 """mute_logger (designed to work as with statement), 621 files allow to redirect the output of the log to a given file. 622 """ 623
624 - def __init__(self, names, levels, files=None, **opt):
625 assert isinstance(names, list) 626 assert isinstance(names, list) 627 628 self.names = names 629 self.levels = levels 630 if isinstance(files, list): 631 self.files = files 632 else: 633 self.files = [files] * len(names) 634 self.logger_saved_info = {} 635 self.opts = opt
636
637 - def __enter__(self):
638 old_levels = [] 639 for name, level, path in zip(self.names, self.levels, self.files): 640 if path: 641 self.setup_logFile_for_logger(path, name, **self.opts) 642 log_module = logging.getLogger(name) 643 old_levels.append(log_module.level) 644 log_module = logging.getLogger(name) 645 log_module.setLevel(level) 646 self.levels = old_levels
647
648 - def __exit__(self, ctype, value, traceback ):
649 for name, level, path in zip(self.names, self.levels, self.files): 650 651 if path: 652 if 'keep' in self.opts and not self.opts['keep']: 653 self.restore_logFile_for_logger(name, level, path=path) 654 else: 655 self.restore_logFile_for_logger(name, level) 656 else: 657 log_module = logging.getLogger(name) 658 log_module.setLevel(level)
659
660 - def setup_logFile_for_logger(self, path, full_logname, **opts):
661 """ Setup the logger by redirecting them all to logfiles in tmp """ 662 663 logs = full_logname.split('.') 664 lognames = [ '.'.join(logs[:(len(logs)-i)]) for i in\ 665 range(len(full_logname.split('.')))] 666 for logname in lognames: 667 try: 668 os.remove(path) 669 except Exception, error: 670 pass 671 my_logger = logging.getLogger(logname) 672 hdlr = logging.FileHandler(path) 673 # I assume below that the orders of the handlers in my_logger.handlers 674 # remains the same after having added/removed the FileHandler 675 self.logger_saved_info[logname] = [hdlr, my_logger.handlers] 676 #for h in my_logger.handlers: 677 # h.setLevel(logging.CRITICAL) 678 for old_hdlr in list(my_logger.handlers): 679 my_logger.removeHandler(old_hdlr) 680 my_logger.addHandler(hdlr) 681 #my_logger.setLevel(level) 682 my_logger.debug('Log of %s' % logname)
683
684 - def restore_logFile_for_logger(self, full_logname, level, path=None, **opts):
685 """ Setup the logger by redirecting them all to logfiles in tmp """ 686 687 logs = full_logname.split('.') 688 lognames = [ '.'.join(logs[:(len(logs)-i)]) for i in\ 689 range(len(full_logname.split('.')))] 690 for logname in lognames: 691 if path: 692 try: 693 os.remove(path) 694 except Exception, error: 695 pass 696 my_logger = logging.getLogger(logname) 697 if logname in self.logger_saved_info: 698 my_logger.removeHandler(self.logger_saved_info[logname][0]) 699 for old_hdlr in self.logger_saved_info[logname][1]: 700 my_logger.addHandler(old_hdlr) 701 else: 702 my_logger.setLevel(level)
703 704 #for i, h in enumerate(my_logger.handlers): 705 # h.setLevel(cls.logger_saved_info[logname][2][i]) 706 707 nb_open =0
708 @contextlib.contextmanager 709 -def stdchannel_redirected(stdchannel, dest_filename):
710 """ 711 A context manager to temporarily redirect stdout or stderr 712 713 e.g.: 714 715 716 with stdchannel_redirected(sys.stderr, os.devnull): 717 if compiler.has_function('clock_gettime', libraries=['rt']): 718 libraries.append('rt') 719 """ 720 721 try: 722 oldstdchannel = os.dup(stdchannel.fileno()) 723 dest_file = open(dest_filename, 'w') 724 os.dup2(dest_file.fileno(), stdchannel.fileno()) 725 yield 726 finally: 727 if oldstdchannel is not None: 728 os.dup2(oldstdchannel, stdchannel.fileno()) 729 os.close(oldstdchannel) 730 if dest_file is not None: 731 dest_file.close()
732
733 -def get_open_fds():
734 ''' 735 return the number of open file descriptors for current process 736 737 .. warning: will only work on UNIX-like os-es. 738 ''' 739 import subprocess 740 import os 741 742 pid = os.getpid() 743 procs = subprocess.check_output( 744 [ "lsof", '-w', '-Ff', "-p", str( pid ) ] ) 745 nprocs = filter( 746 lambda s: s and s[ 0 ] == 'f' and s[1: ].isdigit(), 747 procs.split( '\n' ) ) 748 749 return nprocs
750
751 -def detect_if_cpp_compiler_is_clang(cpp_compiler):
752 """ Detects whether the specified C++ compiler is clang.""" 753 754 try: 755 p = Popen([cpp_compiler, '--version'], stdout=subprocess.PIPE, 756 stderr=subprocess.PIPE) 757 output, error = p.communicate() 758 except Exception, error: 759 # Cannot probe the compiler, assume not clang then 760 return False 761 return 'LLVM' in output or "clang" in output
762
763 -def detect_cpp_std_lib_dependence(cpp_compiler):
764 """ Detects if the specified c++ compiler will normally link against the C++ 765 standard library -lc++ or -libstdc++.""" 766 767 is_clang = detect_if_cpp_compiler_is_clang(cpp_compiler) 768 if is_clang: 769 try: 770 import platform 771 v, _,_ = platform.mac_ver() 772 if not v: 773 # We will not attempt to support clang elsewhere than on macs, so 774 # we venture a guess here. 775 return '-lc++' 776 else: 777 v = float(v.rsplit('.')[1]) 778 if v >= 9: 779 return '-lc++' 780 else: 781 return '-lstdc++' 782 except: 783 return '-lstdc++' 784 return '-lstdc++'
785
786 -def detect_current_compiler(path, compiler_type='fortran'):
787 """find the current compiler for the current directory""" 788 789 # comp = re.compile("^\s*FC\s*=\s*(\w+)\s*") 790 # The regular expression below allows for compiler definition with absolute path 791 if compiler_type == 'fortran': 792 comp = re.compile("^\s*FC\s*=\s*([\w\/\\.\-]+)\s*") 793 elif compiler_type == 'cpp': 794 comp = re.compile("^\s*CXX\s*=\s*([\w\/\\.\-]+)\s*") 795 else: 796 MadGraph5Error, 'Unknown compiler type: %s' % compiler_type 797 798 for line in open(path): 799 if comp.search(line): 800 compiler = comp.search(line).groups()[0] 801 return compiler 802 elif compiler_type == 'fortran' and line.startswith('DEFAULT_F_COMPILER'): 803 return line.split('=')[1].strip() 804 elif compiler_type == 'cpp' and line.startswith('DEFAULT_CPP_COMPILER'): 805 return line.split('=')[1].strip()
806
807 -def find_makefile_in_dir(directory):
808 """ return a list of all file starting with makefile in the given directory""" 809 810 out=[] 811 #list mode 812 if type(directory)==list: 813 for name in directory: 814 out+=find_makefile_in_dir(name) 815 return out 816 817 #single mode 818 for name in os.listdir(directory): 819 if os.path.isdir(directory+'/'+name): 820 out+=find_makefile_in_dir(directory+'/'+name) 821 elif os.path.isfile(directory+'/'+name) and name.lower().startswith('makefile'): 822 out.append(directory+'/'+name) 823 elif os.path.isfile(directory+'/'+name) and name.lower().startswith('make_opt'): 824 out.append(directory+'/'+name) 825 return out
826
827 -def rm_old_compile_file():
828 829 # remove all the .o files 830 os.path.walk('.', rm_file_extension, '.o') 831 832 # remove related libraries 833 libraries = ['libblocks.a', 'libgeneric_mw.a', 'libMWPS.a', 'libtools.a', 'libdhelas3.a', 834 'libdsample.a', 'libgeneric.a', 'libmodel.a', 'libpdf.a', 'libdhelas3.so', 'libTF.a', 835 'libdsample.so', 'libgeneric.so', 'libmodel.so', 'libpdf.so'] 836 lib_pos='./lib' 837 [os.remove(os.path.join(lib_pos, lib)) for lib in libraries \ 838 if os.path.exists(os.path.join(lib_pos, lib))]
839
840 841 -def format_time(n_secs):
842 m, s = divmod(n_secs, 60) 843 h, m = divmod(m, 60) 844 d, h = divmod(h, 24) 845 if d > 0: 846 return "%d day%s,%dh%02dm%02ds" % (d,'' if d<=1 else 's',h, m, s) 847 elif h > 0: 848 return "%dh%02dm%02ds" % (h, m, s) 849 elif m > 0: 850 return "%dm%02ds" % (m, s) 851 else: 852 return "%d second%s" % (s, '' if s<=1 else 's')
853
854 -def rm_file_extension( ext, dirname, names):
855 856 [os.remove(os.path.join(dirname, name)) for name in names if name.endswith(ext)]
857
858 859 860 -def multiple_replacer(*key_values):
861 replace_dict = dict(key_values) 862 replacement_function = lambda match: replace_dict[match.group(0)] 863 pattern = re.compile("|".join([re.escape(k) for k, v in key_values]), re.M) 864 return lambda string: pattern.sub(replacement_function, string)
865
866 -def multiple_replace(string, *key_values):
867 return multiple_replacer(*key_values)(string)
868
869 # Control 870 -def check_system_error(value=1):
871 def deco_check(f): 872 def deco_f(arg, *args, **opt): 873 try: 874 return f(arg, *args, **opt) 875 except OSError, error: 876 logger.debug('try to recover from %s' % error) 877 if isinstance(arg, (list,tuple)): 878 prog = arg[0] 879 else: 880 prog = arg 881 882 # Permission denied 883 if error.errno == 13: 884 if os.path.exists(prog): 885 os.system('chmod +x %s' % prog) 886 elif 'cwd' in opt and opt['cwd'] and \ 887 os.path.isfile(pjoin(opt['cwd'],arg[0])): 888 os.system('chmod +x %s' % pjoin(opt['cwd'],arg[0])) 889 return f(arg, *args, **opt) 890 # NO such file or directory 891 elif error.errno == 2: 892 # raise a more meaningfull error message 893 raise Exception, '%s fails with no such file or directory' \ 894 % arg 895 else: 896 raise
897 return deco_f 898 return deco_check 899
900 901 @check_system_error() 902 -def call(arg, *args, **opt):
903 """nice way to call an external program with nice error treatment""" 904 try: 905 return subprocess.call(arg, *args, **opt) 906 except OSError: 907 arg[0] = './%s' % arg[0] 908 return subprocess.call(arg, *args, **opt)
909
910 @check_system_error() 911 -def Popen(arg, *args, **opt):
912 """nice way to call an external program with nice error treatment""" 913 return subprocess.Popen(arg, *args, **opt)
914
915 @check_system_error() 916 -def call_stdout(arg, *args, **opt):
917 """nice way to call an external program with nice error treatment""" 918 try: 919 out = subprocess.Popen(arg, *args, stdout=subprocess.PIPE, **opt) 920 except OSError: 921 arg[0] = './%s' % arg[0] 922 out = subprocess.call(arg, *args, stdout=subprocess.PIPE, **opt) 923 924 str_out = out.stdout.read().strip() 925 return str_out
926
927 928 @multiple_try() 929 -def mult_try_open(filepath, *args, **opt):
930 """try to open a file with multiple try to ensure that filesystem is sync""" 931 return open(filepath, *args, ** opt)
932
933 ################################################################################ 934 # TAIL FUNCTION 935 ################################################################################ 936 -def tail(f, n, offset=None):
937 """Reads a n lines from f with an offset of offset lines. The return 938 value is a tuple in the form ``lines``. 939 """ 940 avg_line_length = 74 941 to_read = n + (offset or 0) 942 943 while 1: 944 try: 945 f.seek(-(avg_line_length * to_read), 2) 946 except IOError: 947 # woops. apparently file is smaller than what we want 948 # to step back, go to the beginning instead 949 f.seek(0) 950 pos = f.tell() 951 lines = f.read().splitlines() 952 if len(lines) >= to_read or pos == 0: 953 return lines[-to_read:offset and -offset or None] 954 avg_line_length *= 1.3 955 avg_line_length = int(avg_line_length)
956
957 -def mkfifo(fifo_path):
958 """ makes a piping fifo (First-in First-out) file and nicely intercepts 959 error in case the file format of the target drive doesn't suppor tit.""" 960 961 try: 962 os.mkfifo(fifo_path) 963 except: 964 raise OSError('MadGraph5_aMCatNLO could not create a fifo file at:\n'+ 965 ' %s\n'%fifo_path+'Make sure that this file does not exist already'+ 966 ' and that the file format of the target drive supports fifo file (i.e not NFS).')
967
968 ################################################################################ 969 # LAST LINE FUNCTION 970 ################################################################################ 971 -def get_last_line(fsock):
972 """return the last line of a file""" 973 974 return tail(fsock, 1)[0]
975
976 -class BackRead(file):
977 """read a file returning the lines in reverse order for each call of readline() 978 This actually just reads blocks (4096 bytes by default) of data from the end of 979 the file and returns last line in an internal buffer.""" 980 981
982 - def readline(self):
983 """ readline in a backward way """ 984 985 while len(self.data) == 1 and ((self.blkcount * self.blksize) < self.size): 986 self.blkcount = self.blkcount + 1 987 line = self.data[0] 988 try: 989 self.seek(-self.blksize * self.blkcount, 2) # read from end of file 990 self.data = (self.read(self.blksize) + line).split('\n') 991 except IOError: # can't seek before the beginning of the file 992 self.seek(0) 993 data = self.read(self.size - (self.blksize * (self.blkcount-1))) + line 994 self.data = data.split('\n') 995 996 if len(self.data) == 0: 997 return "" 998 999 line = self.data.pop() 1000 return line + '\n'
1001
1002 - def __init__(self, filepos, blksize=4096):
1003 """initialize the internal structures""" 1004 1005 # get the file size 1006 self.size = os.stat(filepos)[6] 1007 # how big of a block to read from the file... 1008 self.blksize = blksize 1009 # how many blocks we've read 1010 self.blkcount = 1 1011 file.__init__(self, filepos, 'rb') 1012 # if the file is smaller than the blocksize, read a block, 1013 # otherwise, read the whole thing... 1014 if self.size > self.blksize: 1015 self.seek(-self.blksize * self.blkcount, 2) # read from end of file 1016 self.data = self.read(self.blksize).split('\n') 1017 # strip the last item if it's empty... a byproduct of the last line having 1018 # a newline at the end of it 1019 if not self.data[-1]: 1020 self.data.pop()
1021
1022 - def next(self):
1023 line = self.readline() 1024 if line: 1025 return line 1026 else: 1027 raise StopIteration
1028
1029 1030 -def write_PS_input(filePath, PS):
1031 """ Write out in file filePath the PS point to be read by the MadLoop.""" 1032 try: 1033 PSfile = open(filePath, 'w') 1034 # Add a newline in the end as the implementation fortran 'read' 1035 # command on some OS is problematic if it ends directly with the 1036 # floating point number read. 1037 1038 PSfile.write('\n'.join([' '.join(['%.16E'%pi for pi in p]) \ 1039 for p in PS])+'\n') 1040 PSfile.close() 1041 except Exception: 1042 raise MadGraph5Error, 'Could not write out the PS point to file %s.'\ 1043 %str(filePath)
1044
1045 -def format_timer(running_time):
1046 """ return a nicely string representing the time elapsed.""" 1047 if running_time < 2e-2: 1048 running_time = running_time = 'current time: %02dh%02d' % (time.localtime().tm_hour, time.localtime().tm_min) 1049 elif running_time < 10: 1050 running_time = ' %.2gs ' % running_time 1051 elif 60 > running_time >= 10: 1052 running_time = ' %.3gs ' % running_time 1053 elif 3600 > running_time >= 60: 1054 running_time = ' %im %is ' % (running_time // 60, int(running_time % 60)) 1055 else: 1056 running_time = ' %ih %im ' % (running_time // 3600, (running_time//60 % 60)) 1057 return running_time
1058
1059 1060 #=============================================================================== 1061 # TMP_directory (designed to work as with statement) 1062 #=============================================================================== 1063 -class TMP_directory(object):
1064 """create a temporary directory and ensure this one to be cleaned. 1065 """ 1066
1067 - def __init__(self, suffix='', prefix='tmp', dir=None):
1068 self.nb_try_remove = 0 1069 import tempfile 1070 self.path = tempfile.mkdtemp(suffix, prefix, dir)
1071 1072
1073 - def __exit__(self, ctype, value, traceback ):
1074 #True only for debugging: 1075 if False and isinstance(value, Exception): 1076 sprint("Directory %s not cleaned. This directory can be removed manually" % self.path) 1077 return False 1078 try: 1079 shutil.rmtree(self.path) 1080 except OSError: 1081 self.nb_try_remove += 1 1082 if self.nb_try_remove < 3: 1083 time.sleep(10) 1084 self.__exit__(ctype, value, traceback) 1085 else: 1086 logger.warning("Directory %s not completely cleaned. This directory can be removed manually" % self.path)
1087
1088 - def __enter__(self):
1089 return self.path
1090
1091 -class TMP_variable(object):
1092 """replace an attribute of a class with another value for the time of the 1093 context manager 1094 """ 1095
1096 - def __init__(self, cls, attribute, value):
1097 1098 self.cls = cls 1099 self.attribute = attribute 1100 if isinstance(attribute, list): 1101 self.old_value = [] 1102 for key, onevalue in zip(attribute, value): 1103 self.old_value.append(getattr(cls, key)) 1104 setattr(self.cls, key, onevalue) 1105 else: 1106 self.old_value = getattr(cls, attribute) 1107 setattr(self.cls, self.attribute, value)
1108
1109 - def __exit__(self, ctype, value, traceback ):
1110 1111 if isinstance(self.attribute, list): 1112 for key, old_value in zip(self.attribute, self.old_value): 1113 setattr(self.cls, key, old_value) 1114 else: 1115 setattr(self.cls, self.attribute, self.old_value)
1116
1117 - def __enter__(self):
1118 return self.old_value
1119
1120 # 1121 # GUNZIP/GZIP 1122 # 1123 -def gunzip(path, keep=False, stdout=None):
1124 """ a standard replacement for os.system('gunzip -f %s.gz ' % event_path)""" 1125 1126 if not path.endswith(".gz"): 1127 if os.path.exists("%s.gz" % path): 1128 path = "%s.gz" % path 1129 else: 1130 raise Exception, "%(path)s does not finish by .gz and the file %(path)s.gz does not exists" %\ 1131 {"path": path} 1132 1133 1134 #for large file (>1G) it is faster and safer to use a separate thread 1135 if os.path.getsize(path) > 1e8: 1136 if stdout: 1137 os.system('gunzip -c %s > %s' % (path, stdout)) 1138 else: 1139 os.system('gunzip %s' % path) 1140 return 0 1141 1142 if not stdout: 1143 stdout = path[:-3] 1144 try: 1145 gfile = ziplib.open(path, "r") 1146 except IOError: 1147 raise 1148 else: 1149 try: 1150 open(stdout,'w').write(gfile.read()) 1151 except IOError: 1152 # this means that the file is actually not gzip 1153 if stdout == path: 1154 return 1155 else: 1156 files.cp(path, stdout) 1157 1158 if not keep: 1159 os.remove(path) 1160 return 0
1161
1162 -def gzip(path, stdout=None, error=True, forceexternal=False):
1163 """ a standard replacement for os.system('gzip %s ' % path)""" 1164 1165 #for large file (>1G) it is faster and safer to use a separate thread 1166 if os.path.getsize(path) > 1e9 or forceexternal: 1167 call(['gzip', '-f', path]) 1168 if stdout: 1169 if not stdout.endswith(".gz"): 1170 stdout = "%s.gz" % stdout 1171 shutil.move('%s.gz' % path, stdout) 1172 return 1173 1174 if not stdout: 1175 stdout = "%s.gz" % path 1176 elif not stdout.endswith(".gz"): 1177 stdout = "%s.gz" % stdout 1178 1179 try: 1180 ziplib.open(stdout,"w").write(open(path).read()) 1181 except OverflowError: 1182 gzip(path, stdout, error=error, forceexternal=True) 1183 except Exception: 1184 if error: 1185 raise 1186 else: 1187 os.remove(path)
1188
1189 # 1190 # Global function to open supported file types 1191 # 1192 -class open_file(object):
1193 """ a convinient class to open a file """ 1194 1195 web_browser = None 1196 eps_viewer = None 1197 text_editor = None 1198 configured = False 1199
1200 - def __init__(self, filename):
1201 """open a file""" 1202 1203 # Check that the class is correctly configure 1204 if not self.configured: 1205 self.configure() 1206 1207 try: 1208 extension = filename.rsplit('.',1)[1] 1209 except IndexError: 1210 extension = '' 1211 1212 1213 # dispatch method 1214 if extension in ['html','htm','php']: 1215 self.open_program(self.web_browser, filename, background=True) 1216 elif extension in ['ps','eps']: 1217 self.open_program(self.eps_viewer, filename, background=True) 1218 else: 1219 self.open_program(self.text_editor,filename, mac_check=False)
1220 # mac_check to False avoid to use open cmd in mac 1221 1222 @classmethod
1223 - def configure(cls, configuration=None):
1224 """ configure the way to open the file """ 1225 1226 cls.configured = True 1227 1228 # start like this is a configuration for mac 1229 cls.configure_mac(configuration) 1230 if sys.platform == 'darwin': 1231 return # done for MAC 1232 1233 # on Mac some default (eps/web) might be kept on None. This is not 1234 #suitable for LINUX which doesn't have open command. 1235 1236 # first for eps_viewer 1237 if not cls.eps_viewer: 1238 cls.eps_viewer = cls.find_valid(['evince','gv', 'ggv'], 'eps viewer') 1239 1240 # Second for web browser 1241 if not cls.web_browser: 1242 cls.web_browser = cls.find_valid( 1243 ['firefox', 'chrome', 'safari','opera'], 1244 'web browser')
1245 1246 @classmethod
1247 - def configure_mac(cls, configuration=None):
1248 """ configure the way to open a file for mac """ 1249 1250 if configuration is None: 1251 configuration = {'text_editor': None, 1252 'eps_viewer':None, 1253 'web_browser':None} 1254 1255 for key in configuration: 1256 if key == 'text_editor': 1257 # Treat text editor ONLY text base editor !! 1258 if configuration[key]: 1259 program = configuration[key].split()[0] 1260 if not which(program): 1261 logger.warning('Specified text editor %s not valid.' % \ 1262 configuration[key]) 1263 else: 1264 # All is good 1265 cls.text_editor = configuration[key] 1266 continue 1267 #Need to find a valid default 1268 if os.environ.has_key('EDITOR'): 1269 cls.text_editor = os.environ['EDITOR'] 1270 else: 1271 cls.text_editor = cls.find_valid( 1272 ['vi', 'emacs', 'vim', 'gedit', 'nano'], 1273 'text editor') 1274 1275 elif key == 'eps_viewer': 1276 if configuration[key]: 1277 cls.eps_viewer = configuration[key] 1278 continue 1279 # else keep None. For Mac this will use the open command. 1280 elif key == 'web_browser': 1281 if configuration[key]: 1282 cls.web_browser = configuration[key] 1283 continue
1284 # else keep None. For Mac this will use the open command. 1285 1286 @staticmethod
1287 - def find_valid(possibility, program='program'):
1288 """find a valid shell program in the list""" 1289 1290 for p in possibility: 1291 if which(p): 1292 logger.info('Using default %s \"%s\". ' % (program, p) + \ 1293 'Set another one in ./input/mg5_configuration.txt') 1294 return p 1295 1296 logger.info('No valid %s found. ' % program + \ 1297 'Please set in ./input/mg5_configuration.txt') 1298 return None
1299 1300
1301 - def open_program(self, program, file_path, mac_check=True, background=False):
1302 """ open a file with a given program """ 1303 1304 if mac_check==True and sys.platform == 'darwin': 1305 return self.open_mac_program(program, file_path) 1306 1307 # Shell program only 1308 if program: 1309 arguments = program.split() # allow argument in program definition 1310 arguments.append(file_path) 1311 1312 if not background: 1313 subprocess.call(arguments) 1314 else: 1315 import thread 1316 thread.start_new_thread(subprocess.call,(arguments,)) 1317 else: 1318 logger.warning('Not able to open file %s since no program configured.' % file_path + \ 1319 'Please set one in ./input/mg5_configuration.txt')
1320
1321 - def open_mac_program(self, program, file_path):
1322 """ open a text with the text editor """ 1323 1324 if not program: 1325 # Ask to mac manager 1326 os.system('open %s' % file_path) 1327 elif which(program): 1328 # shell program 1329 arguments = program.split() # Allow argument in program definition 1330 arguments.append(file_path) 1331 subprocess.call(arguments) 1332 else: 1333 # not shell program 1334 os.system('open -a %s %s' % (program, file_path))
1335
1336 -def get_HEPTools_location_setter(HEPToolsDir,type):
1337 """ Checks whether mg5dir/HEPTools/<type> (which is 'lib', 'bin' or 'include') 1338 is in the environment paths of the user. If not, it returns a preamble that 1339 sets it before calling the exectuable, for example: 1340 <preamble> ./my_exe 1341 with <preamble> -> DYLD_LIBRARY_PATH=blabla:$DYLD_LIBRARY_PATH""" 1342 1343 assert(type in ['bin','include','lib']) 1344 1345 target_env_var = 'PATH' if type in ['bin','include'] else \ 1346 ('DYLD_LIBRARY_PATH' if sys.platform=='darwin' else 'LD_LIBRARY_PATH') 1347 1348 target_path = os.path.abspath(pjoin(HEPToolsDir,type)) 1349 1350 if target_env_var not in os.environ or \ 1351 target_path not in os.environ[target_env_var].split(os.pathsep): 1352 return "%s=%s:$%s "%(target_env_var,target_path,target_env_var) 1353 else: 1354 return ''
1355
1356 -def get_shell_type():
1357 """ Try and guess what shell type does the user use.""" 1358 try: 1359 if os.environ['SHELL'].endswith('bash'): 1360 return 'bash' 1361 elif os.environ['SHELL'].endswith('tcsh'): 1362 return 'tcsh' 1363 else: 1364 # If unknown, return None 1365 return None 1366 except KeyError: 1367 return None
1368
1369 -def is_executable(path):
1370 """ check if a path is executable""" 1371 try: 1372 return os.access(path, os.X_OK) 1373 except Exception: 1374 return False
1375
1376 -class OptionParser(optparse.OptionParser):
1377 """Option Peaser which raise an error instead as calling exit""" 1378
1379 - def exit(self, status=0, msg=None):
1380 if msg: 1381 raise InvalidCmd, msg 1382 else: 1383 raise InvalidCmd
1384
1385 -def sprint(*args, **opt):
1386 """Returns the current line number in our program.""" 1387 1388 if not __debug__: 1389 return 1390 1391 1392 import inspect 1393 if opt.has_key('cond') and not opt['cond']: 1394 return 1395 1396 use_print = False 1397 if opt.has_key('use_print') and opt['use_print']: 1398 use_print = True 1399 1400 if opt.has_key('log'): 1401 log = opt['log'] 1402 else: 1403 log = logging.getLogger('madgraph') 1404 if opt.has_key('level'): 1405 level = opt['level'] 1406 else: 1407 level = logging.getLogger('madgraph').level 1408 if level == 0: 1409 use_print = True 1410 #print "madgraph level",level 1411 #if level == 20: 1412 # level = 10 #avoid info level 1413 #print "use", level 1414 if opt.has_key('wait'): 1415 wait = bool(opt['wait']) 1416 else: 1417 wait = False 1418 1419 lineno = inspect.currentframe().f_back.f_lineno 1420 fargs = inspect.getframeinfo(inspect.currentframe().f_back) 1421 filename, lineno = fargs[:2] 1422 #file = inspect.currentframe().f_back.co_filename 1423 #print type(file) 1424 try: 1425 source = inspect.getsourcelines(inspect.currentframe().f_back) 1426 line = source[0][lineno-source[1]] 1427 line = re.findall(r"misc\.sprint\(\s*(.*)\)\s*($|#)", line)[0][0] 1428 if line.startswith("'") and line.endswith("'") and line.count(",") ==0: 1429 line= '' 1430 elif line.startswith("\"") and line.endswith("\"") and line.count(",") ==0: 1431 line= '' 1432 elif line.startswith(("\"","'")) and len(args)==1 and "%" in line: 1433 line= '' 1434 except Exception: 1435 line='' 1436 1437 if line: 1438 intro = ' %s = \033[0m' % line 1439 else: 1440 intro = '' 1441 1442 1443 if not use_print: 1444 log.log(level, ' '.join([intro]+[str(a) for a in args]) + \ 1445 ' \033[1;30m[%s at line %s]\033[0m' % (os.path.basename(filename), lineno)) 1446 else: 1447 print ' '.join([intro]+[str(a) for a in args]) + \ 1448 ' \033[1;30m[%s at line %s]\033[0m' % (os.path.basename(filename), lineno) 1449 1450 if wait: 1451 raw_input('press_enter to continue') 1452 elif opt.has_key('sleep'): 1453 time.sleep(int(opt['sleep'])) 1454 1455 return
1456
1457 ################################################################################ 1458 # function to check if two float are approximatively equal 1459 ################################################################################ 1460 -def equal(a,b,sig_fig=6, zero_limit=True):
1461 """function to check if two float are approximatively equal""" 1462 import math 1463 1464 if isinstance(sig_fig, int): 1465 if not a or not b: 1466 if zero_limit: 1467 if zero_limit is not True: 1468 power = zero_limit 1469 else: 1470 power = sig_fig + 1 1471 else: 1472 return a == b 1473 else: 1474 power = sig_fig - int(math.log10(abs(a))) 1475 1476 return ( a==b or abs(int(a*10**power) - int(b*10**power)) < 10) 1477 else: 1478 return abs(a-b) < sig_fig
1479
1480 ################################################################################ 1481 # class to change directory with the "with statement" 1482 # Exemple: 1483 # with chdir(path) as path: 1484 # pass 1485 ################################################################################ 1486 -class chdir:
1487 - def __init__(self, newPath):
1488 self.newPath = newPath
1489
1490 - def __enter__(self):
1491 self.savedPath = os.getcwd() 1492 os.chdir(self.newPath)
1493
1494 - def __exit__(self, etype, value, traceback):
1495 os.chdir(self.savedPath)
1496
1497 ################################################################################ 1498 # Timeout FUNCTION 1499 ################################################################################ 1500 1501 -def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):
1502 '''This function will spwan a thread and run the given function using the args, kwargs and 1503 return the given default value if the timeout_duration is exceeded 1504 ''' 1505 import threading 1506 class InterruptableThread(threading.Thread): 1507 def __init__(self): 1508 threading.Thread.__init__(self) 1509 self.result = default
1510 def run(self): 1511 try: 1512 self.result = func(*args, **kwargs) 1513 except Exception,error: 1514 print error 1515 self.result = default 1516 it = InterruptableThread() 1517 it.start() 1518 it.join(timeout_duration) 1519 return it.result 1520
1521 1522 ################################################################################ 1523 # TAIL FUNCTION 1524 ################################################################################ 1525 -class digest:
1526
1527 - def test_all(self):
1528 try: 1529 return self.test_hashlib() 1530 except Exception: 1531 pass 1532 try: 1533 return self.test_md5() 1534 except Exception: 1535 pass 1536 try: 1537 return self.test_zlib() 1538 except Exception: 1539 pass
1540
1541 - def test_hashlib(self):
1542 import hashlib 1543 def digest(text): 1544 """using mg5 for the hash""" 1545 t = hashlib.md5() 1546 t.update(text) 1547 return t.hexdigest()
1548 return digest
1549
1550 - def test_md5(self):
1551 import md5 1552 def digest(text): 1553 """using mg5 for the hash""" 1554 t = md5.md5() 1555 t.update(text) 1556 return t.hexdigest()
1557 return digest 1558
1559 - def test_zlib(self):
1560 import zlib 1561 def digest(text): 1562 return zlib.adler32(text)
1563 1564 digest = digest().test_all()
1565 1566 #=============================================================================== 1567 # Helper class for timing and RAM flashing of subprocesses. 1568 #=============================================================================== 1569 -class ProcessTimer:
1570 - def __init__(self,*args,**opts):
1571 self.cmd_args = args 1572 self.cmd_opts = opts 1573 self.execution_state = False
1574
1575 - def execute(self):
1576 self.max_vms_memory = 0 1577 self.max_rss_memory = 0 1578 1579 self.t1 = None 1580 self.t0 = time.time() 1581 self.p = subprocess.Popen(*self.cmd_args,**self.cmd_opts) 1582 self.execution_state = True
1583
1584 - def poll(self):
1585 if not self.check_execution_state(): 1586 return False 1587 1588 self.t1 = time.time() 1589 # I redirect stderr to void, because from MacOX snow leopard onward, this 1590 # ps -p command writes a million times the following stupid warning 1591 # dyld: DYLD_ environment variables being ignored because main executable (/bin/ps) is setuid or setgid 1592 flash = subprocess.Popen("ps -p %i -o rss"%self.p.pid, 1593 shell=True,stdout=subprocess.PIPE,stderr=open(os.devnull,"w")) 1594 stdout_list = flash.communicate()[0].split('\n') 1595 rss_memory = int(stdout_list[1]) 1596 # for now we ignore vms 1597 vms_memory = 0 1598 1599 # This is the neat version using psutil 1600 # try: 1601 # pp = psutil.Process(self.p.pid) 1602 # 1603 # # obtain a list of the subprocess and all its descendants 1604 # descendants = list(pp.get_children(recursive=True)) 1605 # descendants = descendants + [pp] 1606 # 1607 # rss_memory = 0 1608 # vms_memory = 0 1609 # 1610 # # calculate and sum up the memory of the subprocess and all its descendants 1611 # for descendant in descendants: 1612 # try: 1613 # mem_info = descendant.get_memory_info() 1614 # 1615 # rss_memory += mem_info[0] 1616 # vms_memory += mem_info[1] 1617 # except psutil.error.NoSuchProcess: 1618 # # sometimes a subprocess descendant will have terminated between the time 1619 # # we obtain a list of descendants, and the time we actually poll this 1620 # # descendant's memory usage. 1621 # pass 1622 # 1623 # except psutil.error.NoSuchProcess: 1624 # return self.check_execution_state() 1625 1626 self.max_vms_memory = max(self.max_vms_memory,vms_memory) 1627 self.max_rss_memory = max(self.max_rss_memory,rss_memory) 1628 1629 return self.check_execution_state()
1630
1631 - def is_running(self):
1632 # Version with psutil 1633 # return psutil.pid_exists(self.p.pid) and self.p.poll() == None 1634 return self.p.poll() == None
1635
1636 - def check_execution_state(self):
1637 if not self.execution_state: 1638 return False 1639 if self.is_running(): 1640 return True 1641 self.executation_state = False 1642 self.t1 = time.time() 1643 return False
1644
1645 - def close(self,kill=False):
1646 1647 if self.p.poll() == None: 1648 if kill: 1649 self.p.kill() 1650 else: 1651 self.p.terminate()
1652
1653 # Again a neater handling with psutil 1654 # try: 1655 # pp = psutil.Process(self.p.pid) 1656 # if kill: 1657 # pp.kill() 1658 # else: 1659 # pp.terminate() 1660 # except psutil.error.NoSuchProcess: 1661 # pass 1662 1663 ## Define apple_notify (in a way which is system independent 1664 -class Applenotification(object):
1665
1666 - def __init__(self):
1667 self.init = False 1668 self.working = True
1669
1670 - def load_notification(self):
1671 try: 1672 import Foundation 1673 import objc 1674 self.NSUserNotification = objc.lookUpClass('NSUserNotification') 1675 self.NSUserNotificationCenter = objc.lookUpClass('NSUserNotificationCenter') 1676 except: 1677 self.working=False 1678 self.working=True
1679
1680 - def __call__(self,subtitle, info_text, userInfo={}):
1681 1682 if not self.init: 1683 self.load_notification() 1684 if not self.working: 1685 return 1686 try: 1687 notification = self.NSUserNotification.alloc().init() 1688 notification.setTitle_('MadGraph5_aMC@NLO') 1689 notification.setSubtitle_(subtitle) 1690 notification.setInformativeText_(info_text) 1691 try: 1692 notification.setUserInfo_(userInfo) 1693 except: 1694 pass 1695 self.NSUserNotificationCenter.defaultUserNotificationCenter().scheduleNotification_(notification) 1696 except: 1697 pass
1698 1699 1700 1701 apple_notify = Applenotification()
1702 1703 -class EasterEgg(object):
1704 1705 done_notification = False 1706 message_aprilfirst =\ 1707 {'error': ['Be careful, a cat is eating a lot of fish today. This makes the code unstable.', 1708 'Really, this sounds fishy.', 1709 'A Higgs boson walks into a church. The priest says "We don\'t allow Higgs bosons in here." The Higgs boson replies, "But without me, how can you have mass?"', 1710 "Why does Heisenberg detest driving cars? Because, every time he looks at the speedometer he gets lost!", 1711 "May the mass times acceleration be with you.", 1712 "NOTE: This product may actually be nine-dimensional. If this is the case, functionality is not affected by the extra five dimensions.", 1713 "IMPORTANT: This product is composed of 100%% matter: It is the responsibility of the User to make sure that it does not come in contact with antimatter.", 1714 "", 1715 'The fish are out of jokes. See you next year for more!'], 1716 # 'loading': ['Hi %(user)s, You are Loading Madgraph. Please be patient, we are doing the work.'], 1717 # 'quit': ['Thanks %(user)s for using MadGraph5_aMC@NLO, even on April 1st!'] 1718 } 1719 1720 default_banner_1 = "************************************************************\n" + \ 1721 "* *\n" + \ 1722 "* W E L C O M E to *\n" + \ 1723 "* M A D G R A P H 5 _ a M C @ N L O *\n" + \ 1724 "* *\n" + \ 1725 "* *\n" 1726 1727 1728 default_banner_2 = "* *\n" + \ 1729 "%s" + \ 1730 "* *\n" + \ 1731 "* The MadGraph5_aMC@NLO Development Team - Find us at *\n" + \ 1732 "* https://server06.fynu.ucl.ac.be/projects/madgraph *\n" + \ 1733 "* and *\n" + \ 1734 "* http://amcatnlo.web.cern.ch/amcatnlo/ *\n" + \ 1735 "* *\n" + \ 1736 "* Type 'help' for in-line help. *\n" + \ 1737 "* Type 'tutorial' to learn how MG5 works *\n" + \ 1738 "* Type 'tutorial aMCatNLO' to learn how aMC@NLO works *\n" + \ 1739 "* Type 'tutorial MadLoop' to learn how MadLoop works *\n" + \ 1740 "* *\n" + \ 1741 "************************************************************" 1742 1743 May4_banner = "* _____ *\n" + \ 1744 "* ,-~\" \"~-. *\n" + \ 1745 "* * ,^ ___ ^. * *\n" + \ 1746 "* * / .^ ^. \ * *\n" + \ 1747 "* * Y l o ! Y * *\n" + \ 1748 "* * l_ `.___.' _,[ * *\n" + \ 1749 "* * |^~\"--------------~\"\"^| * *\n" + \ 1750 "* * ! May the 4th ! * *\n" + \ 1751 "* * \ / * *\n" + \ 1752 "* * ^. .^ * *\n" + \ 1753 "* * \"-.._____.,-\" * *\n" 1754 1755 special_banner = {(4,5): May4_banner} 1756 1757
1758 - def __init__(self, msgtype):
1759 1760 try: 1761 now = time.localtime() 1762 date = now.tm_mday, now.tm_mon 1763 if date in [(1,4)]: 1764 madgraph.iolibs.drawing_eps.EpsDiagramDrawer.april_fool = True 1765 if msgtype in EasterEgg.message_aprilfirst: 1766 choices = EasterEgg.message_aprilfirst[msgtype] 1767 if len(choices) == 0: 1768 return 1769 elif len(choices) == 1: 1770 msg = choices[0] 1771 else: 1772 import random 1773 msg = choices[random.randint(0,len(choices)-2)] 1774 EasterEgg.message_aprilfirst[msgtype].remove(msg) 1775 else: 1776 return 1777 elif msgtype=='loading' and date in self.special_banner: 1778 self.change_banner(date) 1779 return 1780 else: 1781 return 1782 if MADEVENT: 1783 return 1784 1785 import os 1786 import pwd 1787 username =pwd.getpwuid( os.getuid() )[ 0 ] 1788 msg = msg % {'user': username} 1789 if sys.platform == "darwin": 1790 self.call_apple(msg) 1791 else: 1792 self.call_linux(msg) 1793 except Exception, error: 1794 sprint(error) 1795 pass
1796
1797 - def __call__(self, msg):
1798 try: 1799 self.call_apple(msg) 1800 except: 1801 pass
1802
1803 - def change_banner(self, date):
1808 1809
1810 - def call_apple(self, msg):
1811 1812 #1. control if the volume is on or not 1813 p = subprocess.Popen("osascript -e 'get volume settings'", stdout=subprocess.PIPE, shell=True) 1814 output, _ = p.communicate() 1815 #output volume:25, input volume:71, alert volume:100, output muted:true 1816 info = dict([[a.strip() for a in l.split(':',1)] for l in output.strip().split(',')]) 1817 muted = False 1818 if 'output muted' in info and info['output muted'] == 'true': 1819 muted = True 1820 elif 'output volume' in info and info['output volume'] == '0': 1821 muted = True 1822 1823 if muted: 1824 if not EasterEgg.done_notification: 1825 apple_notify('On April first','turn up your volume!') 1826 EasterEgg.done_notification = True 1827 else: 1828 os.system('say %s' % msg)
1829 1830
1831 - def call_linux(self, msg):
1832 # check for fishing path 1833 fishPath = madgraph.MG5DIR+"/input/.cowgraph.cow" 1834 if os.path.exists(fishPath): 1835 fishPath = " -f " + fishPath 1836 #sprint("got fishPath: ",fishPath) 1837 1838 # check for fishing pole 1839 fishPole = which('cowthink') 1840 if not os.path.exists(fishPole): 1841 if os.path.exists(which('cowsay')): 1842 fishPole = which('cowsay') 1843 else: 1844 return 1845 1846 # go fishing 1847 fishCmd = fishPole + fishPath + " " + msg 1848 os.system(fishCmd)
1849
1850 1851 -def get_older_version(v1, v2):
1852 """ return v2 if v1>v2 1853 return v1 if v1<v2 1854 return v1 if v1=v2 1855 return v1 if v2 is not in 1.2.3.4.5 format 1856 return v2 if v1 is not in 1.2.3.4.5 format 1857 """ 1858 from itertools import izip_longest 1859 for a1, a2 in izip_longest(v1, v2, fillvalue=0): 1860 try: 1861 a1= int(a1) 1862 except: 1863 return v2 1864 try: 1865 a2= int(a2) 1866 except: 1867 return v1 1868 if a1 > a2: 1869 return v2 1870 elif a1 < a2: 1871 return v1 1872 return v1
1873 1874 1875 1876 plugin_support = {}
1877 -def is_plugin_supported(obj):
1878 global plugin_support 1879 1880 name = obj.__name__ 1881 if name in plugin_support: 1882 return plugin_support[name] 1883 1884 # get MG5 version 1885 if '__mg5amcnlo__' in plugin_support: 1886 mg5_ver = plugin_support['__mg5amcnlo__'] 1887 else: 1888 info = get_pkg_info() 1889 mg5_ver = info['version'].split('.') 1890 try: 1891 min_ver = obj.minimal_mg5amcnlo_version 1892 max_ver = obj.maximal_mg5amcnlo_version 1893 val_ver = obj.latest_validated_version 1894 except: 1895 logger.error("Plugin %s misses some required info to be valid. It is therefore discarded" % name) 1896 plugin_support[name] = False 1897 return 1898 1899 if get_older_version(min_ver, mg5_ver) == min_ver and \ 1900 get_older_version(mg5_ver, max_ver) == mg5_ver: 1901 plugin_support[name] = True 1902 if get_older_version(mg5_ver, val_ver) == val_ver: 1903 logger.warning("""Plugin %s has marked as NOT being validated with this version. 1904 It has been validated for the last time with version: %s""", 1905 name, '.'.join(str(i) for i in val_ver)) 1906 else: 1907 if __debug__: 1908 logger.error("Plugin %s seems not supported by this version of MG5aMC. Keep it active (please update status)" % name) 1909 plugin_support[name] = True 1910 else: 1911 logger.error("Plugin %s is not supported by this version of MG5aMC." % name) 1912 plugin_support[name] = False 1913 return plugin_support[name]
1914
1915 1916 #decorator 1917 -def set_global(loop=False, unitary=True, mp=False, cms=False):
1918 from functools import wraps 1919 import aloha 1920 import aloha.aloha_lib as aloha_lib 1921 def deco_set(f): 1922 @wraps(f) 1923 def deco_f_set(*args, **opt): 1924 old_loop = aloha.loop_mode 1925 old_gauge = aloha.unitary_gauge 1926 old_mp = aloha.mp_precision 1927 old_cms = aloha.complex_mass 1928 aloha.loop_mode = loop 1929 aloha.unitary_gauge = unitary 1930 aloha.mp_precision = mp 1931 aloha.complex_mass = cms 1932 aloha_lib.KERNEL.clean() 1933 try: 1934 out = f(*args, **opt) 1935 except: 1936 aloha.loop_mode = old_loop 1937 aloha.unitary_gauge = old_gauge 1938 aloha.mp_precision = old_mp 1939 aloha.complex_mass = old_cms 1940 raise 1941 aloha.loop_mode = old_loop 1942 aloha.unitary_gauge = old_gauge 1943 aloha.mp_precision = old_mp 1944 aloha.complex_mass = old_cms 1945 aloha_lib.KERNEL.clean() 1946 return out
1947 return deco_f_set 1948 return deco_set 1949
1950 1951 1952 1953 -def plugin_import(module, error_msg, fcts=[]):
1954 """convenient way to import a plugin file/function""" 1955 1956 try: 1957 _temp = __import__('PLUGIN.%s' % module, globals(), locals(), fcts, -1) 1958 except ImportError: 1959 try: 1960 _temp = __import__('MG5aMC_PLUGIN.%s' % module, globals(), locals(), fcts, -1) 1961 except ImportError: 1962 raise MadGraph5Error, error_msg 1963 1964 if not fcts: 1965 return _temp 1966 elif len(fcts) == 1: 1967 return getattr(_temp,fcts[0]) 1968 else: 1969 return [getattr(_temp,name) for name in fcts]
1970
1971 -def from_plugin_import(plugin_path, target_type, keyname=None, warning=False, 1972 info=None):
1973 """return the class associated with keyname for a given plugin class 1974 if keyname is None, return all the name associated""" 1975 1976 validname = [] 1977 for plugpath in plugin_path: 1978 plugindirname = os.path.basename(plugpath) 1979 for plug in os.listdir(plugpath): 1980 if os.path.exists(pjoin(plugpath, plug, '__init__.py')): 1981 try: 1982 with stdchannel_redirected(sys.stdout, os.devnull): 1983 __import__('%s.%s' % (plugindirname,plug)) 1984 except Exception, error: 1985 if warning: 1986 logger.warning("error detected in plugin: %s.", plug) 1987 logger.warning("%s", error) 1988 continue 1989 plugin = sys.modules['%s.%s' % (plugindirname,plug)] 1990 if hasattr(plugin, target_type): 1991 if not is_plugin_supported(plugin): 1992 continue 1993 if keyname is None: 1994 validname += getattr(plugin, target_type).keys() 1995 else: 1996 if keyname in getattr(plugin, target_type): 1997 if not info: 1998 logger.info('Using from plugin %s mode %s' % (plug, keyname), '$MG:BOLD') 1999 else: 2000 logger.info(info % {'plug': plug, 'key':keyname}, '$MG:BOLD') 2001 return getattr(plugin, target_type)[keyname] 2002 2003 if not keyname: 2004 return validname
2005 2006 2007 2008 2009 python_lhapdf=None
2010 -def import_python_lhapdf(lhapdfconfig):
2011 """load the python module of lhapdf return None if it can not be loaded""" 2012 2013 #save the result to have it faster and avoid the segfault at the second try if lhapdf is not compatible 2014 global python_lhapdf 2015 if python_lhapdf: 2016 if python_lhapdf == -1: 2017 return None 2018 else: 2019 return python_lhapdf 2020 2021 use_lhapdf=False 2022 try: 2023 lhapdf_libdir=subprocess.Popen([lhapdfconfig,'--libdir'],\ 2024 stdout=subprocess.PIPE).stdout.read().strip() 2025 except: 2026 use_lhapdf=False 2027 return False 2028 else: 2029 try: 2030 candidates=[dirname for dirname in os.listdir(lhapdf_libdir) \ 2031 if os.path.isdir(os.path.join(lhapdf_libdir,dirname))] 2032 except OSError: 2033 candidates=[] 2034 for candidate in candidates: 2035 if os.path.isfile(os.path.join(lhapdf_libdir,candidate,'site-packages','lhapdf.so')): 2036 sys.path.insert(0,os.path.join(lhapdf_libdir,candidate,'site-packages')) 2037 try: 2038 import lhapdf 2039 use_lhapdf=True 2040 break 2041 except ImportError: 2042 sys.path.pop(0) 2043 continue 2044 if not use_lhapdf: 2045 try: 2046 candidates=[dirname for dirname in os.listdir(lhapdf_libdir+'64') \ 2047 if os.path.isdir(os.path.join(lhapdf_libdir+'64',dirname))] 2048 except OSError: 2049 candidates=[] 2050 for candidate in candidates: 2051 if os.path.isfile(os.path.join(lhapdf_libdir+'64',candidate,'site-packages','lhapdf.so')): 2052 sys.path.insert(0,os.path.join(lhapdf_libdir+'64',candidate,'site-packages')) 2053 try: 2054 import lhapdf 2055 use_lhapdf=True 2056 break 2057 except ImportError: 2058 sys.path.pop(0) 2059 continue 2060 if not use_lhapdf: 2061 try: 2062 import lhapdf 2063 use_lhapdf=True 2064 except ImportError: 2065 print 'fail' 2066 logger.warning("Failed to access python version of LHAPDF: "\ 2067 "If the python interface to LHAPDF is available on your system, try "\ 2068 "adding its location to the PYTHONPATH environment variable and the"\ 2069 "LHAPDF library location to LD_LIBRARY_PATH (linux) or DYLD_LIBRARY_PATH (mac os x)."\ 2070 "The required LD_LIBRARY_PATH is "+ lhapdf_libdir 2071 ) 2072 2073 if use_lhapdf: 2074 python_lhapdf = lhapdf 2075 python_lhapdf.setVerbosity(0) 2076 else: 2077 python_lhapdf = None 2078 return python_lhapdf
2079
2080 -def newtonmethod(f, df, x0, error=1e-10,maxiter=10000):
2081 """implement newton method for solving f(x)=0, df is the derivate""" 2082 x = x0 2083 iter=0 2084 while abs(f(x)) > error: 2085 iter+=1 2086 x = x - f(x)/df(x) 2087 if iter ==maxiter: 2088 sprint('fail to solve equation') 2089 raise Exception 2090 return x
2091
2092 -def wget(http, path, *args, **opt):
2093 """a wget function for both unix and mac""" 2094 2095 if sys.platform == "darwin": 2096 return call(['curl', '-L', http, '-o%s' % path], *args, **opt) 2097 else: 2098 return call(['wget', http, '--output-document=%s'% path], *args, **opt)
2099 2100 ############################### TRACQER FOR OPEN FILE 2101 #openfiles = set() 2102 #oldfile = __builtin__.file 2103 # 2104 #class newfile(oldfile): 2105 # done = 0 2106 # def __init__(self, *args): 2107 # self.x = args[0] 2108 # if 'matplotlib' in self.x: 2109 # raise Exception 2110 # print "### OPENING %s ### %s " % (str(self.x) , time.time()-start) 2111 # oldfile.__init__(self, *args) 2112 # openfiles.add(self) 2113 # 2114 # def close(self): 2115 # print "### CLOSING %s ### %s" % (str(self.x), time.time()-start) 2116 # oldfile.close(self) 2117 # openfiles.remove(self) 2118 #oldopen = __builtin__.open 2119 #def newopen(*args): 2120 # return newfile(*args) 2121 #__builtin__.file = newfile 2122 #__builtin__.open = newopen 2123