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