00001
00002
00003
00004 from Options import Options
00005 options = Options()
00006
00007
00008
00009 import sys
00010 from Mixins import PrintOptions,_ParameterTypeBase,_SimpleParameterTypeBase, _Parameterizable, _ConfigureComponent, _TypedParameterizable, _Labelable, _Unlabelable, _ValidatingListBase
00011 from Mixins import *
00012 from Types import *
00013 from Modules import *
00014 from Modules import _Module
00015 from SequenceTypes import *
00016 from SequenceTypes import _ModuleSequenceType, _Sequenceable
00017 from SequenceVisitors import PathValidator, EndPathValidator
00018 from Utilities import *
00019 import DictTypes
00020
00021 from ExceptionHandling import *
00022
00023
00024 if sys.getrecursionlimit()<5000:
00025 sys.setrecursionlimit(5000)
00026
00027 def checkImportPermission(minLevel = 2, allowedPatterns = []):
00028 """
00029 Raise an exception if called by special config files. This checks
00030 the call or import stack for the importing file. An exception is raised if
00031 the importing module is not in allowedPatterns and if it is called too deeply:
00032 minLevel = 2: inclusion by top lvel cfg only
00033 minLevel = 1: No inclusion allowed
00034 allowedPatterns = ['Module1','Module2/SubModule1'] allows import
00035 by any module in Module1 or Submodule1
00036 """
00037
00038 import inspect
00039 import os
00040
00041 ignorePatterns = ['FWCore/ParameterSet/Config.py','<string>']
00042 CMSSWPath = [os.environ['CMSSW_BASE'],os.environ['CMSSW_RELEASE_BASE']]
00043
00044
00045 trueStack = []
00046 for item in inspect.stack():
00047 inPath = False
00048 ignore = False
00049
00050 for pattern in CMSSWPath:
00051 if item[1].find(pattern) != -1:
00052 inPath = True
00053 break
00054 if item[1].find('/') == -1:
00055 inPath = True
00056
00057 for pattern in ignorePatterns:
00058 if item[1].find(pattern) != -1:
00059 ignore = True
00060 break
00061
00062 if inPath and not ignore:
00063 trueStack.append(item[1])
00064
00065 importedFile = trueStack[0]
00066 importedBy = ''
00067 if len(trueStack) > 1:
00068 importedBy = trueStack[1]
00069
00070 for pattern in allowedPatterns:
00071 if importedBy.find(pattern) > -1:
00072 return True
00073
00074 if len(trueStack) <= minLevel:
00075 return True
00076
00077 raise ImportError("Inclusion of %s is allowed only by cfg or specified cfi files."
00078 % importedFile)
00079
00080 def findProcess(module):
00081 """Look inside the module and find the Processes it contains"""
00082 class Temp(object):
00083 pass
00084 process = None
00085 if isinstance(module,dict):
00086 if 'process' in module:
00087 p = module['process']
00088 module = Temp()
00089 module.process = p
00090 if hasattr(module,'process'):
00091 if isinstance(module.process,Process):
00092 process = module.process
00093 else:
00094 raise RuntimeError("The attribute named 'process' does not inherit from the Process class")
00095 else:
00096 raise RuntimeError("no 'process' attribute found in the module, please add one")
00097 return process
00098
00099
00100 class Process(object):
00101 """Root class for a CMS configuration process"""
00102 def __init__(self,name):
00103 """The argument 'name' will be the name applied to this Process"""
00104 self.__dict__['_Process__name'] = name
00105 if not name.isalnum():
00106 raise RuntimeError("Error: The process name is an empty string or contains non-alphanumeric characters")
00107 self.__dict__['_Process__filters'] = {}
00108 self.__dict__['_Process__producers'] = {}
00109 self.__dict__['_Process__source'] = None
00110 self.__dict__['_Process__looper'] = None
00111 self.__dict__['_Process__subProcess'] = None
00112 self.__dict__['_Process__schedule'] = None
00113 self.__dict__['_Process__analyzers'] = {}
00114 self.__dict__['_Process__outputmodules'] = {}
00115 self.__dict__['_Process__paths'] = DictTypes.SortedKeysDict()
00116 self.__dict__['_Process__endpaths'] = DictTypes.SortedKeysDict()
00117 self.__dict__['_Process__sequences'] = {}
00118 self.__dict__['_Process__services'] = {}
00119 self.__dict__['_Process__essources'] = {}
00120 self.__dict__['_Process__esproducers'] = {}
00121 self.__dict__['_Process__esprefers'] = {}
00122 self.__dict__['_Process__psets']={}
00123 self.__dict__['_Process__vpsets']={}
00124 self.__dict__['_cloneToObjectDict'] = {}
00125
00126 self.__dict__['_Process__InExtendCall'] = False
00127 self.__dict__['_Process__partialschedules'] = {}
00128 self.__isStrict = False
00129
00130 def setStrict(self, value):
00131 self.__isStrict = value
00132 _Module.__isStrict__ = True
00133
00134
00135 def producerNames(self):
00136 """Returns a string containing all the EDProducer labels separated by a blank"""
00137 return ' '.join(self.producers_().keys())
00138 def analyzerNames(self):
00139 """Returns a string containing all the EDAnalyzer labels separated by a blank"""
00140 return ' '.join(self.analyzers_().keys())
00141 def filterNames(self):
00142 """Returns a string containing all the EDFilter labels separated by a blank"""
00143 return ' '.join(self.filters_().keys())
00144 def pathNames(self):
00145 """Returns a string containing all the Path names separated by a blank"""
00146 return ' '.join(self.paths_().keys())
00147
00148 def __setstate__(self, pkldict):
00149 """
00150 Unpickling hook.
00151
00152 Since cloneToObjectDict stores a hash of objects by their
00153 id() it needs to be updated when unpickling to use the
00154 new object id values instantiated during the unpickle.
00155
00156 """
00157 self.__dict__.update(pkldict)
00158 tmpDict = {}
00159 for value in self._cloneToObjectDict.values():
00160 tmpDict[id(value)] = value
00161 self.__dict__['_cloneToObjectDict'] = tmpDict
00162
00163
00164
00165 def filters_(self):
00166 """returns a dict of the filters which have been added to the Process"""
00167 return DictTypes.FixedKeysDict(self.__filters)
00168 filters = property(filters_, doc="dictionary containing the filters for the process")
00169 def name_(self):
00170 return self.__name
00171 def setName_(self,name):
00172 if not name.isalnum():
00173 raise RuntimeError("Error: The process name is an empty string or contains non-alphanumeric characters")
00174 self.__dict__['_Process__name'] = name
00175 process = property(name_,setName_, doc="name of the process")
00176 def producers_(self):
00177 """returns a dict of the producers which have been added to the Process"""
00178 return DictTypes.FixedKeysDict(self.__producers)
00179 producers = property(producers_,doc="dictionary containing the producers for the process")
00180 def source_(self):
00181 """returns the source which has been added to the Process or None if none have been added"""
00182 return self.__source
00183 def setSource_(self,src):
00184 self._placeSource('source',src)
00185 source = property(source_,setSource_,doc='the main source or None if not set')
00186 def looper_(self):
00187 """returns the looper which has been added to the Process or None if none have been added"""
00188 return self.__looper
00189 def setLooper_(self,lpr):
00190 self._placeLooper('looper',lpr)
00191 looper = property(looper_,setLooper_,doc='the main looper or None if not set')
00192 def subProcess_(self):
00193 """returns the sub-process which has been added to the Process or None if none have been added"""
00194 return self.__subProcess
00195 def setSubProcess_(self,lpr):
00196 self._placeSubProcess('subProcess',lpr)
00197 subProcess = property(subProcess_,setSubProcess_,doc='the SubProcess or None if not set')
00198 def analyzers_(self):
00199 """returns a dict of the analyzers which have been added to the Process"""
00200 return DictTypes.FixedKeysDict(self.__analyzers)
00201 analyzers = property(analyzers_,doc="dictionary containing the analyzers for the process")
00202 def outputModules_(self):
00203 """returns a dict of the output modules which have been added to the Process"""
00204 return DictTypes.FixedKeysDict(self.__outputmodules)
00205 outputModules = property(outputModules_,doc="dictionary containing the output_modules for the process")
00206 def paths_(self):
00207 """returns a dict of the paths which have been added to the Process"""
00208 return DictTypes.SortedAndFixedKeysDict(self.__paths)
00209 paths = property(paths_,doc="dictionary containing the paths for the process")
00210 def endpaths_(self):
00211 """returns a dict of the endpaths which have been added to the Process"""
00212 return DictTypes.SortedAndFixedKeysDict(self.__endpaths)
00213 endpaths = property(endpaths_,doc="dictionary containing the endpaths for the process")
00214 def sequences_(self):
00215 """returns a dict of the sequences which have been added to the Process"""
00216 return DictTypes.FixedKeysDict(self.__sequences)
00217 sequences = property(sequences_,doc="dictionary containing the sequences for the process")
00218 def schedule_(self):
00219 """returns the schedule which has been added to the Process or None if none have been added"""
00220 return self.__schedule
00221 def setPartialSchedule_(self,sch,label):
00222 if label == "schedule":
00223 self.setSchedule_(sch)
00224 else:
00225 self._place(label, sch, self.__partialschedules)
00226 def setSchedule_(self,sch):
00227
00228 index = 0
00229 try:
00230 for p in sch:
00231 p.label_()
00232 index +=1
00233 except:
00234 raise RuntimeError("The path at index "+str(index)+" in the Schedule was not attached to the process.")
00235
00236 self.__dict__['_Process__schedule'] = sch
00237 schedule = property(schedule_,setSchedule_,doc='the schedule or None if not set')
00238 def services_(self):
00239 """returns a dict of the services which have been added to the Process"""
00240 return DictTypes.FixedKeysDict(self.__services)
00241 services = property(services_,doc="dictionary containing the services for the process")
00242 def es_producers_(self):
00243 """returns a dict of the esproducers which have been added to the Process"""
00244 return DictTypes.FixedKeysDict(self.__esproducers)
00245 es_producers = property(es_producers_,doc="dictionary containing the es_producers for the process")
00246 def es_sources_(self):
00247 """returns a the es_sources which have been added to the Process"""
00248 return DictTypes.FixedKeysDict(self.__essources)
00249 es_sources = property(es_sources_,doc="dictionary containing the es_sources for the process")
00250 def es_prefers_(self):
00251 """returns a dict of the es_prefers which have been added to the Process"""
00252 return DictTypes.FixedKeysDict(self.__esprefers)
00253 es_prefers = property(es_prefers_,doc="dictionary containing the es_prefers for the process")
00254 def psets_(self):
00255 """returns a dict of the PSets which have been added to the Process"""
00256 return DictTypes.FixedKeysDict(self.__psets)
00257 psets = property(psets_,doc="dictionary containing the PSets for the process")
00258 def vpsets_(self):
00259 """returns a dict of the VPSets which have been added to the Process"""
00260 return DictTypes.FixedKeysDict(self.__vpsets)
00261 vpsets = property(vpsets_,doc="dictionary containing the PSets for the process")
00262 def __setattr__(self,name,value):
00263
00264 if not name.replace('_','').isalnum():
00265 raise ValueError('The label '+name+' contains forbiden characters')
00266
00267
00268 if name.startswith('_Process__'):
00269 self.__dict__[name]=value
00270 return
00271 if not isinstance(value,_ConfigureComponent):
00272 raise TypeError("can only assign labels to an object which inherits from '_ConfigureComponent'\n"
00273 +"an instance of "+str(type(value))+" will not work")
00274 if not isinstance(value,_Labelable) and not isinstance(value,Source) and not isinstance(value,Looper) and not isinstance(value,Schedule):
00275 if name == value.type_():
00276 self.add_(value)
00277 return
00278 else:
00279 raise TypeError("an instance of "+str(type(value))+" can not be assigned the label '"+name+"'.\n"+
00280 "Please either use the label '"+value.type_()+" or use the 'add_' method instead.")
00281
00282 if self.__isStrict:
00283 newValue =value.copy()
00284 try:
00285 newValue._filename = value._filename
00286 except:
00287 pass
00288 value.setIsFrozen()
00289 else:
00290 newValue =value
00291 if not self._okToPlace(name, value, self.__dict__):
00292 msg = "Trying to override definition of process."+name
00293 msg += "\n new object defined in: "+value._filename
00294 msg += "\n existing object defined in: "+getattr(self,name)._filename
00295 raise ValueError(msg)
00296
00297 if hasattr(self,name) and not (getattr(self,name)==newValue):
00298
00299
00300
00301 if not self.__InExtendCall and isinstance(newValue, _Sequenceable):
00302 self._replaceInSequences(name, newValue)
00303 self.__delattr__(name)
00304 self.__dict__[name]=newValue
00305 if isinstance(newValue,_Labelable):
00306 newValue.setLabel(name)
00307 self._cloneToObjectDict[id(value)] = newValue
00308 self._cloneToObjectDict[id(newValue)] = newValue
00309
00310 newValue._place(name,self)
00311
00312 def __delattr__(self,name):
00313 if not hasattr(self,name):
00314 raise KeyError('process does not know about '+name)
00315 elif name.startswith('_Process__'):
00316 raise ValueError('this attribute cannot be deleted')
00317 else:
00318
00319 dicts = [item for item in self.__dict__.values() if (type(item)==dict or type(item)==DictTypes.SortedKeysDict)]
00320 for reg in dicts:
00321 if reg.has_key(name): del reg[name]
00322
00323 obj = getattr(self,name)
00324 if isinstance(obj,_Labelable):
00325 getattr(self,name).setLabel(None)
00326
00327 try:
00328 del self.__dict__[name]
00329 except:
00330 pass
00331
00332 def add_(self,value):
00333 """Allows addition of components which do not have to have a label, e.g. Services"""
00334 if not isinstance(value,_ConfigureComponent):
00335 raise TypeError
00336 if not isinstance(value,_Unlabelable):
00337 raise TypeError
00338
00339
00340 if self.__isStrict:
00341 newValue =value.copy()
00342 value.setIsFrozen()
00343 else:
00344 newValue =value
00345 newValue._place('',self)
00346
00347 def _okToPlace(self, name, mod, d):
00348 if not self.__InExtendCall:
00349
00350 return True
00351 elif not self.__isStrict:
00352 return True
00353 elif name in d:
00354
00355
00356
00357
00358 if mod._isModified:
00359 if d[name]._isModified:
00360 return False
00361 else:
00362 return True
00363 else:
00364 return True
00365 else:
00366 return True
00367
00368 def _place(self, name, mod, d):
00369 if self._okToPlace(name, mod, d):
00370 if self.__isStrict and isinstance(mod, _ModuleSequenceType):
00371 d[name] = mod._postProcessFixup(self._cloneToObjectDict)
00372 else:
00373 d[name] = mod
00374 if isinstance(mod,_Labelable):
00375 mod.setLabel(name)
00376 def _placeOutputModule(self,name,mod):
00377 self._place(name, mod, self.__outputmodules)
00378 def _placeProducer(self,name,mod):
00379 self._place(name, mod, self.__producers)
00380 def _placeFilter(self,name,mod):
00381 self._place(name, mod, self.__filters)
00382 def _placeAnalyzer(self,name,mod):
00383 self._place(name, mod, self.__analyzers)
00384 def _placePath(self,name,mod):
00385 self._validateSequence(mod, name)
00386 try:
00387 self._place(name, mod, self.__paths)
00388 except ModuleCloneError, msg:
00389 context = format_outerframe(4)
00390 raise Exception("%sThe module %s in path %s is unknown to the process %s." %(context, msg, name, self._Process__name))
00391 def _placeEndPath(self,name,mod):
00392 self._validateSequence(mod, name)
00393 try:
00394 self._place(name, mod, self.__endpaths)
00395 except ModuleCloneError, msg:
00396 context = format_outerframe(4)
00397 raise Exception("%sThe module %s in endpath %s is unknown to the process %s." %(context, msg, name, self._Process__name))
00398 def _placeSequence(self,name,mod):
00399 self._validateSequence(mod, name)
00400 self._place(name, mod, self.__sequences)
00401 def _placeESProducer(self,name,mod):
00402 self._place(name, mod, self.__esproducers)
00403 def _placeESPrefer(self,name,mod):
00404 self._place(name, mod, self.__esprefers)
00405 def _placeESSource(self,name,mod):
00406 self._place(name, mod, self.__essources)
00407 def _placePSet(self,name,mod):
00408 self._place(name, mod, self.__psets)
00409 def _placeVPSet(self,name,mod):
00410 self._place(name, mod, self.__vpsets)
00411 def _placeSource(self,name,mod):
00412 """Allow the source to be referenced by 'source' or by type name"""
00413 if name != 'source':
00414 raise ValueError("The label '"+name+"' can not be used for a Source. Only 'source' is allowed.")
00415 if self.__dict__['_Process__source'] is not None :
00416 del self.__dict__[self.__dict__['_Process__source'].type_()]
00417 self.__dict__['_Process__source'] = mod
00418 self.__dict__[mod.type_()] = mod
00419 def _placeLooper(self,name,mod):
00420 if name != 'looper':
00421 raise ValueError("The label '"+name+"' can not be used for a Looper. Only 'looper' is allowed.")
00422 self.__dict__['_Process__looper'] = mod
00423 self.__dict__[mod.type_()] = mod
00424 def _placeSubProcess(self,name,mod):
00425 if name != 'subProcess':
00426 raise ValueError("The label '"+name+"' can not be used for a SubProcess. Only 'subProcess' is allowed.")
00427 self.__dict__['_Process__subProcess'] = mod
00428 self.__dict__[mod.type_()] = mod
00429 def _placeService(self,typeName,mod):
00430 self._place(typeName, mod, self.__services)
00431 self.__dict__[typeName]=mod
00432 def load(self, moduleName):
00433 moduleName = moduleName.replace("/",".")
00434 module = __import__(moduleName)
00435 self.extend(sys.modules[moduleName])
00436 def extend(self,other,items=()):
00437 """Look in other and find types which we can use"""
00438
00439 self.__dict__['_Process__InExtendCall'] = True
00440
00441 seqs = dict()
00442 labelled = dict()
00443 for name in dir(other):
00444
00445 if name.startswith('_'):
00446 continue
00447 item = getattr(other,name)
00448 if name == "source" or name == "looper" or name == "subProcess":
00449 self.__setattr__(name,item)
00450 elif isinstance(item,_ModuleSequenceType):
00451 seqs[name]=item
00452 elif isinstance(item,_Labelable):
00453 self.__setattr__(name,item)
00454 labelled[name]=item
00455 try:
00456 item.label_()
00457 except:
00458 item.setLabel(name)
00459 continue
00460 elif isinstance(item,Schedule):
00461 self.__setattr__(name,item)
00462 elif isinstance(item,_Unlabelable):
00463 self.add_(item)
00464
00465
00466 for name in seqs.iterkeys():
00467 seq = seqs[name]
00468
00469
00470 if id(seq) not in self._cloneToObjectDict:
00471 self.__setattr__(name,seq)
00472 else:
00473 newSeq = self._cloneToObjectDict[id(seq)]
00474 self.__dict__[name]=newSeq
00475 newSeq.setLabel(name)
00476
00477 newSeq._place(name,self)
00478 self.__dict__['_Process__InExtendCall'] = False
00479 def _dumpConfigNamedList(self,items,typeName,options):
00480 returnValue = ''
00481 for name,item in items:
00482 returnValue +=options.indentation()+typeName+' '+name+' = '+item.dumpConfig(options)
00483 return returnValue
00484 def _dumpConfigUnnamedList(self,items,typeName,options):
00485 returnValue = ''
00486 for name,item in items:
00487 returnValue +=options.indentation()+typeName+' = '+item.dumpConfig(options)
00488 return returnValue
00489 def _dumpConfigOptionallyNamedList(self,items,typeName,options):
00490 returnValue = ''
00491 for name,item in items:
00492 if name == item.type_():
00493 name = ''
00494 returnValue +=options.indentation()+typeName+' '+name+' = '+item.dumpConfig(options)
00495 return returnValue
00496 def dumpConfig(self, options=PrintOptions()):
00497 """return a string containing the equivalent process defined using the old configuration language"""
00498 config = "process "+self.__name+" = {\n"
00499 options.indent()
00500 if self.source_():
00501 config += options.indentation()+"source = "+self.source_().dumpConfig(options)
00502 if self.looper_():
00503 config += options.indentation()+"looper = "+self.looper_().dumpConfig(options)
00504 if self.subProcess_():
00505 config += options.indentation()+"subProcess = "+self.subProcess_().dumpConfig(options)
00506
00507 config+=self._dumpConfigNamedList(self.producers_().iteritems(),
00508 'module',
00509 options)
00510 config+=self._dumpConfigNamedList(self.filters_().iteritems(),
00511 'module',
00512 options)
00513 config+=self._dumpConfigNamedList(self.analyzers_().iteritems(),
00514 'module',
00515 options)
00516 config+=self._dumpConfigNamedList(self.outputModules_().iteritems(),
00517 'module',
00518 options)
00519 config+=self._dumpConfigNamedList(self.sequences_().iteritems(),
00520 'sequence',
00521 options)
00522 config+=self._dumpConfigNamedList(self.paths_().iteritems(),
00523 'path',
00524 options)
00525 config+=self._dumpConfigNamedList(self.endpaths_().iteritems(),
00526 'endpath',
00527 options)
00528 config+=self._dumpConfigUnnamedList(self.services_().iteritems(),
00529 'service',
00530 options)
00531 config+=self._dumpConfigOptionallyNamedList(
00532 self.es_producers_().iteritems(),
00533 'es_module',
00534 options)
00535 config+=self._dumpConfigOptionallyNamedList(
00536 self.es_sources_().iteritems(),
00537 'es_source',
00538 options)
00539 config += self._dumpConfigESPrefers(options)
00540 for name,item in self.psets.iteritems():
00541 config +=options.indentation()+item.configTypeName()+' '+name+' = '+item.configValue(options)
00542 for name,item in self.vpsets.iteritems():
00543 config +=options.indentation()+'VPSet '+name+' = '+item.configValue(options)
00544 if self.schedule:
00545 pathNames = [p.label_() for p in self.schedule]
00546 config +=options.indentation()+'schedule = {'+','.join(pathNames)+'}\n'
00547
00548
00549
00550
00551 config += "}\n"
00552 options.unindent()
00553 return config
00554 def _dumpConfigESPrefers(self, options):
00555 result = ''
00556 for item in self.es_prefers_().itervalues():
00557 result +=options.indentation()+'es_prefer '+item.targetLabel_()+' = '+item.dumpConfig(options)
00558 return result
00559 def _dumpPythonList(self, d, options):
00560 returnValue = ''
00561 if isinstance(d, DictTypes.SortedKeysDict):
00562 for name,item in d.items():
00563 returnValue +='process.'+name+' = '+item.dumpPython(options)+'\n\n'
00564 else:
00565 for name,item in sorted(d.items()):
00566 returnValue +='process.'+name+' = '+item.dumpPython(options)+'\n\n'
00567 return returnValue
00568 def _validateSequence(self, sequence, label):
00569
00570 try:
00571 l = set()
00572 nameVisitor = NodeNameVisitor(l)
00573 sequence.visit(nameVisitor)
00574 except:
00575 raise RuntimeError("An entry in sequence "+label + ' has no label')
00576 def _sequencesInDependencyOrder(self):
00577
00578 returnValue=DictTypes.SortedKeysDict()
00579 dependencies = {}
00580 for label,seq in self.sequences.iteritems():
00581 d = []
00582 v = SequenceVisitor(d)
00583 seq.visit(v)
00584 dependencies[label]=[dep.label_() for dep in d if dep.hasLabel_()]
00585 resolvedDependencies=True
00586
00587
00588 iterCount = 0
00589 while resolvedDependencies:
00590 iterCount += 1
00591 resolvedDependencies = (0 != len(dependencies))
00592 oldDeps = dict(dependencies)
00593 for label,deps in oldDeps.iteritems():
00594
00595 if len(deps)==0 or iterCount > 100:
00596 iterCount = 0
00597 resolvedDependencies=True
00598 returnValue[label]=self.sequences[label]
00599
00600 del dependencies[label]
00601 for lb2,deps2 in dependencies.iteritems():
00602 while deps2.count(label):
00603 deps2.remove(label)
00604 if len(dependencies):
00605 raise RuntimeError("circular sequence dependency discovered \n"+
00606 ",".join([label for label,junk in dependencies.iteritems()]))
00607 return returnValue
00608 def _dumpPython(self, d, options):
00609 result = ''
00610 for name, value in d.iteritems():
00611 result += value.dumpPythonAs(name,options)+'\n'
00612 return result
00613 def dumpPython(self, options=PrintOptions()):
00614 """return a string containing the equivalent process defined using python"""
00615 result = "import FWCore.ParameterSet.Config as cms\n\n"
00616 result += "process = cms.Process(\""+self.__name+"\")\n\n"
00617 if self.source_():
00618 result += "process.source = "+self.source_().dumpPython(options)
00619 if self.looper_():
00620 result += "process.looper = "+self.looper_().dumpPython()
00621 if self.subProcess_():
00622 result += self.subProcess_().dumpPython(options)
00623 result+=self._dumpPythonList(self.producers_(), options)
00624 result+=self._dumpPythonList(self.filters_() , options)
00625 result+=self._dumpPythonList(self.analyzers_(), options)
00626 result+=self._dumpPythonList(self.outputModules_(), options)
00627 result+=self._dumpPythonList(self._sequencesInDependencyOrder(), options)
00628 result+=self._dumpPythonList(self.paths_(), options)
00629 result+=self._dumpPythonList(self.endpaths_(), options)
00630 result+=self._dumpPythonList(self.services_(), options)
00631 result+=self._dumpPythonList(self.es_producers_(), options)
00632 result+=self._dumpPythonList(self.es_sources_(), options)
00633 result+=self._dumpPython(self.es_prefers_(), options)
00634 result+=self._dumpPythonList(self.psets, options)
00635 result+=self._dumpPythonList(self.vpsets, options)
00636 if self.schedule:
00637 pathNames = ['process.'+p.label_() for p in self.schedule]
00638 result +='process.schedule = cms.Schedule(*[ ' + ', '.join(pathNames) + ' ])\n'
00639
00640 return result
00641 def _replaceInSequences(self, label, new):
00642 old = getattr(self,label)
00643
00644 for sequenceable in self.sequences.itervalues():
00645 sequenceable.replace(old,new)
00646 for sequenceable in self.paths.itervalues():
00647 sequenceable.replace(old,new)
00648 for sequenceable in self.endpaths.itervalues():
00649 sequenceable.replace(old,new)
00650 def globalReplace(self,label,new):
00651 """ Replace the item with label 'label' by object 'new' in the process and all sequences/paths"""
00652 if not hasattr(self,label):
00653 raise LookupError("process has no item of label "+label)
00654 self._replaceInSequences(label, new)
00655 setattr(self,label,new)
00656 def _insertInto(self, parameterSet, itemDict):
00657 for name,value in itemDict.iteritems():
00658 value.insertInto(parameterSet, name)
00659 def _insertOneInto(self, parameterSet, label, item, tracked):
00660 vitems = []
00661 if not item == None:
00662 newlabel = item.nameInProcessDesc_(label)
00663 vitems = [newlabel]
00664 item.insertInto(parameterSet, newlabel)
00665 parameterSet.addVString(tracked, label, vitems)
00666 def _insertManyInto(self, parameterSet, label, itemDict, tracked):
00667 l = []
00668 for name,value in itemDict.iteritems():
00669 newLabel = value.nameInProcessDesc_(name)
00670 l.append(newLabel)
00671 value.insertInto(parameterSet, name)
00672
00673 l.sort()
00674 parameterSet.addVString(tracked, label, l)
00675 def _insertPaths(self, processPSet):
00676 scheduledPaths = []
00677 triggerPaths = []
00678 endpaths = []
00679 if self.schedule_() == None:
00680
00681 for name,value in self.paths_().iteritems():
00682 scheduledPaths.append(name)
00683 triggerPaths.append(name)
00684 for name,value in self.endpaths_().iteritems():
00685 scheduledPaths.append(name)
00686 endpaths.append(name)
00687 else:
00688 for path in self.schedule_():
00689 pathname = path.label_()
00690 scheduledPaths.append(pathname)
00691 if self.endpaths_().has_key(pathname):
00692 endpaths.append(pathname)
00693 else:
00694 triggerPaths.append(pathname)
00695 processPSet.addVString(True, "@end_paths", endpaths)
00696 processPSet.addVString(True, "@paths", scheduledPaths)
00697
00698 p = processPSet.newPSet()
00699 p.addVString(True, "@trigger_paths", triggerPaths)
00700 processPSet.addPSet(True, "@trigger_paths", p)
00701
00702 pathValidator = PathValidator()
00703 endpathValidator = EndPathValidator()
00704 for triggername in triggerPaths:
00705
00706 pathValidator.setLabel(triggername)
00707 self.paths_()[triggername].visit(pathValidator)
00708 self.paths_()[triggername].insertInto(processPSet, triggername, self.__dict__)
00709 for endpathname in endpaths:
00710
00711 endpathValidator.setLabel(endpathname)
00712 self.endpaths_()[endpathname].visit(endpathValidator)
00713 self.endpaths_()[endpathname].insertInto(processPSet, endpathname, self.__dict__)
00714 processPSet.addVString(False, "@filters_on_endpaths", endpathValidator.filtersOnEndpaths)
00715
00716 def prune(self):
00717 """ Remove clutter from the process which we think is unnecessary:
00718 tracked PSets, VPSets and unused modules and sequences. If a Schedule has been set, then Paths and EndPaths
00719 not in the schedule will also be removed, along with an modules and sequences used only by
00720 those removed Paths and EndPaths."""
00721 for name in self.psets_():
00722 if getattr(self,name).isTracked():
00723 delattr(self, name)
00724 for name in self.vpsets_():
00725 delattr(self, name)
00726
00727 for x in self.paths.itervalues():
00728 x.resolve(self.__dict__)
00729 for x in self.endpaths.itervalues():
00730 x.resolve(self.__dict__)
00731 usedModules = set()
00732 if self.schedule_():
00733 usedModules=set(self.schedule_().moduleNames())
00734
00735 schedNames = set(( x.label_() for x in self.schedule_()))
00736 names = set(self.paths)
00737 names.update(set(self.endpaths))
00738 junk = names - schedNames
00739 for n in junk:
00740 delattr(self,n)
00741 else:
00742 pths = list(self.paths.itervalues())
00743 pths.extend(self.endpaths.itervalues())
00744 temp = Schedule(*pths)
00745 usedModules=set(temp.moduleNames())
00746 self._pruneModules(self.producers_(), usedModules)
00747 self._pruneModules(self.filters_(), usedModules)
00748 self._pruneModules(self.analyzers_(), usedModules)
00749
00750 seqs = list()
00751 sv = SequenceVisitor(seqs)
00752 for p in self.paths.itervalues():
00753 p.visit(sv)
00754 for p in self.endpaths.itervalues():
00755 p.visit(sv)
00756 keepSeqSet = set(( s for s in seqs if s.hasLabel_()))
00757 availableSeqs = set(self.sequences.itervalues())
00758 for s in availableSeqs-keepSeqSet:
00759 delattr(self,s.label_())
00760
00761 def _pruneModules(self, d, scheduledNames):
00762 moduleNames = set(d.keys())
00763 junk = moduleNames - scheduledNames
00764 for name in junk:
00765 delattr(self, name)
00766
00767 def fillProcessDesc(self, processPSet):
00768 """Used by the framework to convert python to C++ objects"""
00769 class ServiceInjectorAdaptor(object):
00770 def __init__(self,ppset,thelist):
00771 self.__thelist = thelist
00772 self.__processPSet = ppset
00773 def addService(self,pset):
00774 self.__thelist.append(pset)
00775 def newPSet(self):
00776 return self.__processPSet.newPSet()
00777 self.validate()
00778 processPSet.addString(True, "@process_name", self.name_())
00779 all_modules = self.producers_().copy()
00780 all_modules.update(self.filters_())
00781 all_modules.update(self.analyzers_())
00782 all_modules.update(self.outputModules_())
00783 self._insertInto(processPSet, self.psets_())
00784 self._insertInto(processPSet, self.vpsets_())
00785 self._insertManyInto(processPSet, "@all_modules", all_modules, True)
00786 self._insertOneInto(processPSet, "@all_sources", self.source_(), True)
00787 self._insertOneInto(processPSet, "@all_loopers", self.looper_(), True)
00788 self._insertOneInto(processPSet, "@all_subprocesses", self.subProcess_(), False)
00789 self._insertManyInto(processPSet, "@all_esmodules", self.es_producers_(), True)
00790 self._insertManyInto(processPSet, "@all_essources", self.es_sources_(), True)
00791 self._insertManyInto(processPSet, "@all_esprefers", self.es_prefers_(), True)
00792 self._insertPaths(processPSet)
00793
00794 services = []
00795 for n in self.services_():
00796 getattr(self,n).insertInto(ServiceInjectorAdaptor(processPSet,services))
00797 processPSet.addVPSet(False,"services",services)
00798 return processPSet
00799
00800 def validate(self):
00801
00802
00803
00804
00805 pass
00806
00807 def prefer(self, esmodule,*args,**kargs):
00808 """Prefer this ES source or producer. The argument can
00809 either be an object label, e.g.,
00810 process.prefer(process.juicerProducer) (not supported yet)
00811 or a name of an ESSource or ESProducer
00812 process.prefer("juicer")
00813 or a type of unnamed ESSource or ESProducer
00814 process.prefer("JuicerProducer")
00815 In addition, you can pass as a labelled arguments the name of the Record you wish to
00816 prefer where the type passed is a cms.vstring and that vstring can contain the
00817 name of the C++ types in the Record which are being preferred, e.g.,
00818 #prefer all data in record 'OrangeRecord' from 'juicer'
00819 process.prefer("juicer", OrangeRecord=cms.vstring())
00820 or
00821 #prefer only "Orange" data in "OrangeRecord" from "juicer"
00822 process.prefer("juicer", OrangeRecord=cms.vstring("Orange"))
00823 or
00824 #prefer only "Orange" data with label "ExtraPulp" in "OrangeRecord" from "juicer"
00825 ESPrefer("ESJuicerProd", OrangeRecord=cms.vstring("Orange/ExtraPulp"))
00826 """
00827
00828 if isinstance(esmodule, ESSource) or isinstance(esmodule, ESProducer):
00829 raise RuntimeError("Syntax of process.prefer(process.esmodule) not supported yet")
00830 elif self._findPreferred(esmodule, self.es_producers_(),*args,**kargs) or \
00831 self._findPreferred(esmodule, self.es_sources_(),*args,**kargs):
00832 pass
00833 else:
00834 raise RuntimeError("Cannot resolve prefer for "+repr(esmodule))
00835
00836 def _findPreferred(self, esname, d,*args,**kargs):
00837
00838 if esname in d:
00839 typ = d[esname].type_()
00840 if typ == esname:
00841 self.__setattr__( esname+"_prefer", ESPrefer(typ,*args,**kargs) )
00842 else:
00843 self.__setattr__( esname+"_prefer", ESPrefer(typ, esname,*args,**kargs) )
00844 return True
00845 else:
00846
00847 found = False
00848 for name, value in d.iteritems():
00849 if value.type_() == esname:
00850 if found:
00851 raise RuntimeError("More than one ES module for "+esname)
00852 found = True
00853 self.__setattr__(esname+"_prefer", ESPrefer(d[esname].type_()) )
00854 return found
00855
00856 class FilteredStream(dict):
00857 """a dictionary with fixed keys"""
00858 def _blocked_attribute(obj):
00859 raise AttributeError, "An FilteredStream defintion cannot be modified after creation."
00860 _blocked_attribute = property(_blocked_attribute)
00861 __setattr__ = __delitem__ = __setitem__ = clear = _blocked_attribute
00862 pop = popitem = setdefault = update = _blocked_attribute
00863 def __new__(cls, *args, **kw):
00864 new = dict.__new__(cls)
00865 dict.__init__(new, *args, **kw)
00866 keys = kw.keys()
00867 keys.sort()
00868 if keys != ['content', 'dataTier', 'name', 'paths', 'responsible', 'selectEvents']:
00869 raise ValueError("The needed parameters are: content, dataTier, name, paths, responsible, selectEvents")
00870 if not isinstance(kw['name'],str):
00871 raise ValueError("name must be of type string")
00872 if not isinstance(kw['content'], vstring) and not isinstance(kw['content'],str):
00873 raise ValueError("content must be of type vstring or string")
00874 if not isinstance(kw['dataTier'], string):
00875 raise ValueError("dataTier must be of type string")
00876 if not isinstance(kw['selectEvents'], PSet):
00877 raise ValueError("selectEvents must be of type PSet")
00878 if not isinstance(kw['paths'],(tuple, Path)):
00879 raise ValueError("'paths' must be a tuple of paths")
00880 return new
00881 def __init__(self, *args, **kw):
00882 pass
00883 def __repr__(self):
00884 return "FilteredStream object: %s" %self["name"]
00885 def __getattr__(self,attr):
00886 return self[attr]
00887
00888 class SubProcess(_ConfigureComponent,_Unlabelable):
00889 """Allows embedding another process within a parent process. This allows one to
00890 chain processes together directly in one cmsRun job rather than having to run
00891 separate jobs which are connected via a temporary file.
00892 """
00893 def __init__(self,process, SelectEvents = untracked.PSet(), outputCommands = untracked.vstring()):
00894 """
00895 """
00896 if not isinstance(process, Process):
00897 raise ValueError("the 'process' argument must be of type cms.Process")
00898 if not isinstance(SelectEvents,PSet):
00899 raise ValueError("the 'SelectEvents' argument must be of type cms.untracked.PSet")
00900 if not isinstance(outputCommands,vstring):
00901 raise ValueError("the 'outputCommands' argument must be of type cms.untracked.vstring")
00902 self.__process = process
00903 self.__SelectEvents = SelectEvents
00904 self.__outputCommands = outputCommands
00905 def dumpPython(self,options):
00906 out = "parentProcess"+str(hash(self))+" = process\n"
00907 out += self.__process.dumpPython()
00908 out += "childProcess = process\n"
00909 out += "process = parentProcess"+str(hash(self))+"\n"
00910 out += "process.subProcess = cms.SubProcess( process = childProcess, SelectEvents = "+self.__SelectEvents.dumpPython(options) +", outputCommands = "+self.__outputCommands.dumpPython(options) +")\n"
00911 return out
00912 def type_(self):
00913 return 'subProcess'
00914 def nameInProcessDesc_(self,label):
00915 return '@sub_process'
00916 def _place(self,label,process):
00917 process._placeSubProcess('subProcess',self)
00918 def insertInto(self,parameterSet, newlabel):
00919 topPSet = parameterSet.newPSet()
00920 self.__process.fillProcessDesc(topPSet)
00921 subProcessPSet = parameterSet.newPSet()
00922 self.__SelectEvents.insertInto(subProcessPSet,"SelectEvents")
00923 self.__outputCommands.insertInto(subProcessPSet,"outputCommands")
00924 subProcessPSet.addPSet(False,"process",topPSet)
00925 parameterSet.addPSet(False,self.nameInProcessDesc_("subProcess"), subProcessPSet)
00926
00927 if __name__=="__main__":
00928 import unittest
00929 class TestMakePSet(object):
00930 """Has same interface as the C++ object which creates PSets
00931 """
00932 def __init__(self):
00933 self.values = dict()
00934 def __insertValue(self,tracked,label,value):
00935 self.values[label]=(tracked,value)
00936 def addInt32(self,tracked,label,value):
00937 self.__insertValue(tracked,label,value)
00938 def addVInt32(self,tracked,label,value):
00939 self.__insertValue(tracked,label,value)
00940 def addUInt32(self,tracked,label,value):
00941 self.__insertValue(tracked,label,value)
00942 def addVUInt32(self,tracked,label,value):
00943 self.__insertValue(tracked,label,value)
00944 def addInt64(self,tracked,label,value):
00945 self.__insertValue(tracked,label,value)
00946 def addVInt64(self,tracked,label,value):
00947 self.__insertValue(tracked,label,value)
00948 def addUInt64(self,tracked,label,value):
00949 self.__insertValue(tracked,label,value)
00950 def addVUInt64(self,tracked,label,value):
00951 self.__insertValue(tracked,label,value)
00952 def addDouble(self,tracked,label,value):
00953 self.__insertValue(tracked,label,value)
00954 def addVDouble(self,tracked,label,value):
00955 self.__insertValue(tracked,label,value)
00956 def addBool(self,tracked,label,value):
00957 self.__insertValue(tracked,label,value)
00958 def addString(self,tracked,label,value):
00959 self.__insertValue(tracked,label,value)
00960 def addVString(self,tracked,label,value):
00961 self.__insertValue(tracked,label,value)
00962 def addInputTag(self,tracked,label,value):
00963 self.__insertValue(tracked,label,value)
00964 def addVInputTag(self,tracked,label,value):
00965 self.__insertValue(tracked,label,value)
00966 def addESInputTag(self,tracked,label,value):
00967 self.__insertValue(tracked,label,value)
00968 def addVESInputTag(self,tracked,label,value):
00969 self.__insertValue(tracked,label,value)
00970 def addEventID(self,tracked,label,value):
00971 self.__insertValue(tracked,label,value)
00972 def addVEventID(self,tracked,label,value):
00973 self.__insertValue(tracked,label,value)
00974 def addLuminosityBlockID(self,tracked,label,value):
00975 self.__insertValue(tracked,label,value)
00976 def addLuminosityBlockID(self,tracked,label,value):
00977 self.__insertValue(tracked,label,value)
00978 def addEventRange(self,tracked,label,value):
00979 self.__insertValue(tracked,label,value)
00980 def addVEventRange(self,tracked,label,value):
00981 self.__insertValue(tracked,label,value)
00982 def addPSet(self,tracked,label,value):
00983 self.__insertValue(tracked,label,value)
00984 def addVPSet(self,tracked,label,value):
00985 self.__insertValue(tracked,label,value)
00986 def addFileInPath(self,tracked,label,value):
00987 self.__insertValue(tracked,label,value)
00988 def newPSet(self):
00989 return TestMakePSet()
00990
00991 class TestModuleCommand(unittest.TestCase):
00992 def setUp(self):
00993 """Nothing to do """
00994 None
00995 def testParameterizable(self):
00996 p = _Parameterizable()
00997 self.assertEqual(len(p.parameterNames_()),0)
00998 p.a = int32(1)
00999 self.assert_('a' in p.parameterNames_())
01000 self.assertEqual(p.a.value(), 1)
01001 p.a = 10
01002 self.assertEqual(p.a.value(), 10)
01003 p.a = untracked(int32(1))
01004 self.assertEqual(p.a.value(), 1)
01005 self.failIf(p.a.isTracked())
01006 p.a = untracked.int32(1)
01007 self.assertEqual(p.a.value(), 1)
01008 self.failIf(p.a.isTracked())
01009 p = _Parameterizable(foo=int32(10), bar = untracked(double(1.0)))
01010 self.assertEqual(p.foo.value(), 10)
01011 self.assertEqual(p.bar.value(),1.0)
01012 self.failIf(p.bar.isTracked())
01013 self.assertRaises(TypeError,setattr,(p,'c',1))
01014 p = _Parameterizable(a=PSet(foo=int32(10), bar = untracked(double(1.0))))
01015 self.assertEqual(p.a.foo.value(),10)
01016 self.assertEqual(p.a.bar.value(),1.0)
01017 p.b = untracked(PSet(fii = int32(1)))
01018 self.assertEqual(p.b.fii.value(),1)
01019 self.failIf(p.b.isTracked())
01020
01021 v = int32(10)
01022 p=_Parameterizable(a=v)
01023 v.setValue(11)
01024 self.assertEqual(p.a.value(),11)
01025 p.a = 12
01026 self.assertEqual(p.a.value(),12)
01027 self.assertEqual(v.value(),12)
01028 def testTypedParameterizable(self):
01029 p = _TypedParameterizable("blah", b=int32(1))
01030
01031 other = p.copy()
01032 other.b = 2
01033 self.assertNotEqual(p.b,other.b)
01034
01035 def testProcessInsertion(self):
01036 p = Process("test")
01037 p.a = EDAnalyzer("MyAnalyzer")
01038 self.assert_( 'a' in p.analyzers_() )
01039 self.assert_( 'a' in p.analyzers)
01040 p.add_(Service("MessageLogger"))
01041 self.assert_('MessageLogger' in p.services_())
01042 self.assertEqual(p.MessageLogger.type_(), "MessageLogger")
01043 p.Tracer = Service("Tracer")
01044 self.assert_('Tracer' in p.services_())
01045 self.assertRaises(TypeError, setattr, *(p,'b',"this should fail"))
01046 self.assertRaises(TypeError, setattr, *(p,'bad',Service("MessageLogger")))
01047 self.assertRaises(ValueError, setattr, *(p,'bad',Source("PoolSource")))
01048 p.out = OutputModule("Outer")
01049 self.assertEqual(p.out.type_(), 'Outer')
01050 self.assert_( 'out' in p.outputModules_() )
01051
01052 p.geom = ESSource("GeomProd")
01053 self.assert_('geom' in p.es_sources_())
01054 p.add_(ESSource("ConfigDB"))
01055 self.assert_('ConfigDB' in p.es_sources_())
01056
01057 def testProcessExtend(self):
01058 class FromArg(object):
01059 def __init__(self,*arg,**args):
01060 for name in args.iterkeys():
01061 self.__dict__[name]=args[name]
01062
01063 a=EDAnalyzer("MyAnalyzer")
01064 s1 = Sequence(a)
01065 s2 = Sequence(s1)
01066 s3 = Sequence(s2)
01067 d = FromArg(
01068 a=a,
01069 b=Service("Full"),
01070 c=Path(a),
01071 d=s2,
01072 e=s1,
01073 f=s3,
01074 g=Sequence(s1+s2+s3)
01075 )
01076 p = Process("Test")
01077 p.extend(d)
01078 self.assertEqual(p.a.type_(),"MyAnalyzer")
01079 self.assertRaises(AttributeError,getattr,p,'b')
01080 self.assertEqual(p.Full.type_(),"Full")
01081 self.assertEqual(str(p.c),'a')
01082 self.assertEqual(str(p.d),'a')
01083
01084 def testProcessDumpPython(self):
01085 p = Process("test")
01086 p.a = EDAnalyzer("MyAnalyzer")
01087 p.p = Path(p.a)
01088 p.s = Sequence(p.a)
01089 p.r = Sequence(p.s)
01090 p.p2 = Path(p.s)
01091 p.schedule = Schedule(p.p2,p.p)
01092 d=p.dumpPython()
01093 self.assertEqual(d,
01094 """import FWCore.ParameterSet.Config as cms
01095
01096 process = cms.Process("test")
01097
01098 process.a = cms.EDAnalyzer("MyAnalyzer")
01099
01100
01101 process.s = cms.Sequence(process.a)
01102
01103
01104 process.r = cms.Sequence(process.s)
01105
01106
01107 process.p = cms.Path(process.a)
01108
01109
01110 process.p2 = cms.Path(process.s)
01111
01112
01113 process.schedule = cms.Schedule(*[ process.p2, process.p ])
01114 """)
01115
01116 p = Process("test")
01117 p.a = EDAnalyzer("MyAnalyzer")
01118 p.p = Path(p.a)
01119 p.r = Sequence(p.a)
01120 p.s = Sequence(p.r)
01121 p.p2 = Path(p.r)
01122 p.schedule = Schedule(p.p2,p.p)
01123 p.b = EDAnalyzer("YourAnalyzer")
01124 d=p.dumpPython()
01125 self.assertEqual(d,
01126 """import FWCore.ParameterSet.Config as cms
01127
01128 process = cms.Process("test")
01129
01130 process.a = cms.EDAnalyzer("MyAnalyzer")
01131
01132
01133 process.b = cms.EDAnalyzer("YourAnalyzer")
01134
01135
01136 process.r = cms.Sequence(process.a)
01137
01138
01139 process.s = cms.Sequence(process.r)
01140
01141
01142 process.p = cms.Path(process.a)
01143
01144
01145 process.p2 = cms.Path(process.r)
01146
01147
01148 process.schedule = cms.Schedule(*[ process.p2, process.p ])
01149 """)
01150
01151 p = Process("test")
01152 p.a = EDAnalyzer("MyAnalyzer")
01153 p.p = Path(p.a)
01154 s = Sequence(p.a)
01155 p.r = Sequence(s)
01156 p.p2 = Path(p.r)
01157 p.schedule = Schedule(p.p2,p.p)
01158 d=p.dumpPython()
01159 self.assertEqual(d,
01160 """import FWCore.ParameterSet.Config as cms
01161
01162 process = cms.Process("test")
01163
01164 process.a = cms.EDAnalyzer("MyAnalyzer")
01165
01166
01167 process.r = cms.Sequence((process.a))
01168
01169
01170 process.p = cms.Path(process.a)
01171
01172
01173 process.p2 = cms.Path(process.r)
01174
01175
01176 process.schedule = cms.Schedule(*[ process.p2, process.p ])
01177 """)
01178
01179 def testSecSource(self):
01180 p = Process('test')
01181 p.a = SecSource("MySecSource")
01182 self.assertEqual(p.dumpPython().replace('\n',''),'import FWCore.ParameterSet.Config as cmsprocess = cms.Process("test")process.a = cms.SecSource("MySecSource")')
01183
01184 def testGlobalReplace(self):
01185 p = Process('test')
01186 p.a = EDAnalyzer("MyAnalyzer")
01187 p.b = EDAnalyzer("YourAnalyzer")
01188 p.c = EDAnalyzer("OurAnalyzer")
01189 p.s = Sequence(p.a*p.b)
01190 p.p = Path(p.c+p.s+p.a)
01191 new = EDAnalyzer("NewAnalyzer")
01192 p.globalReplace("a",new)
01193
01194 def testSequence(self):
01195 p = Process('test')
01196 p.a = EDAnalyzer("MyAnalyzer")
01197 p.b = EDAnalyzer("YourAnalyzer")
01198 p.c = EDAnalyzer("OurAnalyzer")
01199 p.s = Sequence(p.a*p.b)
01200 self.assertEqual(str(p.s),'a+b')
01201 self.assertEqual(p.s.label_(),'s')
01202 path = Path(p.c+p.s)
01203 self.assertEqual(str(path),'c+a+b')
01204 p._validateSequence(path, 'p1')
01205 notInProcess = EDAnalyzer('NotInProcess')
01206 p2 = Path(p.c+p.s*notInProcess)
01207 self.assertRaises(RuntimeError, p._validateSequence, p2, 'p2')
01208
01209 def testPath(self):
01210 p = Process("test")
01211 p.a = EDAnalyzer("MyAnalyzer")
01212 p.b = EDAnalyzer("YourAnalyzer")
01213 p.c = EDAnalyzer("OurAnalyzer")
01214 path = Path(p.a)
01215 path *= p.b
01216 path += p.c
01217 self.assertEqual(str(path),'a+b+c')
01218 path = Path(p.a*p.b+p.c)
01219 self.assertEqual(str(path),'a+b+c')
01220
01221
01222 path = Path(p.a+ p.b*p.c)
01223 self.assertEqual(str(path),'a+b+c')
01224 path = Path(p.a*(p.b+p.c))
01225 self.assertEqual(str(path),'a+b+c')
01226 path = Path(p.a*(p.b+~p.c))
01227 self.assertEqual(str(path),'a+b+~c')
01228 p.es = ESProducer("AnESProducer")
01229 self.assertRaises(TypeError,Path,p.es)
01230
01231 def testCloneSequence(self):
01232 p = Process("test")
01233 a = EDAnalyzer("MyAnalyzer")
01234 p.a = a
01235 a.setLabel("a")
01236 b = EDAnalyzer("YOurAnalyzer")
01237 p.b = b
01238 b.setLabel("b")
01239 path = Path(a * b)
01240 p.path = Path(p.a*p.b)
01241 lookuptable = {id(a): p.a, id(b): p.b}
01242
01243
01244
01245 self.assertEqual(str(path),str(p.path))
01246
01247 def testSchedule(self):
01248 p = Process("test")
01249 p.a = EDAnalyzer("MyAnalyzer")
01250 p.b = EDAnalyzer("YourAnalyzer")
01251 p.c = EDAnalyzer("OurAnalyzer")
01252 p.d = EDAnalyzer("OurAnalyzer")
01253 p.path1 = Path(p.a)
01254 p.path2 = Path(p.b)
01255 p.path3 = Path(p.d)
01256
01257 s = Schedule(p.path1,p.path2)
01258 self.assertEqual(s[0],p.path1)
01259 self.assertEqual(s[1],p.path2)
01260 p.schedule = s
01261 self.assert_('b' in p.schedule.moduleNames())
01262 self.assert_(hasattr(p, 'b'))
01263 self.assert_(hasattr(p, 'c'))
01264 self.assert_(hasattr(p, 'd'))
01265 self.assert_(hasattr(p, 'path1'))
01266 self.assert_(hasattr(p, 'path2'))
01267 self.assert_(hasattr(p, 'path3'))
01268 p.prune()
01269 self.assert_('b' in p.schedule.moduleNames())
01270 self.assert_(hasattr(p, 'b'))
01271 self.assert_(not hasattr(p, 'c'))
01272 self.assert_(not hasattr(p, 'd'))
01273 self.assert_(hasattr(p, 'path1'))
01274 self.assert_(hasattr(p, 'path2'))
01275 self.assert_(not hasattr(p, 'path3'))
01276
01277
01278 p = Process("test")
01279 p.a = EDAnalyzer("MyAnalyzer")
01280 path1 = Path(p.a)
01281 s = Schedule(path1)
01282 self.assertRaises(RuntimeError, lambda : p.setSchedule_(s) )
01283
01284
01285 p = Process("test")
01286 p.a = EDAnalyzer("MyAnalyzer")
01287 p.b = EDAnalyzer("MyOtherAnalyzer")
01288 p.c = EDProducer("MyProd")
01289 path1 = Path(p.c*Sequence(p.a+p.b))
01290 s = Schedule(path1)
01291 self.assert_('a' in s.moduleNames())
01292 self.assert_('b' in s.moduleNames())
01293 self.assert_('c' in s.moduleNames())
01294 p.path1 = path1
01295 p.schedule = s
01296 p.prune()
01297 self.assert_('a' in s.moduleNames())
01298 self.assert_('b' in s.moduleNames())
01299 self.assert_('c' in s.moduleNames())
01300
01301 def testImplicitSchedule(self):
01302 p = Process("test")
01303 p.a = EDAnalyzer("MyAnalyzer")
01304 p.b = EDAnalyzer("YourAnalyzer")
01305 p.c = EDAnalyzer("OurAnalyzer")
01306 p.path1 = Path(p.a)
01307 p.path2 = Path(p.b)
01308 self.assert_(p.schedule is None)
01309 pths = p.paths
01310 keys = pths.keys()
01311 self.assertEqual(pths[keys[0]],p.path1)
01312 self.assertEqual(pths[keys[1]],p.path2)
01313 p.prune()
01314 self.assert_(hasattr(p, 'a'))
01315 self.assert_(hasattr(p, 'b'))
01316 self.assert_(not hasattr(p, 'c'))
01317 self.assert_(hasattr(p, 'path1'))
01318 self.assert_(hasattr(p, 'path2'))
01319
01320
01321 p = Process("test")
01322 p.a = EDAnalyzer("MyAnalyzer")
01323 p.b = EDAnalyzer("YourAnalyzer")
01324 p.c = EDAnalyzer("OurAnalyzer")
01325 p.path2 = Path(p.b)
01326 p.path1 = Path(p.a)
01327 self.assert_(p.schedule is None)
01328 pths = p.paths
01329 keys = pths.keys()
01330 self.assertEqual(pths[keys[1]],p.path1)
01331 self.assertEqual(pths[keys[0]],p.path2)
01332
01333
01334 def testUsing(self):
01335 p = Process('test')
01336 p.block = PSet(a = int32(1))
01337 p.modu = EDAnalyzer('Analyzer', p.block, b = int32(2))
01338 self.assertEqual(p.modu.a.value(),1)
01339 self.assertEqual(p.modu.b.value(),2)
01340
01341 def testOverride(self):
01342 p = Process('test')
01343 a = EDProducer("A", a1=int32(0))
01344 self.assert_(not a.isModified())
01345 a.a1 = 1
01346 self.assert_(a.isModified())
01347 p.a = a
01348 self.assertEqual(p.a.a1.value(), 1)
01349
01350
01351 p.a = EDProducer("A", a1=int32(2))
01352 self.assertEqual(p.a.a1.value(), 2)
01353
01354
01355
01356 b = EDProducer("A", a1=int32(3))
01357 b.a1 = 4
01358
01359 ps1 = PSet(a = int32(1))
01360 ps2 = PSet(a = int32(2))
01361 self.assertRaises(ValueError, EDProducer, 'C', ps1, ps2)
01362 self.assertRaises(ValueError, EDProducer, 'C', ps1, a=int32(3))
01363
01364 def testExamples(self):
01365 p = Process("Test")
01366 p.source = Source("PoolSource",fileNames = untracked(string("file:reco.root")))
01367 p.foos = EDProducer("FooProducer")
01368 p.bars = EDProducer("BarProducer", foos=InputTag("foos"))
01369 p.out = OutputModule("PoolOutputModule",fileName=untracked(string("file:foos.root")))
01370 p.bars.foos = 'Foosball'
01371 self.assertEqual(p.bars.foos, InputTag('Foosball'))
01372 p.p = Path(p.foos*p.bars)
01373 p.e = EndPath(p.out)
01374 p.add_(Service("MessageLogger"))
01375
01376 def testPrefers(self):
01377 p = Process("Test")
01378 p.add_(ESSource("ForceSource"))
01379 p.juicer = ESProducer("JuicerProducer")
01380 p.prefer("ForceSource")
01381 p.prefer("juicer")
01382 self.assertEqual(p.dumpConfig(),
01383 """process Test = {
01384 es_module juicer = JuicerProducer {
01385 }
01386 es_source = ForceSource {
01387 }
01388 es_prefer = ForceSource {
01389 }
01390 es_prefer juicer = JuicerProducer {
01391 }
01392 }
01393 """)
01394 p.prefer("juicer",fooRcd=vstring("Foo"))
01395 self.assertEqual(p.dumpConfig(),
01396 """process Test = {
01397 es_module juicer = JuicerProducer {
01398 }
01399 es_source = ForceSource {
01400 }
01401 es_prefer = ForceSource {
01402 }
01403 es_prefer juicer = JuicerProducer {
01404 vstring fooRcd = {
01405 'Foo'
01406 }
01407
01408 }
01409 }
01410 """)
01411 self.assertEqual(p.dumpPython(),
01412 """import FWCore.ParameterSet.Config as cms
01413
01414 process = cms.Process("Test")
01415
01416 process.juicer = cms.ESProducer("JuicerProducer")
01417
01418
01419 process.ForceSource = cms.ESSource("ForceSource")
01420
01421
01422 process.prefer("ForceSource")
01423
01424 process.prefer("juicer",
01425 fooRcd = cms.vstring('Foo')
01426 )
01427
01428 """)
01429
01430 def testFreeze(self):
01431 process = Process("Freeze")
01432 m = EDProducer("M", p=PSet(i = int32(1)))
01433 m.p.i = 2
01434 process.m = m
01435
01436
01437
01438
01439
01440
01441 process.m.p.i = 4
01442 self.assertEqual(process.m.p.i.value(), 4)
01443 process.m.p = PSet(j=int32(1))
01444
01445 m2 = m.clone(p = PSet(i = int32(5)), j = int32(8))
01446 m2.p.i = 6
01447 m2.j = 8
01448 def testSubProcess(self):
01449 process = Process("Parent")
01450 subProcess = Process("Child")
01451 subProcess.a = EDProducer("A")
01452 subProcess.p = Path(subProcess.a)
01453 subProcess.add_(Service("Foo"))
01454 process.add_( SubProcess(subProcess) )
01455 d = process.dumpPython()
01456 equalD ="""import FWCore.ParameterSet.Config as cms
01457
01458 process = cms.Process("Parent")
01459
01460 parentProcess = process
01461 import FWCore.ParameterSet.Config as cms
01462
01463 process = cms.Process("Child")
01464
01465 process.a = cms.EDProducer("A")
01466
01467
01468 process.p = cms.Path(process.a)
01469
01470
01471 process.Foo = cms.Service("Foo")
01472
01473
01474 childProcess = process
01475 process = parentProcess
01476 process.subProcess = cms.SubProcess( process = childProcess, SelectEvents = cms.untracked.PSet(
01477
01478 ), outputCommands = cms.untracked.vstring())
01479 """
01480 equalD = equalD.replace("parentProcess","parentProcess"+str(hash(process.subProcess)))
01481 self.assertEqual(d,equalD)
01482 p = TestMakePSet()
01483 process.subProcess.insertInto(p,"dummy")
01484 self.assertEqual((True,['a']),p.values["@sub_process"][1].values["process"][1].values['@all_modules'])
01485 self.assertEqual((True,['p']),p.values["@sub_process"][1].values["process"][1].values['@paths'])
01486 self.assertEqual({'@service_type':(True,'Foo')}, p.values["@sub_process"][1].values["process"][1].values["services"][1][0].values)
01487 def testPrune(self):
01488 p = Process("test")
01489 p.a = EDAnalyzer("MyAnalyzer")
01490 p.b = EDAnalyzer("YourAnalyzer")
01491 p.c = EDAnalyzer("OurAnalyzer")
01492 p.d = EDAnalyzer("OurAnalyzer")
01493 p.s = Sequence(p.d)
01494 p.path1 = Path(p.a)
01495 p.path2 = Path(p.b)
01496 self.assert_(p.schedule is None)
01497 pths = p.paths
01498 keys = pths.keys()
01499 self.assertEqual(pths[keys[0]],p.path1)
01500 self.assertEqual(pths[keys[1]],p.path2)
01501 p.prune()
01502 self.assert_(hasattr(p, 'a'))
01503 self.assert_(hasattr(p, 'b'))
01504 self.assert_(not hasattr(p, 'c'))
01505 self.assert_(not hasattr(p, 'd'))
01506 self.assert_(not hasattr(p, 's'))
01507 self.assert_(hasattr(p, 'path1'))
01508 self.assert_(hasattr(p, 'path2'))
01509
01510 p = Process("test")
01511 p.a = EDAnalyzer("MyAnalyzer")
01512 p.b = EDAnalyzer("YourAnalyzer")
01513 p.c = EDAnalyzer("OurAnalyzer")
01514 p.d = EDAnalyzer("OurAnalyzer")
01515 p.e = EDAnalyzer("OurAnalyzer")
01516 p.s = Sequence(p.d)
01517 p.s2 = Sequence(p.b)
01518 p.s3 = Sequence(p.e)
01519 p.path1 = Path(p.a)
01520 p.path2 = Path(p.b)
01521 p.path3 = Path(p.b+p.s2)
01522 p.path4 = Path(p.b+p.s3)
01523 p.schedule = Schedule(p.path1,p.path2,p.path3)
01524 pths = p.paths
01525 keys = pths.keys()
01526 self.assertEqual(pths[keys[0]],p.path1)
01527 self.assertEqual(pths[keys[1]],p.path2)
01528 p.prune()
01529 self.assert_(hasattr(p, 'a'))
01530 self.assert_(hasattr(p, 'b'))
01531 self.assert_(not hasattr(p, 'c'))
01532 self.assert_(not hasattr(p, 'd'))
01533 self.assert_(not hasattr(p, 'e'))
01534 self.assert_(not hasattr(p, 's'))
01535 self.assert_(hasattr(p, 's2'))
01536 self.assert_(not hasattr(p, 's3'))
01537 self.assert_(hasattr(p, 'path1'))
01538 self.assert_(hasattr(p, 'path2'))
01539 self.assert_(hasattr(p, 'path3'))
01540 self.assert_(not hasattr(p, 'path4'))
01541
01542 p = Process("test")
01543 p.a = EDAnalyzer("MyAnalyzer")
01544 p.b = EDAnalyzer("YourAnalyzer")
01545 p.s = Sequence(SequencePlaceholder("a")+p.b)
01546 p.pth = Path(p.s)
01547 p.prune()
01548 self.assert_(hasattr(p, 'a'))
01549 self.assert_(hasattr(p, 'b'))
01550 self.assert_(hasattr(p, 's'))
01551 self.assert_(hasattr(p, 'pth'))
01552
01553 unittest.main()