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