def runIOTests(self, update = False, force = 0, verbose=False, \ testKeys='instanceList'): """ Run the IOTests for this instance (defined in self.instance_tests) and compare the files of the chosen tests against the hardcoded ones stored in tests/input_files/IOTestsComparison. If you see an error in the comparison and you are sure that the newest output is correct (i.e. you understand that this modification is meant to be so). Then feel free to automatically regenerate this file with the newest version by doing ./test_manager -i U folderName/testName/fileName If update is True (meant to be used by __main__ only) then it will create/update/remove the files instead of testing them. The argument tests can be a list of tuple-keys describing the tests to cover. Otherwise it is the instance_test list. The force argument must be 10 if you do not want to monitor the modifications on the updated files. If it is 0 you will monitor all modified file and if 1 you will monitor each modified file of a given name only once. """ # First make sure that the tarball need not be untarred # Extract the tarball for hardcoded in all cases to make sure the # IOTestComparison folder is synchronized with it. if IOTestManager._compress_ref_fodler: if path.isdir(_hc_comparison_files): try: shutil.rmtree(_hc_comparison_files) except IOError: pass if path.isfile(_hc_comparison_tarball): tar = tarfile.open(_hc_comparison_tarball,mode='r:bz2') tar.extractall(path.dirname(_hc_comparison_files)) tar.close() else: raise MadGraph5Error, \ "Could not find the comparison tarball %s."%_hc_comparison_tarball else: if not path.isdir(_hc_comparison_files): raise MadGraph5Error, \ "Could not find the comparison tarball %s."%_hc_comparison_tarball # In update = True mode, we keep track of the modification to # provide summary information modifications={'updated':[],'created':[], 'removed':[], 'missing':[]} # List all the names of the files for which modifications have been # reviewed at least once.The approach taken here is different than # with the list refusedFolder and refusedTest. # The key of the dictionary are the filenames and the value are string # determining the user answer for that file. reviewed_file_names = {} # Chose what test to cover if testKeys == 'instanceList': testKeys = self.instance_tests if verbose: print "\n== "+colored%(32,"Operational mode")+\ " : file %s ==\n"%(colored%(34,('UPDATE' if update else 'TESTING'))) for (folder_name, test_name) in testKeys: try: (iotest, iotestManager) = self.all_tests[(folder_name, test_name)] except KeyError: raise MadGraph5Error, 'Test (%s,%s) could not be found.'\ %(folder_name, test_name) if verbose: print "Processing %s in %s"%( colored%(32,test_name),colored%(34,folder_name)) files_path = iotest.run(iotestManager) try: pass # files_path = iotest.run(iotestManager) except Exception as e: iotest.clean_output() if not verbose: raise e else: print colored%(31," Test %s "%test_name+\ "crashed with the following error:\n %s."%str(e)) continue # First create the list of files to check as the user might be using # regular expressions. filesToCheck=[] # Store here the files reckognized as veto rules (with filename # starting with '-') veto_rules = [] for fname in iotest.testedFiles: # Disregard the veto rules regexp_finder = re.compile( r'^(?P<veto>-)?(?P<root_folder>.*)(\/)?\[(?P<regexp>.*)\]$') found = regexp_finder.search(fname) if not found is None: # folder without the final / base_path = pjoin(files_path,found.group('root_folder')) regexp = re.compile(found.group('regexp')) # In filesToCheck, we must remove the files_path/ prepended for root, dirnames, filenames in os.walk(base_path): for file in filenames: if not regexp.search(str(os.path.relpath( pjoin(root,file),base_path))) is None and \ not path.islink(pjoin(root,file)): new_target = os.path.relpath( pjoin(root,file),files_path) if found.group('veto')=='-': veto_rules.append(new_target) else: filesToCheck.append(new_target) else: fn = fname[1:] if fname.startswith('-') else fname if (not path.exists(pjoin(files_path,fn))) or path.islink(pjoin(files_path,fn)): if force in [0,1]: answer = Cmd.timed_input(question= """The IOTest %s does not create file '%s'. Fix it! [type 'enter'] >"""\ %(test_name,fn),default="y") modifications['missing'].append( "%s/%s/%s"%(folder_name,test_name,path.basename(fname))) if verbose: print " > [ %s ] "%(colored%(31,"MISSING"))+\ "%s/%s/%s"%(folder_name,test_name,path.basename(fname)) else: if fname.startswith('-'): veto_rules.append(fn) else: filesToCheck.append(fn) # Apply the trimming of the veto rules filesToCheck = [f for f in filesToCheck if f not in veto_rules] if update: # Remove files which are no longer used for comparison activeFiles = [self.toFileName(f) for f in filesToCheck] for file in glob.glob(pjoin(_hc_comparison_files,folder_name,\ test_name,'*')): # Ignore the .BackUp files and directories. Also ignore # a file which was previously flagged missing because it # was explicitly specified in the list of files that the # test *must* provide. if path.basename(file).endswith('.BackUp') or \ path.isdir(file) or \ pjoin(folder_name,test_name,path.basename(file)) in \ modifications['missing']: continue if path.basename(file) not in activeFiles: if force==0 or (force==1 and \ path.basename(file) not in reviewed_file_names.keys()): answer = Cmd.timed_input(question= """Obsolete ref. file %s in %s/%s detected, delete it? [y/n] >"""\ %(path.basename(file),folder_name,test_name) ,default="y") reviewed_file_names[path.basename(file)] = answer elif (force==1 and \ path.basename(file) in reviewed_file_names.keys()): answer = reviewed_file_names[path.basename(file)] else: answer = 'Y' if answer not in ['Y','y','']: if verbose: print " > [ %s ] "%(colored%(31,"IGNORED"))+\ "file deletion %s/%s/%s"%(folder_name,test_name, path.basename(file)) continue os.remove(file) if verbose: print " > [ %s ] "%(colored%(31,"REMOVED"))+\ "%s/%s/%s"%(folder_name,test_name,path.basename(file)) modifications['removed'].append( '/'.join(str(file).split('/')[-3:])) # Make sure it is not filtered out by the user-filter if self.filesChecked_filter!=['ALL']: new_filesToCheck = [] for file in filesToCheck: # Try if it matches any filter for filter in self.filesChecked_filter: # A regular expression if filter.endswith(']'): split=filter[:-1].split('[') # folder without the final / folder=split[0][:-1] if folder!=path.dirname(pjoin(file)): continue search = re.compile('['.join(split[1:])) if not search.match(path.basename(file)) is None: new_filesToCheck.append(file) break # Just the exact filename elif filter==file: new_filesToCheck.append(file) break filesToCheck = new_filesToCheck # Now we can scan them and process them one at a time # Keep track of the folders and testNames the user did not want to # create refused_Folders = [] refused_testNames = [] for fname in filesToCheck: file_path = path.abspath(pjoin(files_path,fname)) self.assertTrue(path.isfile(file_path), 'File %s not found.'%str(file_path)) comparison_path = pjoin(_hc_comparison_files,\ folder_name,test_name,self.toFileName(fname)) if not update: if not os.path.isfile(comparison_path): iotest.clean_output() if not verbose: raise MadGraph5Error,\ "Missing ref. files for test %s\n"%test_name+\ "Create them with './test_manager.py -U %s'"%test_name continue else: print colored%(31,'The ref. file %s' %str('/'.join(comparison_path.split('/')[-3:]))+' does not exist.') print colored%(34,'Consider creating it with '+ './test_manager.py -U %s'%test_name) exit(0) goal = open(comparison_path).read()%misc.get_pkg_info() if not verbose: self.assertFileContains(open(file_path), goal) else: try: self.assertFileContains(open(file_path), goal) except AssertionError: if verbose: print " > %s differs from the reference."%fname else: if not path.isdir(pjoin(_hc_comparison_files,folder_name)): if force==0: if folder_name in refused_Folders: continue answer = Cmd.timed_input(question= """New folder %s detected, create it? [y/n] >"""%folder_name ,default="y") if answer not in ['Y','y','']: refused_Folders.append(folder_name) if verbose: print " > [ %s ] folder %s"\ %(colored%(31,"IGNORED"),folder_name) continue if verbose: print " > [ %s ] folder %s"%\ (colored%(32,"CREATED"),folder_name) os.makedirs(pjoin(_hc_comparison_files,folder_name)) if not path.isdir(pjoin(_hc_comparison_files,folder_name, test_name)): if force==0: if (folder_name,test_name) in refused_testNames: continue answer = Cmd.timed_input(question= """New test %s/%s detected, create it? [y/n] >"""%(folder_name,test_name) ,default="y") if answer not in ['Y','y','']: refused_testNames.append((folder_name,test_name)) if verbose: print " > [ %s ] test %s/%s"\ %(colored%(31,"IGNORED"),folder_name,test_name) continue if verbose: print " > [ %s ] test %s/%s"\ %(colored%(32,"CREATED"),folder_name,test_name) os.makedirs(pjoin(_hc_comparison_files,folder_name, test_name)) # Transform the package information to make it a template file = open(file_path,'r') target=file.read() # So that if % appear, we cast them to %% which are not formatted. target = target.replace('%','%%') # So that the version and date is automatically updated target = target.replace('MadGraph5_aMC@NLO v. %(version)s, %(date)s'\ %misc.get_pkg_info(), 'MadGraph5_aMC@NLO v. %(version)s, %(date)s') target = target.replace('v%(version)s (%(date)s)'\ %misc.get_pkg_info(), 'v%(version)s (%(date)s)') file.close() if os.path.isfile(comparison_path): file = open(comparison_path,'r') existing = file.read() file.close() if existing == target: continue else: # Copying the existing reference as a backup tmp_path = pjoin(_hc_comparison_files,folder_name,\ test_name,self.toFileName(fname)+'.BackUp') if os.path.isfile(tmp_path): os.remove(tmp_path) file = open(tmp_path,'w') file.write(target) file.close() if force==0 or (force==1 and path.basename(\ comparison_path) not in reviewed_file_names.keys()): text = \ """File %s in test %s/%s differs by the following (reference file first): """%(fname,folder_name,test_name) text += misc.Popen(['diff',str(comparison_path), str(tmp_path)],stdout=subprocess.PIPE).\ communicate()[0] # Remove the last newline if text[-1]=='\n': text=text[:-1] if (len(text.split('\n'))<15): print text else: pydoc.pager(text) print "Difference displayed in editor." answer = '' while answer not in ['y', 'n']: answer = Cmd.timed_input(question= """Ref. file %s differs from the new one (see diff. before), update it? [y/n/h/r] >"""%fname ,default="y") if answer not in ['y','n']: if answer == 'r': pydoc.pager(text) else: print "reference path: %s" % comparison_path print "code returns: %s" % tmp_path os.remove(tmp_path) reviewed_file_names[path.basename(\ comparison_path)] = answer elif (force==1 and path.basename(\ comparison_path) in reviewed_file_names.keys()): answer = reviewed_file_names[path.basename(\ comparison_path)] else: answer = 'Y' if answer not in ['Y','y','']: if verbose: print " > [ %s ] %s"%\ (colored%(31,"IGNORED"),fname) continue # Copying the existing reference as a backup back_up_path = pjoin(_hc_comparison_files,folder_name,\ test_name,self.toFileName(fname)+'.BackUp') if os.path.isfile(back_up_path): os.remove(back_up_path) cp(comparison_path,back_up_path) if verbose: print " > [ %s ] %s"\ %(colored%(32,"UPDATED"),fname) modifications['updated'].append( '/'.join(comparison_path.split('/')[-3:])) else: if force==0 or (force==1 and path.basename(\ comparison_path) not in reviewed_file_names.keys()): answer = Cmd.timed_input(question= """New file %s detected, create it? [y/n] >"""%fname ,default="y") reviewed_file_names[path.basename(\ comparison_path)] = answer elif (force==1 and path.basename(\ comparison_path) in reviewed_file_names.keys()): answer = reviewed_file_names[\ path.basename(comparison_path)] else: answer = 'Y' if answer not in ['Y','y','']: if verbose: print " > [ %s ] %s"%\ (colored%(31,"IGNORED"),fname) continue if verbose: print " > [ %s ] %s"%\ (colored%(32,"CREATED"),fname) modifications['created'].append( '/'.join(comparison_path.split('/')[-3:])) file = open(comparison_path,'w') file.write(target) file.close() # Clean the iotest output iotest.clean_output() # Monitor the modifications when in creation files mode by returning the # modifications dictionary. if update: return modifications else: return 'test_over'
def runIOTests(arg=[''],update=True,force=0,synchronize=False): """ running the IOtests associated to expression. By default, this launch all the tests created in classes inheriting IOTests. """ # Update the tarball, while removing the .backups. def noBackUps(tarinfo): if tarinfo.name.endswith('.BackUp'): return None else: return tarinfo if synchronize: print "Please, prefer updating the reference file automatically "+\ "rather than by hand." tar = tarfile.open(_hc_comparison_tarball, "w:bz2") tar.add(_hc_comparison_files, \ arcname=path.basename(_hc_comparison_files), filter=noBackUps) tar.close() # I am too lazy to work out the difference with the existing tarball and # put it in the log. So this is why one should refrain from editing the # reference files by hand. text = " \nModifications performed by hand on %s at %s in"%(\ str(datetime.date.today()),misc.format_timer(0.0)[14:]) text += '\n MadGraph5_aMC@NLO v. %(version)s, %(date)s\n'%misc.get_pkg_info() log = open(_hc_comparison_modif_log,mode='a') log.write(text) log.close() print "INFO:: Ref. tarball %s updated"%str(_hc_comparison_tarball) return if len(arg)!=1 or not isinstance(arg[0],str): print "Exactly one argument, and in must be a string, not %s."%arg return arg=arg[0] # Extract the tarball for hardcoded comparison if necessary if not path.isdir(_hc_comparison_files): if path.isfile(_hc_comparison_tarball): tar = tarfile.open(_hc_comparison_tarball,mode='r:bz2') tar.extractall(path.dirname(_hc_comparison_files)) tar.close() else: os.makedirs(_hc_comparison_files) # Make a backup of the comparison file directory in order to revert it if # the user wants to ignore the changes detected (only when updating the refs) hc_comparison_files_BackUp = _hc_comparison_files+'_BackUp' if update and path.isdir(_hc_comparison_files): if path.isdir(hc_comparison_files_BackUp): shutil.rmtree(hc_comparison_files_BackUp) shutil.copytree(_hc_comparison_files,hc_comparison_files_BackUp) IOTestManager.testFolders_filter = arg.split('/')[0].split('&') IOTestManager.testNames_filter = arg.split('/')[1].split('&') IOTestManager.filesChecked_filter = '/'.join(arg.split('/')[2:]).split('&') #print "INFO:: Using folders %s"%str(IOTestManager.testFolders_filter) #print "INFO:: Using test names %s"%str(IOTestManager.testNames_filter) #print "INFO:: Using file paths %s"%str(IOTestManager.filesChecked_filter) # Initiate all the IOTests from all the setUp() IOTestsInstances = [] start = time.time() for IOTestsClass in IOTestFinder(): # Instantiate the class IOTestsInstances.append(IOTestsClass()) # Run the setUp IOTestsInstances[-1].setUp() # Find the testIO defined and use them in load mode only, we will run # them later here. IOTestsFunctions = IOTestFinder() IOTestsFunctions.collect_function(IOTestsClass,prefix='testIO') for IOTestFunction in IOTestsFunctions: start = time.time() eval('IOTestsInstances[-1].'+IOTestFunction.split('.')[-1]+\ '(load_only=True)') setUp_time = time.time() - start if setUp_time > 0.5: print colored%(34,"Loading IOtest %s is slow (%s)"% (colored%(32,'.'.join(IOTestFunction.split('.')[-3:])), colored%(34,'%.2fs'%setUp_time))) if len(IOTestsInstances)==0: print "No IOTest found." return # runIOTests cannot be made a classmethod, so I use an instance, but it does # not matter which one as no instance attribute will be used. try: modifications = IOTestsInstances[-1].runIOTests( update = update, force = force, verbose=True, testKeys=IOTestManager.all_tests.keys()) except KeyboardInterrupt: if update: # Remove the BackUp of the reference files. if not path.isdir(hc_comparison_files_BackUp): print "\nWARNING:: Update interrupted and modifications already "+\ "performed could not be reverted." else: shutil.rmtree(_hc_comparison_files) mv(hc_comparison_files_BackUp,_hc_comparison_files) print colored%(34, "\nINFO:: Update interrupted, existing modifications reverted.") sys.exit(0) else: print "\nINFO:: IOTest runs interrupted." sys.exit(0) tot_time = time.time() - start if modifications == 'test_over': print colored%(32,"\n%d IOTests "%len(IOTestManager.all_tests.keys()))+\ "successfully tested in %s."%(colored%(34,'%.2fs'%tot_time)) sys.exit(0) elif not isinstance(modifications,dict): print "Error during the files update." sys.exit(0) if sum(len(v) for v in modifications.values())>0: # Display the modifications text = colored%(34, " \nModifications performed on %s at %s in"%(\ str(datetime.date.today()),misc.format_timer(0.0)[14:])) text += colored%(34, '\n MadGraph5_aMC@NLO v. %(version)s, %(date)s\n'%misc.get_pkg_info()) for key in modifications.keys(): if len(modifications[key])==0: continue text += colored%(32,"The following reference files have been %s :"%key) text += '\n'+'\n'.join([" %s"%mod for mod in modifications[key]]) text += '\n' print text try: answer = Cmd.timed_input(question= "Do you want to apply the modifications listed above? [y/n] >",default="y") except KeyboardInterrupt: answer = 'n' if answer == 'y': log = open(_hc_comparison_modif_log,mode='a') log.write(text) log.close() if IOTestManager._compress_ref_fodler: tar = tarfile.open(_hc_comparison_tarball, "w:bz2") tar.add(_hc_comparison_files, \ arcname=path.basename(_hc_comparison_files), filter=noBackUps) tar.close() print colored%(32,"INFO:: tarball %s updated"%str(_hc_comparison_tarball)) else: print colored%(32,"INFO:: Reference %s updated"%\ str(os.path.basename(_hc_comparison_files))) if len(modifications['created'])>0: print colored%(31,"Some ref. files have been created; add "+\ "them to the revision with\n "+ "bzr add tests/input_files/IOTestsComparison") # Make sure to remove the BackUp files filelist = glob.glob(os.path.join(_hc_comparison_files, '*','*','*.BackUp')) for f in filelist: os.remove(f) else: if path.isdir(hc_comparison_files_BackUp): shutil.rmtree(_hc_comparison_files) shutil.copytree(hc_comparison_files_BackUp,_hc_comparison_files) print colored%(32,"INFO:: No modifications applied.") else: print colored%(31, "ERROR:: Could not revert the modifications. No backup found.") else: print colored%(32,"\nNo modifications performed. No update necessary.") # Remove the BackUp of the reference files. if path.isdir(hc_comparison_files_BackUp): shutil.rmtree(hc_comparison_files_BackUp)
def runIOTests(self, update = False, force = 0, verbose=False, \ testKeys='instanceList'): """ Run the IOTests for this instance (defined in self.instance_tests) and compare the files of the chosen tests against the hardcoded ones stored in tests/input_files/IOTestsComparison. If you see an error in the comparison and you are sure that the newest output is correct (i.e. you understand that this modification is meant to be so). Then feel free to automatically regenerate this file with the newest version by doing ./test_manager -i U folderName/testName/fileName If update is True (meant to be used by __main__ only) then it will create/update/remove the files instead of testing them. The argument tests can be a list of tuple-keys describing the tests to cover. Otherwise it is the instance_test list. The force argument must be 10 if you do not want to monitor the modifications on the updated files. If it is 0 you will monitor all modified file and if 1 you will monitor each modified file of a given name only once. """ # First make sure that the tarball need not be untarred # Extract the tarball for hardcoded in all cases to make sure the # IOTestComparison folder is synchronized with it. if IOTestManager._compress_ref_fodler: if path.isdir(_hc_comparison_files): try: shutil.rmtree(_hc_comparison_files) except IOError: pass if path.isfile(_hc_comparison_tarball): tar = tarfile.open(_hc_comparison_tarball, mode='r:bz2') tar.extractall(path.dirname(_hc_comparison_files)) tar.close() else: raise MadGraph5Error( "Could not find the comparison tarball %s." % _hc_comparison_tarball) else: if not path.isdir(_hc_comparison_files): raise MadGraph5Error( "Could not find the comparison tarball %s." % _hc_comparison_tarball) # In update = True mode, we keep track of the modification to # provide summary information modifications = { 'updated': [], 'created': [], 'removed': [], 'missing': [] } # List all the names of the files for which modifications have been # reviewed at least once.The approach taken here is different than # with the list refusedFolder and refusedTest. # The key of the dictionary are the filenames and the value are string # determining the user answer for that file. reviewed_file_names = {} # Chose what test to cover if testKeys == 'instanceList': testKeys = self.instance_tests if verbose: print("\n== "+colored%(32,"Operational mode")+\ " : file %s ==\n"%(colored%(34,('UPDATE' if update else 'TESTING')))) for (folder_name, test_name) in testKeys: try: (iotest, iotestManager) = self.all_tests[(folder_name, test_name)] except KeyError: raise MadGraph5Error('Test (%s,%s) could not be found.'\ %(folder_name, test_name)) if verbose: print("Processing %s in %s" % (colored % (32, test_name), colored % (34, folder_name))) files_path = iotest.run(iotestManager) try: pass # files_path = iotest.run(iotestManager) except Exception as e: iotest.clean_output() if not verbose: raise e else: print(colored%(31," Test %s "%test_name+\ "crashed with the following error:\n %s."%str(e))) continue # First create the list of files to check as the user might be using # regular expressions. filesToCheck = [] # Store here the files reckognized as veto rules (with filename # starting with '-') veto_rules = [] for fname in iotest.testedFiles: # Disregard the veto rules regexp_finder = re.compile( r'^(?P<veto>-)?(?P<root_folder>.*)(\/)?\[(?P<regexp>.*)\]$' ) found = regexp_finder.search(fname) if not found is None: # folder without the final / base_path = pjoin(files_path, found.group('root_folder')) regexp = re.compile(found.group('regexp')) # In filesToCheck, we must remove the files_path/ prepended for root, dirnames, filenames in os.walk(base_path): for file in filenames: if not regexp.search(str(os.path.relpath( pjoin(root,file),base_path))) is None and \ not path.islink(pjoin(root,file)): new_target = os.path.relpath( pjoin(root, file), files_path) if found.group('veto') == '-': veto_rules.append(new_target) else: filesToCheck.append(new_target) else: fn = fname[1:] if fname.startswith('-') else fname if (not path.exists(pjoin(files_path, fn))) or path.islink( pjoin(files_path, fn)): if force in [0, 1]: answer = Cmd.timed_input(question= """The IOTest %s does not create file '%s'. Fix it! [type 'enter'] >"""\ %(test_name,fn),default="y") modifications['missing'].append( "%s/%s/%s" % (folder_name, test_name, path.basename(fname))) if verbose: print(" > [ %s ] "%(colored%(31,"MISSING"))+\ "%s/%s/%s"%(folder_name,test_name,path.basename(fname))) else: if fname.startswith('-'): veto_rules.append(fn) else: filesToCheck.append(fn) # Apply the trimming of the veto rules filesToCheck = [f for f in filesToCheck if f not in veto_rules] if update: # Remove files which are no longer used for comparison activeFiles = [self.toFileName(f) for f in filesToCheck] for file in glob.glob(pjoin(_hc_comparison_files,folder_name,\ test_name,'*')): # Ignore the .BackUp files and directories. Also ignore # a file which was previously flagged missing because it # was explicitly specified in the list of files that the # test *must* provide. if path.basename(file).endswith('.BackUp') or \ path.isdir(file) or \ pjoin(folder_name,test_name,path.basename(file)) in \ modifications['missing']: continue if path.basename(file) not in activeFiles: if force==0 or (force==1 and \ path.basename(file) not in list(reviewed_file_names.keys())): answer = Cmd.timed_input(question= """Obsolete ref. file %s in %s/%s detected, delete it? [y/n] >"""\ %(path.basename(file),folder_name,test_name) ,default="y") reviewed_file_names[path.basename(file)] = answer elif (force==1 and \ path.basename(file) in list(reviewed_file_names.keys())): answer = reviewed_file_names[path.basename(file)] else: answer = 'Y' if answer not in ['Y', 'y', '']: if verbose: print(" > [ %s ] "%(colored%(31,"IGNORED"))+\ "file deletion %s/%s/%s"%(folder_name,test_name, path.basename(file))) continue os.remove(file) if verbose: print(" > [ %s ] "%(colored%(31,"REMOVED"))+\ "%s/%s/%s"%(folder_name,test_name,path.basename(file))) modifications['removed'].append('/'.join( str(file).split('/')[-3:])) # Make sure it is not filtered out by the user-filter if self.filesChecked_filter != ['ALL']: new_filesToCheck = [] for file in filesToCheck: # Try if it matches any filter for filter in self.filesChecked_filter: # A regular expression if filter.endswith(']'): split = filter[:-1].split('[') # folder without the final / folder = split[0][:-1] if folder != path.dirname(pjoin(file)): continue search = re.compile('['.join(split[1:])) if not search.match(path.basename(file)) is None: new_filesToCheck.append(file) break # Just the exact filename elif filter == file: new_filesToCheck.append(file) break filesToCheck = new_filesToCheck # Now we can scan them and process them one at a time # Keep track of the folders and testNames the user did not want to # create refused_Folders = [] refused_testNames = [] for fname in filesToCheck: file_path = path.abspath(pjoin(files_path, fname)) self.assertTrue(path.isfile(file_path), 'File %s not found.' % str(file_path)) comparison_path = pjoin(_hc_comparison_files,\ folder_name,test_name,self.toFileName(fname)) if not update: if not os.path.isfile(comparison_path): iotest.clean_output() if not verbose: raise MadGraph5Error("Missing ref. files for test %s\n"%test_name+\ "Create them with './test_manager.py -U %s'"%test_name) continue else: print(colored % (31, 'The ref. file %s' % str( '/'.join(comparison_path.split('/')[-3:])) + ' does not exist.')) print(colored % (34, 'Consider creating it with ' + './test_manager.py -U %s' % test_name)) exit(0) goal = open(comparison_path).read() % misc.get_pkg_info() if not verbose: self.assertFileContains(open(file_path), goal) else: try: self.assertFileContains(open(file_path), goal) except AssertionError: if verbose: print(" > %s differs from the reference." % fname) else: if not path.isdir(pjoin(_hc_comparison_files, folder_name)): if force == 0: if folder_name in refused_Folders: continue answer = Cmd.timed_input( question= """New folder %s detected, create it? [y/n] >""" % folder_name, default="y") if answer not in ['Y', 'y', '']: refused_Folders.append(folder_name) if verbose: print(" > [ %s ] folder %s"\ %(colored%(31,"IGNORED"),folder_name)) continue if verbose: print(" > [ %s ] folder %s"%\ (colored%(32,"CREATED"),folder_name)) os.makedirs(pjoin(_hc_comparison_files, folder_name)) if not path.isdir( pjoin(_hc_comparison_files, folder_name, test_name)): if force == 0: if (folder_name, test_name) in refused_testNames: continue answer = Cmd.timed_input( question= """New test %s/%s detected, create it? [y/n] >""" % (folder_name, test_name), default="y") if answer not in ['Y', 'y', '']: refused_testNames.append( (folder_name, test_name)) if verbose: print(" > [ %s ] test %s/%s"\ %(colored%(31,"IGNORED"),folder_name,test_name)) continue if verbose: print(" > [ %s ] test %s/%s"\ %(colored%(32,"CREATED"),folder_name,test_name)) os.makedirs( pjoin(_hc_comparison_files, folder_name, test_name)) # Transform the package information to make it a template file = open(file_path, 'r') target = file.read() # So that if % appear, we cast them to %% which are not formatted. target = target.replace('%', '%%') # So that the version and date is automatically updated target = target.replace('MadGraph5_aMC@NLO v. %(version)s, %(date)s'\ %misc.get_pkg_info(), 'MadGraph5_aMC@NLO v. %(version)s, %(date)s') target = target.replace('v%(version)s (%(date)s)'\ %misc.get_pkg_info(), 'v%(version)s (%(date)s)') file.close() if os.path.isfile(comparison_path): file = open(comparison_path, 'r') existing = file.read() file.close() if existing == target: continue else: # Copying the existing reference as a backup tmp_path = pjoin(_hc_comparison_files,folder_name,\ test_name,self.toFileName(fname)+'.BackUp') if os.path.isfile(tmp_path): os.remove(tmp_path) file = open(tmp_path, 'w') file.write(target) file.close() if force==0 or (force==1 and path.basename(\ comparison_path) not in list(reviewed_file_names.keys())): text = \ """File %s in test %s/%s differs by the following (reference file first): """%(fname,folder_name,test_name) text += misc.Popen(['diff',str(comparison_path), str(tmp_path)],stdout=subprocess.PIPE).\ communicate()[0].decode('utf-8') # Remove the last newline if text[-1] == '\n': text = text[:-1] if (len(text.split('\n')) < 15): print(text) else: pydoc.pager(text) print("Difference displayed in editor.") answer = '' while answer not in ['y', 'n']: answer = Cmd.timed_input( question= """Ref. file %s differs from the new one (see diff. before), update it? [y/n/h/r] >""" % fname, default="y") if answer not in ['y', 'n']: if answer == 'r': pydoc.pager(text) else: print("reference path: %s" % comparison_path) print("code returns: %s" % tmp_path) os.remove(tmp_path) reviewed_file_names[path.basename(\ comparison_path)] = answer elif (force==1 and path.basename(\ comparison_path) in list(reviewed_file_names.keys())): answer = reviewed_file_names[path.basename(\ comparison_path)] else: answer = 'Y' if answer not in ['Y', 'y', '']: if verbose: print(" > [ %s ] %s"%\ (colored%(31,"IGNORED"),fname)) continue # Copying the existing reference as a backup back_up_path = pjoin(_hc_comparison_files,folder_name,\ test_name,self.toFileName(fname)+'.BackUp') if os.path.isfile(back_up_path): os.remove(back_up_path) cp(comparison_path, back_up_path) if verbose: print(" > [ %s ] %s"\ %(colored%(32,"UPDATED"),fname)) modifications['updated'].append('/'.join( comparison_path.split('/')[-3:])) else: if force==0 or (force==1 and path.basename(\ comparison_path) not in list(reviewed_file_names.keys())): answer = Cmd.timed_input( question= """New file %s detected, create it? [y/n] >""" % fname, default="y") reviewed_file_names[path.basename(\ comparison_path)] = answer elif (force==1 and path.basename(\ comparison_path) in list(reviewed_file_names.keys())): answer = reviewed_file_names[\ path.basename(comparison_path)] else: answer = 'Y' if answer not in ['Y', 'y', '']: if verbose: print(" > [ %s ] %s"%\ (colored%(31,"IGNORED"),fname)) continue if verbose: print(" > [ %s ] %s"%\ (colored%(32,"CREATED"),fname)) modifications['created'].append('/'.join( comparison_path.split('/')[-3:])) file = open(comparison_path, 'w') file.write(target) file.close() # Clean the iotest output iotest.clean_output() # Monitor the modifications when in creation files mode by returning the # modifications dictionary. if update: return modifications else: return 'test_over'
def runIOTests(arg=[''], update=True, force=0, synchronize=False): """ running the IOtests associated to expression. By default, this launch all the tests created in classes inheriting IOTests. """ # Update the tarball, while removing the .backups. def noBackUps(tarinfo): if tarinfo.name.endswith('.BackUp'): return None else: return tarinfo if synchronize: print "Please, prefer updating the reference file automatically "+\ "rather than by hand." tar = tarfile.open(_hc_comparison_tarball, "w:bz2") tar.add(_hc_comparison_files, \ arcname=path.basename(_hc_comparison_files), filter=noBackUps) tar.close() # I am too lazy to work out the difference with the existing tarball and # put it in the log. So this is why one should refrain from editing the # reference files by hand. text = " \nModifications performed by hand on %s at %s in"%(\ str(datetime.date.today()),misc.format_timer(0.0)[14:]) text += '\n MadGraph5_aMC@NLO v. %(version)s, %(date)s\n' % misc.get_pkg_info( ) log = open(_hc_comparison_modif_log, mode='a') log.write(text) log.close() print "INFO:: Ref. tarball %s updated" % str(_hc_comparison_tarball) return if len(arg) != 1 or not isinstance(arg[0], str): print "Exactly one argument, and in must be a string, not %s." % arg return arg = arg[0] # Extract the tarball for hardcoded comparison if necessary if not path.isdir(_hc_comparison_files): if path.isfile(_hc_comparison_tarball): tar = tarfile.open(_hc_comparison_tarball, mode='r:bz2') tar.extractall(path.dirname(_hc_comparison_files)) tar.close() else: os.makedirs(_hc_comparison_files) # Make a backup of the comparison file directory in order to revert it if # the user wants to ignore the changes detected (only when updating the refs) hc_comparison_files_BackUp = _hc_comparison_files + '_BackUp' if update and path.isdir(_hc_comparison_files): if path.isdir(hc_comparison_files_BackUp): shutil.rmtree(hc_comparison_files_BackUp) shutil.copytree(_hc_comparison_files, hc_comparison_files_BackUp) IOTestManager.testFolders_filter = arg.split('/')[0].split('&') IOTestManager.testNames_filter = arg.split('/')[1].split('&') IOTestManager.filesChecked_filter = '/'.join(arg.split('/')[2:]).split('&') #print "INFO:: Using folders %s"%str(IOTestManager.testFolders_filter) #print "INFO:: Using test names %s"%str(IOTestManager.testNames_filter) #print "INFO:: Using file paths %s"%str(IOTestManager.filesChecked_filter) # Initiate all the IOTests from all the setUp() IOTestsInstances = [] start = time.time() for IOTestsClass in IOTestFinder(): # Instantiate the class IOTestsInstances.append(IOTestsClass()) # Run the setUp IOTestsInstances[-1].setUp() # Find the testIO defined and use them in load mode only, we will run # them later here. IOTestsFunctions = IOTestFinder() IOTestsFunctions.collect_function(IOTestsClass, prefix='testIO') for IOTestFunction in IOTestsFunctions: start = time.time() # Add all the tests automatically (i.e. bypass filters) if the # specified test is the name of the IOtest. the [7:] is to # skip the testIO prefix name_filer_bu = None if IOTestFunction.split('.')[-1][7:] in \ IOTestManager.testNames_filter: name_filer_bu = IOTestManager.testNames_filter IOTestManager.testNames_filter = ['ALL'] existing_tests = IOTestManager.all_tests.keys() eval('IOTestsInstances[-1].'+IOTestFunction.split('.')[-1]+\ '(load_only=True)') if name_filer_bu: new_tests = [test[0] for test in IOTestManager.all_tests.keys() \ if test not in existing_tests] IOTestManager.testNames_filter = name_filer_bu + new_tests name_filer_bu = None setUp_time = time.time() - start if setUp_time > 0.5: print colored % ( 34, "Loading IOtest %s is slow (%s)" % (colored % (32, '.'.join(IOTestFunction.split('.')[-3:])), colored % (34, '%.2fs' % setUp_time))) if len(IOTestsInstances) == 0: print "No IOTest found." return # runIOTests cannot be made a classmethod, so I use an instance, but it does # not matter which one as no instance attribute will be used. try: modifications = IOTestsInstances[-1].runIOTests( update=update, force=force, verbose=True, testKeys=IOTestManager.all_tests.keys()) except KeyboardInterrupt: if update: # Remove the BackUp of the reference files. if not path.isdir(hc_comparison_files_BackUp): print "\nWARNING:: Update interrupted and modifications already "+\ "performed could not be reverted." else: shutil.rmtree(_hc_comparison_files) mv(hc_comparison_files_BackUp, _hc_comparison_files) print colored % ( 34, "\nINFO:: Update interrupted, existing modifications reverted." ) sys.exit(0) else: print "\nINFO:: IOTest runs interrupted." sys.exit(0) tot_time = time.time() - start if modifications == 'test_over': print colored%(32,"\n%d IOTests "%len(IOTestManager.all_tests.keys()))+\ "successfully tested in %s."%(colored%(34,'%.2fs'%tot_time)) sys.exit(0) elif not isinstance(modifications, dict): print "Error during the files update." sys.exit(0) if len(modifications['missing']) > 0: text = '\n' text += colored % ( 31, "The following files were not generated by the tests, fix this!") text += '\n' + '\n'.join( [" %s" % mod for mod in modifications['missing']]) print text modifications['missing'] = [] if sum(len(v) for v in modifications.values()) > 0: # Display the modifications text = colored%(34, " \nModifications performed on %s at %s in"%(\ str(datetime.date.today()),misc.format_timer(0.0)[14:])) text += colored % ( 34, '\n MadGraph5_aMC@NLO v. %(version)s, %(date)s\n' % misc.get_pkg_info()) for key in modifications.keys(): if len(modifications[key]) == 0: continue text += colored % ( 32, "The following reference files have been %s :" % key) text += '\n' + '\n'.join( [" %s" % mod for mod in modifications[key]]) text += '\n' print text try: answer = Cmd.timed_input( question= "Do you want to apply the modifications listed above? [y/n] >", default="y") except KeyboardInterrupt: answer = 'n' if answer == 'y': log = open(_hc_comparison_modif_log, mode='a') log.write(text) log.close() if IOTestManager._compress_ref_fodler: tar = tarfile.open(_hc_comparison_tarball, "w:bz2") tar.add(_hc_comparison_files, \ arcname=path.basename(_hc_comparison_files), filter=noBackUps) tar.close() print colored % (32, "INFO:: tarball %s updated" % str(_hc_comparison_tarball)) else: print colored%(32,"INFO:: Reference %s updated"%\ str(os.path.basename(_hc_comparison_files))) if len(modifications['created']) > 0: print colored%(31,"Some ref. files have been created; add "+\ "them to the revision with\n "+ "bzr add tests/input_files/IOTestsComparison") # Make sure to remove the BackUp files filelist = glob.glob( os.path.join(_hc_comparison_files, '*', '*', '*.BackUp')) for f in filelist: os.remove(f) else: if path.isdir(hc_comparison_files_BackUp): shutil.rmtree(_hc_comparison_files) shutil.copytree(hc_comparison_files_BackUp, _hc_comparison_files) print colored % (32, "INFO:: No modifications applied.") else: print colored % ( 31, "ERROR:: Could not revert the modifications. No backup found." ) else: print colored % (32, "\nNo modifications performed. No update necessary.") # Remove the BackUp of the reference files. if path.isdir(hc_comparison_files_BackUp): shutil.rmtree(hc_comparison_files_BackUp)