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