CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Config.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 ### command line options helper
4 from Options import Options
5 options = Options()
6 
7 
8 ## imports
9 import sys
10 from Mixins import PrintOptions,_ParameterTypeBase,_SimpleParameterTypeBase, _Parameterizable, _ConfigureComponent, _TypedParameterizable, _Labelable, _Unlabelable, _ValidatingListBase, _modifyParametersFromDict
11 from Mixins import *
12 from Types import *
13 from Modules import *
14 from Modules import _Module
15 from SequenceTypes import *
16 from SequenceTypes import _ModuleSequenceType, _Sequenceable #extend needs it
17 from SequenceVisitors import PathValidator, EndPathValidator
18 import DictTypes
19 
20 from ExceptionHandling import *
21 
22 #when building RECO paths we have hit the default recursion limit
23 if sys.getrecursionlimit()<5000:
24  sys.setrecursionlimit(5000)
25 
26 def checkImportPermission(minLevel = 2, allowedPatterns = []):
27  """
28  Raise an exception if called by special config files. This checks
29  the call or import stack for the importing file. An exception is raised if
30  the importing module is not in allowedPatterns and if it is called too deeply:
31  minLevel = 2: inclusion by top lvel cfg only
32  minLevel = 1: No inclusion allowed
33  allowedPatterns = ['Module1','Module2/SubModule1'] allows import
34  by any module in Module1 or Submodule1
35  """
36 
37  import inspect
38  import os
39 
40  ignorePatterns = ['FWCore/ParameterSet/Config.py','<string>']
41  CMSSWPath = [os.environ['CMSSW_BASE'],os.environ['CMSSW_RELEASE_BASE']]
42 
43  # Filter the stack to things in CMSSWPath and not in ignorePatterns
44  trueStack = []
45  for item in inspect.stack():
46  inPath = False
47  ignore = False
48 
49  for pattern in CMSSWPath:
50  if item[1].find(pattern) != -1:
51  inPath = True
52  break
53  if item[1].find('/') == -1: # The base file, no path
54  inPath = True
55 
56  for pattern in ignorePatterns:
57  if item[1].find(pattern) != -1:
58  ignore = True
59  break
60 
61  if inPath and not ignore:
62  trueStack.append(item[1])
63 
64  importedFile = trueStack[0]
65  importedBy = ''
66  if len(trueStack) > 1:
67  importedBy = trueStack[1]
68 
69  for pattern in allowedPatterns:
70  if importedBy.find(pattern) > -1:
71  return True
72 
73  if len(trueStack) <= minLevel: # Imported directly
74  return True
75 
76  raise ImportError("Inclusion of %s is allowed only by cfg or specified cfi files."
77  % importedFile)
78 
79 def findProcess(module):
80  """Look inside the module and find the Processes it contains"""
81  class Temp(object):
82  pass
83  process = None
84  if isinstance(module,dict):
85  if 'process' in module:
86  p = module['process']
87  module = Temp()
88  module.process = p
89  if hasattr(module,'process'):
90  if isinstance(module.process,Process):
91  process = module.process
92  else:
93  raise RuntimeError("The attribute named 'process' does not inherit from the Process class")
94  else:
95  raise RuntimeError("no 'process' attribute found in the module, please add one")
96  return process
97 
98 
99 class Process(object):
100  """Root class for a CMS configuration process"""
101  def __init__(self,name,*Mods):
102  """The argument 'name' will be the name applied to this Process
103  Can optionally pass as additional arguments cms.Modifier instances
104  that will be used to modify the Process as it is built
105  """
106  self.__dict__['_Process__name'] = name
107  if not name.isalnum():
108  raise RuntimeError("Error: The process name is an empty string or contains non-alphanumeric characters")
109  self.__dict__['_Process__filters'] = {}
110  self.__dict__['_Process__producers'] = {}
111  self.__dict__['_Process__source'] = None
112  self.__dict__['_Process__looper'] = None
113  self.__dict__['_Process__subProcesses'] = []
114  self.__dict__['_Process__schedule'] = None
115  self.__dict__['_Process__analyzers'] = {}
116  self.__dict__['_Process__outputmodules'] = {}
117  self.__dict__['_Process__paths'] = DictTypes.SortedKeysDict() # have to keep the order
118  self.__dict__['_Process__endpaths'] = DictTypes.SortedKeysDict() # of definition
119  self.__dict__['_Process__sequences'] = {}
120  self.__dict__['_Process__services'] = {}
121  self.__dict__['_Process__essources'] = {}
122  self.__dict__['_Process__esproducers'] = {}
123  self.__dict__['_Process__esprefers'] = {}
124  self.__dict__['_Process__aliases'] = {}
125  self.__dict__['_Process__psets']={}
126  self.__dict__['_Process__vpsets']={}
127  self.__dict__['_cloneToObjectDict'] = {}
128  # policy switch to avoid object overwriting during extend/load
129  self.__dict__['_Process__InExtendCall'] = False
130  self.__dict__['_Process__partialschedules'] = {}
131  self.__isStrict = False
132  self.__dict__['_Process__modifiers'] = Mods
133  for m in self.__modifiers:
134  m._setChosen()
135 
136  def setStrict(self, value):
137  self.__isStrict = value
138  _Module.__isStrict__ = True
139 
140  # some user-friendly methods for command-line browsing
141  def producerNames(self):
142  """Returns a string containing all the EDProducer labels separated by a blank"""
143  return ' '.join(self.producers_().keys())
144  def analyzerNames(self):
145  """Returns a string containing all the EDAnalyzer labels separated by a blank"""
146  return ' '.join(self.analyzers_().keys())
147  def filterNames(self):
148  """Returns a string containing all the EDFilter labels separated by a blank"""
149  return ' '.join(self.filters_().keys())
150  def pathNames(self):
151  """Returns a string containing all the Path names separated by a blank"""
152  return ' '.join(self.paths_().keys())
153 
154  def __setstate__(self, pkldict):
155  """
156  Unpickling hook.
157 
158  Since cloneToObjectDict stores a hash of objects by their
159  id() it needs to be updated when unpickling to use the
160  new object id values instantiated during the unpickle.
161 
162  """
163  self.__dict__.update(pkldict)
164  tmpDict = {}
165  for value in self._cloneToObjectDict.values():
166  tmpDict[id(value)] = value
167  self.__dict__['_cloneToObjectDict'] = tmpDict
168 
169 
170 
171  def filters_(self):
172  """returns a dict of the filters that have been added to the Process"""
173  return DictTypes.FixedKeysDict(self.__filters)
174  filters = property(filters_, doc="dictionary containing the filters for the process")
175  def name_(self):
176  return self.__name
177  def setName_(self,name):
178  if not name.isalnum():
179  raise RuntimeError("Error: The process name is an empty string or contains non-alphanumeric characters")
180  self.__dict__['_Process__name'] = name
181  process = property(name_,setName_, doc="name of the process")
182  def producers_(self):
183  """returns a dict of the producers that have been added to the Process"""
184  return DictTypes.FixedKeysDict(self.__producers)
185  producers = property(producers_,doc="dictionary containing the producers for the process")
186  def source_(self):
187  """returns the source that has been added to the Process or None if none have been added"""
188  return self.__source
189  def setSource_(self,src):
190  self._placeSource('source',src)
191  source = property(source_,setSource_,doc='the main source or None if not set')
192  def looper_(self):
193  """returns the looper that has been added to the Process or None if none have been added"""
194  return self.__looper
195  def setLooper_(self,lpr):
196  self._placeLooper('looper',lpr)
197  looper = property(looper_,setLooper_,doc='the main looper or None if not set')
198  def subProcesses_(self):
199  """returns a list of the subProcesses that have been added to the Process"""
200  return self.__subProcesses
201  subProcesses = property(subProcesses_,doc='the SubProcesses that have been added to the Process')
202  def analyzers_(self):
203  """returns a dict of the analyzers that have been added to the Process"""
204  return DictTypes.FixedKeysDict(self.__analyzers)
205  analyzers = property(analyzers_,doc="dictionary containing the analyzers for the process")
206  def outputModules_(self):
207  """returns a dict of the output modules that have been added to the Process"""
208  return DictTypes.FixedKeysDict(self.__outputmodules)
209  outputModules = property(outputModules_,doc="dictionary containing the output_modules for the process")
210  def paths_(self):
211  """returns a dict of the paths that have been added to the Process"""
212  return DictTypes.SortedAndFixedKeysDict(self.__paths)
213  paths = property(paths_,doc="dictionary containing the paths for the process")
214  def endpaths_(self):
215  """returns a dict of the endpaths that have been added to the Process"""
216  return DictTypes.SortedAndFixedKeysDict(self.__endpaths)
217  endpaths = property(endpaths_,doc="dictionary containing the endpaths for the process")
218  def sequences_(self):
219  """returns a dict of the sequences that have been added to the Process"""
220  return DictTypes.FixedKeysDict(self.__sequences)
221  sequences = property(sequences_,doc="dictionary containing the sequences for the process")
222  def schedule_(self):
223  """returns the schedule that has been added to the Process or None if none have been added"""
224  return self.__schedule
225  def setPartialSchedule_(self,sch,label):
226  if label == "schedule":
227  self.setSchedule_(sch)
228  else:
229  self._place(label, sch, self.__partialschedules)
230  def setSchedule_(self,sch):
231  # See if every module has been inserted into the process
232  index = 0
233  try:
234  for p in sch:
235  p.label_()
236  index +=1
237  except:
238  raise RuntimeError("The path at index "+str(index)+" in the Schedule was not attached to the process.")
239 
240  self.__dict__['_Process__schedule'] = sch
241  schedule = property(schedule_,setSchedule_,doc='the schedule or None if not set')
242  def services_(self):
243  """returns a dict of the services that have been added to the Process"""
244  return DictTypes.FixedKeysDict(self.__services)
245  services = property(services_,doc="dictionary containing the services for the process")
246  def es_producers_(self):
247  """returns a dict of the esproducers that have been added to the Process"""
248  return DictTypes.FixedKeysDict(self.__esproducers)
249  es_producers = property(es_producers_,doc="dictionary containing the es_producers for the process")
250  def es_sources_(self):
251  """returns a the es_sources that have been added to the Process"""
252  return DictTypes.FixedKeysDict(self.__essources)
253  es_sources = property(es_sources_,doc="dictionary containing the es_sources for the process")
254  def es_prefers_(self):
255  """returns a dict of the es_prefers that have been added to the Process"""
256  return DictTypes.FixedKeysDict(self.__esprefers)
257  es_prefers = property(es_prefers_,doc="dictionary containing the es_prefers for the process")
258  def aliases_(self):
259  """returns a dict of the aliases that have been added to the Process"""
260  return DictTypes.FixedKeysDict(self.__aliases)
261  aliases = property(aliases_,doc="dictionary containing the aliases for the process")
262  def psets_(self):
263  """returns a dict of the PSets that have been added to the Process"""
264  return DictTypes.FixedKeysDict(self.__psets)
265  psets = property(psets_,doc="dictionary containing the PSets for the process")
266  def vpsets_(self):
267  """returns a dict of the VPSets that have been added to the Process"""
268  return DictTypes.FixedKeysDict(self.__vpsets)
269  vpsets = property(vpsets_,doc="dictionary containing the PSets for the process")
270 
271  def __setObjectLabel(self, object, newLabel) :
272  if not object.hasLabel_() :
273  object.setLabel(newLabel)
274  return
275  if newLabel == object.label_() :
276  return
277  if newLabel is None :
278  object.setLabel(None)
279  return
280  if (hasattr(self, object.label_()) and id(getattr(self, object.label_())) == id(object)) :
281  msg100 = "Attempting to change the label of an attribute of the Process\n"
282  msg101 = "Old label = "+object.label_()+" New label = "+newLabel+"\n"
283  msg102 = "Type = "+str(type(object))+"\n"
284  msg103 = "Some possible solutions:\n"
285  msg104 = " 1. Clone modules instead of using simple assignment. Cloning is\n"
286  msg105 = " also preferred for other types when possible.\n"
287  msg106 = " 2. Declare new names starting with an underscore if they are\n"
288  msg107 = " for temporaries you do not want propagated into the Process. The\n"
289  msg108 = " underscore tells \"from x import *\" and process.load not to import\n"
290  msg109 = " the name.\n"
291  msg110 = " 3. Reorganize so the assigment is not necessary. Giving a second\n"
292  msg111 = " name to the same object usually causes confusion and problems.\n"
293  msg112 = " 4. Compose Sequences: newName = cms.Sequence(oldName)\n"
294  raise ValueError(msg100+msg101+msg102+msg103+msg104+msg105+msg106+msg107+msg108+msg109+msg110+msg111+msg112)
295  object.setLabel(None)
296  object.setLabel(newLabel)
297 
298  def __setattr__(self,name,value):
299  # check if the name is well-formed (only _ and alphanumerics are allowed)
300  if not name.replace('_','').isalnum():
301  raise ValueError('The label '+name+' contains forbiden characters')
302 
303  # private variable exempt from all this
304  if name.startswith('_Process__'):
305  self.__dict__[name]=value
306  return
307  if not isinstance(value,_ConfigureComponent):
308  raise TypeError("can only assign labels to an object that inherits from '_ConfigureComponent'\n"
309  +"an instance of "+str(type(value))+" will not work - requested label is "+name)
310  if not isinstance(value,_Labelable) and not isinstance(value,Source) and not isinstance(value,Looper) and not isinstance(value,Schedule):
311  if name == value.type_():
312  self.add_(value)
313  return
314  else:
315  raise TypeError("an instance of "+str(type(value))+" can not be assigned the label '"+name+"'.\n"+
316  "Please either use the label '"+value.type_()+" or use the 'add_' method instead.")
317  #clone the item
318  if self.__isStrict:
319  newValue =value.copy()
320  try:
321  newValue._filename = value._filename
322  except:
323  pass
324  value.setIsFrozen()
325  else:
326  newValue =value
327  if not self._okToPlace(name, value, self.__dict__):
328  newFile='top level config'
329  if hasattr(value,'_filename'):
330  newFile = value._filename
331  oldFile='top level config'
332  oldValue = getattr(self,name)
333  if hasattr(oldValue,'_filename'):
334  oldFile = oldValue._filename
335  msg = "Trying to override definition of process."+name
336  msg += "\n new object defined in: "+newFile
337  msg += "\n existing object defined in: "+oldFile
338  raise ValueError(msg)
339  # remove the old object of the name (if there is one)
340  if hasattr(self,name) and not (getattr(self,name)==newValue):
341  # Compain if items in sequences from load() statements have
342  # degeneratate names, but if the user overwrites a name in the
343  # main config, replace it everywhere
344  if isinstance(newValue, _Sequenceable):
345  if not self.__InExtendCall:
346  self._replaceInSequences(name, newValue)
347  else:
348  #should check to see if used in sequence before complaining
349  newFile='top level config'
350  if hasattr(value,'_filename'):
351  newFile = value._filename
352  oldFile='top level config'
353  oldValue = getattr(self,name)
354  if hasattr(oldValue,'_filename'):
355  oldFile = oldValue._filename
356  msg1 = "Trying to override definition of "+name+" while it is used by the sequence "
357  msg2 = "\n new object defined in: "+newFile
358  msg2 += "\n existing object defined in: "+oldFile
359  s = self.__findFirstSequenceUsingModule(self.sequences,oldValue)
360  if s is not None:
361  raise ValueError(msg1+s.label_()+msg2)
362  s = self.__findFirstSequenceUsingModule(self.paths,oldValue)
363  if s is not None:
364  raise ValueError(msg1+s.label_()+msg2)
365  s = self.__findFirstSequenceUsingModule(self.endpaths,oldValue)
366  if s is not None:
367  raise ValueError(msg1+s.label_()+msg2)
368  self.__delattr__(name)
369  self.__dict__[name]=newValue
370  if isinstance(newValue,_Labelable):
371  self.__setObjectLabel(newValue, name)
372  self._cloneToObjectDict[id(value)] = newValue
373  self._cloneToObjectDict[id(newValue)] = newValue
374  #now put in proper bucket
375  newValue._place(name,self)
376  def __findFirstSequenceUsingModule(self,seqs,mod):
377  """Given a container of sequences, find the first sequence containing mod
378  and return the sequence. If no sequence is found, return None"""
379  from FWCore.ParameterSet.SequenceTypes import ModuleNodeVisitor
380  for sequenceable in seqs.itervalues():
381  l = list()
382  v = ModuleNodeVisitor(l)
383  sequenceable.visit(v)
384  if mod in l:
385  return sequenceable
386  return None
387  def __delattr__(self,name):
388  if not hasattr(self,name):
389  raise KeyError('process does not know about '+name)
390  elif name.startswith('_Process__'):
391  raise ValueError('this attribute cannot be deleted')
392  else:
393  # we have to remove it from all dictionaries/registries
394  dicts = [item for item in self.__dict__.values() if (type(item)==dict or type(item)==DictTypes.SortedKeysDict)]
395  for reg in dicts:
396  if name in reg: del reg[name]
397  # if it was a labelable object, the label needs to be removed
398  obj = getattr(self,name)
399  if isinstance(obj,_Labelable):
400  getattr(self,name).setLabel(None)
401  # now remove it from the process itself
402  try:
403  del self.__dict__[name]
404  except:
405  pass
406 
407  def add_(self,value):
408  """Allows addition of components that do not have to have a label, e.g. Services"""
409  if not isinstance(value,_ConfigureComponent):
410  raise TypeError
411  if not isinstance(value,_Unlabelable):
412  raise TypeError
413  #clone the item
414  #clone the item
415  if self.__isStrict:
416  newValue =value.copy()
417  value.setIsFrozen()
418  else:
419  newValue =value
420  newValue._place('',self)
421 
422  def _okToPlace(self, name, mod, d):
423  if not self.__InExtendCall:
424  # if going
425  return True
426  elif not self.__isStrict:
427  return True
428  elif name in d:
429  # if there's an old copy, and the new one
430  # hasn't been modified, we're done. Still
431  # not quite safe if something has been defined twice.
432  # Need to add checks
433  if mod._isModified:
434  if d[name]._isModified:
435  return False
436  else:
437  return True
438  else:
439  return True
440  else:
441  return True
442 
443  def _place(self, name, mod, d):
444  if self._okToPlace(name, mod, d):
445  if self.__isStrict and isinstance(mod, _ModuleSequenceType):
446  d[name] = mod._postProcessFixup(self._cloneToObjectDict)
447  else:
448  d[name] = mod
449  if isinstance(mod,_Labelable):
450  self.__setObjectLabel(mod, name)
451  def _placeOutputModule(self,name,mod):
452  self._place(name, mod, self.__outputmodules)
453  def _placeProducer(self,name,mod):
454  self._place(name, mod, self.__producers)
455  def _placeFilter(self,name,mod):
456  self._place(name, mod, self.__filters)
457  def _placeAnalyzer(self,name,mod):
458  self._place(name, mod, self.__analyzers)
459  def _placePath(self,name,mod):
460  self._validateSequence(mod, name)
461  try:
462  self._place(name, mod, self.__paths)
463  except ModuleCloneError as msg:
464  context = format_outerframe(4)
465  raise Exception("%sThe module %s in path %s is unknown to the process %s." %(context, msg, name, self._Process__name))
466  def _placeEndPath(self,name,mod):
467  self._validateSequence(mod, name)
468  try:
469  self._place(name, mod, self.__endpaths)
470  except ModuleCloneError as msg:
471  context = format_outerframe(4)
472  raise Exception("%sThe module %s in endpath %s is unknown to the process %s." %(context, msg, name, self._Process__name))
473  def _placeSequence(self,name,mod):
474  self._validateSequence(mod, name)
475  self._place(name, mod, self.__sequences)
476  def _placeESProducer(self,name,mod):
477  self._place(name, mod, self.__esproducers)
478  def _placeESPrefer(self,name,mod):
479  self._place(name, mod, self.__esprefers)
480  def _placeESSource(self,name,mod):
481  self._place(name, mod, self.__essources)
482  def _placeAlias(self,name,mod):
483  self._place(name, mod, self.__aliases)
484  def _placePSet(self,name,mod):
485  self._place(name, mod, self.__psets)
486  def _placeVPSet(self,name,mod):
487  self._place(name, mod, self.__vpsets)
488  def _placeSource(self,name,mod):
489  """Allow the source to be referenced by 'source' or by type name"""
490  if name != 'source':
491  raise ValueError("The label '"+name+"' can not be used for a Source. Only 'source' is allowed.")
492  if self.__dict__['_Process__source'] is not None :
493  del self.__dict__[self.__dict__['_Process__source'].type_()]
494  self.__dict__['_Process__source'] = mod
495  self.__dict__[mod.type_()] = mod
496  def _placeLooper(self,name,mod):
497  if name != 'looper':
498  raise ValueError("The label '"+name+"' can not be used for a Looper. Only 'looper' is allowed.")
499  self.__dict__['_Process__looper'] = mod
500  self.__dict__[mod.type_()] = mod
501  def _placeSubProcess(self,name,mod):
502  self.__dict__['_Process__subProcess'] = mod
503  self.__dict__[mod.type_()] = mod
504  def addSubProcess(self,mod):
505  self.__subProcesses.append(mod)
506  def _placeService(self,typeName,mod):
507  self._place(typeName, mod, self.__services)
508  self.__dict__[typeName]=mod
509  def load(self, moduleName):
510  moduleName = moduleName.replace("/",".")
511  module = __import__(moduleName)
512  self.extend(sys.modules[moduleName])
513  def extend(self,other,items=()):
514  """Look in other and find types that we can use"""
515  # enable explicit check to avoid overwriting of existing objects
516  self.__dict__['_Process__InExtendCall'] = True
517 
518  seqs = dict()
519  mods = []
520  for name in dir(other):
521  #'from XX import *' ignores these, and so should we.
522  if name.startswith('_'):
523  continue
524  item = getattr(other,name)
525  if name == "source" or name == "looper":
526  # In these cases 'item' could be None if the specific object was not defined
527  if item is not None:
528  self.__setattr__(name,item)
529  elif isinstance(item,_ModuleSequenceType):
530  seqs[name]=item
531  elif isinstance(item,_Labelable):
532  self.__setattr__(name,item)
533  if not item.hasLabel_() :
534  item.setLabel(name)
535  elif isinstance(item,Schedule):
536  self.__setattr__(name,item)
537  elif isinstance(item,_Unlabelable):
538  self.add_(item)
539  elif isinstance(item,ProcessModifier):
540  mods.append(item)
541  elif isinstance(item,ProcessFragment):
542  self.extend(item)
543 
544  #now create a sequence that uses the newly made items
545  for name in seqs.iterkeys():
546  seq = seqs[name]
547  #newSeq = seq.copy()
548  #
549  if id(seq) not in self._cloneToObjectDict:
550  self.__setattr__(name,seq)
551  else:
552  newSeq = self._cloneToObjectDict[id(seq)]
553  self.__dict__[name]=newSeq
554  self.__setObjectLabel(newSeq, name)
555  #now put in proper bucket
556  newSeq._place(name,self)
557 
558  #apply modifiers now that all names have been added
559  for item in mods:
560  item.apply(self)
561 
562  self.__dict__['_Process__InExtendCall'] = False
563 
564  def _dumpConfigNamedList(self,items,typeName,options):
565  returnValue = ''
566  for name,item in items:
567  returnValue +=options.indentation()+typeName+' '+name+' = '+item.dumpConfig(options)
568  return returnValue
569  def _dumpConfigUnnamedList(self,items,typeName,options):
570  returnValue = ''
571  for name,item in items:
572  returnValue +=options.indentation()+typeName+' = '+item.dumpConfig(options)
573  return returnValue
574  def _dumpConfigOptionallyNamedList(self,items,typeName,options):
575  returnValue = ''
576  for name,item in items:
577  if name == item.type_():
578  name = ''
579  returnValue +=options.indentation()+typeName+' '+name+' = '+item.dumpConfig(options)
580  return returnValue
581  def dumpConfig(self, options=PrintOptions()):
582  """return a string containing the equivalent process defined using the old configuration language"""
583  config = "process "+self.__name+" = {\n"
584  options.indent()
585  if self.source_():
586  config += options.indentation()+"source = "+self.source_().dumpConfig(options)
587  if self.looper_():
588  config += options.indentation()+"looper = "+self.looper_().dumpConfig(options)
589 
590  config+=self._dumpConfigNamedList(self.subProcesses_(),
591  'subProcess',
592  options)
593  config+=self._dumpConfigNamedList(self.producers_().iteritems(),
594  'module',
595  options)
596  config+=self._dumpConfigNamedList(self.filters_().iteritems(),
597  'module',
598  options)
599  config+=self._dumpConfigNamedList(self.analyzers_().iteritems(),
600  'module',
601  options)
602  config+=self._dumpConfigNamedList(self.outputModules_().iteritems(),
603  'module',
604  options)
605  config+=self._dumpConfigNamedList(self.sequences_().iteritems(),
606  'sequence',
607  options)
608  config+=self._dumpConfigNamedList(self.paths_().iteritems(),
609  'path',
610  options)
611  config+=self._dumpConfigNamedList(self.endpaths_().iteritems(),
612  'endpath',
613  options)
614  config+=self._dumpConfigUnnamedList(self.services_().iteritems(),
615  'service',
616  options)
617  config+=self._dumpConfigNamedList(self.aliases_().iteritems(),
618  'alias',
619  options)
620  config+=self._dumpConfigOptionallyNamedList(
621  self.es_producers_().iteritems(),
622  'es_module',
623  options)
624  config+=self._dumpConfigOptionallyNamedList(
625  self.es_sources_().iteritems(),
626  'es_source',
627  options)
628  config += self._dumpConfigESPrefers(options)
629  for name,item in self.psets.iteritems():
630  config +=options.indentation()+item.configTypeName()+' '+name+' = '+item.configValue(options)
631  for name,item in self.vpsets.iteritems():
632  config +=options.indentation()+'VPSet '+name+' = '+item.configValue(options)
633  if self.schedule:
634  pathNames = [p.label_() for p in self.schedule]
635  config +=options.indentation()+'schedule = {'+','.join(pathNames)+'}\n'
636 
637 # config+=self._dumpConfigNamedList(self.vpsets.iteritems(),
638 # 'VPSet',
639 # options)
640  config += "}\n"
641  options.unindent()
642  return config
643  def _dumpConfigESPrefers(self, options):
644  result = ''
645  for item in self.es_prefers_().itervalues():
646  result +=options.indentation()+'es_prefer '+item.targetLabel_()+' = '+item.dumpConfig(options)
647  return result
648  def _dumpPythonSubProcesses(self, l, options):
649  returnValue = ''
650  for item in l:
651  returnValue += item.dumpPython(options)+'\n\n'
652  return returnValue
653  def _dumpPythonList(self, d, options):
654  returnValue = ''
655  if isinstance(d, DictTypes.SortedKeysDict):
656  for name,item in d.items():
657  returnValue +='process.'+name+' = '+item.dumpPython(options)+'\n\n'
658  else:
659  for name,item in sorted(d.items()):
660  returnValue +='process.'+name+' = '+item.dumpPython(options)+'\n\n'
661  return returnValue
662  def _validateSequence(self, sequence, label):
663  # See if every module has been inserted into the process
664  try:
665  l = set()
666  nameVisitor = NodeNameVisitor(l)
667  sequence.visit(nameVisitor)
668  except:
669  raise RuntimeError("An entry in sequence "+label + ' has no label')
671  #for each sequence, see what other sequences it depends upon
672  returnValue=DictTypes.SortedKeysDict()
673  dependencies = {}
674  for label,seq in self.sequences.iteritems():
675  d = []
676  v = SequenceVisitor(d)
677  seq.visit(v)
678  dependencies[label]=[dep.label_() for dep in d if dep.hasLabel_()]
679  resolvedDependencies=True
680  #keep looping until we can no longer get rid of all dependencies
681  # if that happens it means we have circular dependencies
682  iterCount = 0
683  while resolvedDependencies:
684  iterCount += 1
685  resolvedDependencies = (0 != len(dependencies))
686  oldDeps = dict(dependencies)
687  for label,deps in oldDeps.iteritems():
688  # don't try too hard
689  if len(deps)==0 or iterCount > 100:
690  iterCount = 0
691  resolvedDependencies=True
692  returnValue[label]=self.sequences[label]
693  #remove this as a dependency for all other sequences
694  del dependencies[label]
695  for lb2,deps2 in dependencies.iteritems():
696  while deps2.count(label):
697  deps2.remove(label)
698  if len(dependencies):
699  raise RuntimeError("circular sequence dependency discovered \n"+
700  ",".join([label for label,junk in dependencies.iteritems()]))
701  return returnValue
702  def _dumpPython(self, d, options):
703  result = ''
704  for name, value in sorted(d.iteritems()):
705  result += value.dumpPythonAs(name,options)+'\n'
706  return result
707  def dumpPython(self, options=PrintOptions()):
708  """return a string containing the equivalent process defined using python"""
709  result = "import FWCore.ParameterSet.Config as cms\n\n"
710  result += "process = cms.Process(\""+self.__name+"\")\n\n"
711  if self.source_():
712  result += "process.source = "+self.source_().dumpPython(options)
713  if self.looper_():
714  result += "process.looper = "+self.looper_().dumpPython()
715  result+=self._dumpPythonList(self.psets, options)
716  result+=self._dumpPythonList(self.vpsets, options)
717  result+=self._dumpPythonSubProcesses(self.subProcesses_(), options)
718  result+=self._dumpPythonList(self.producers_(), options)
719  result+=self._dumpPythonList(self.filters_() , options)
720  result+=self._dumpPythonList(self.analyzers_(), options)
721  result+=self._dumpPythonList(self.outputModules_(), options)
722  result+=self._dumpPythonList(self._sequencesInDependencyOrder(), options)
723  result+=self._dumpPythonList(self.paths_(), options)
724  result+=self._dumpPythonList(self.endpaths_(), options)
725  result+=self._dumpPythonList(self.services_(), options)
726  result+=self._dumpPythonList(self.es_producers_(), options)
727  result+=self._dumpPythonList(self.es_sources_(), options)
728  result+=self._dumpPython(self.es_prefers_(), options)
729  result+=self._dumpPythonList(self.aliases_(), options)
730  if self.schedule:
731  pathNames = ['process.'+p.label_() for p in self.schedule]
732  result +='process.schedule = cms.Schedule(*[ ' + ', '.join(pathNames) + ' ])\n'
733 
734  return result
735  def _replaceInSequences(self, label, new):
736  old = getattr(self,label)
737  #TODO - replace by iterator concatenation
738  for sequenceable in self.sequences.itervalues():
739  sequenceable.replace(old,new)
740  for sequenceable in self.paths.itervalues():
741  sequenceable.replace(old,new)
742  for sequenceable in self.endpaths.itervalues():
743  sequenceable.replace(old,new)
744  def globalReplace(self,label,new):
745  """ Replace the item with label 'label' by object 'new' in the process and all sequences/paths"""
746  if not hasattr(self,label):
747  raise LookupError("process has no item of label "+label)
748  self._replaceInSequences(label, new)
749  setattr(self,label,new)
750  def _insertInto(self, parameterSet, itemDict):
751  for name,value in itemDict.iteritems():
752  value.insertInto(parameterSet, name)
753  def _insertOneInto(self, parameterSet, label, item, tracked):
754  vitems = []
755  if not item == None:
756  newlabel = item.nameInProcessDesc_(label)
757  vitems = [newlabel]
758  item.insertInto(parameterSet, newlabel)
759  parameterSet.addVString(tracked, label, vitems)
760  def _insertManyInto(self, parameterSet, label, itemDict, tracked):
761  l = []
762  for name,value in itemDict.iteritems():
763  newLabel = value.nameInProcessDesc_(name)
764  l.append(newLabel)
765  value.insertInto(parameterSet, name)
766  # alphabetical order is easier to compare with old language
767  l.sort()
768  parameterSet.addVString(tracked, label, l)
769  def _insertSubProcessesInto(self, parameterSet, label, itemList, tracked):
770  l = []
771  subprocs = []
772  for value in itemList:
773  name = value.getProcessName()
774  newLabel = value.nameInProcessDesc_(name)
775  l.append(newLabel)
776  pset = value.getSubProcessPSet(parameterSet)
777  subprocs.append(pset)
778  # alphabetical order is easier to compare with old language
779  l.sort()
780  parameterSet.addVString(tracked, label, l)
781  parameterSet.addVPSet(False,"subProcesses",subprocs)
782  def _insertPaths(self, processPSet):
783  scheduledPaths = []
784  triggerPaths = []
785  endpaths = []
786  if self.schedule_() == None:
787  # make one from triggerpaths & endpaths
788  for name,value in self.paths_().iteritems():
789  scheduledPaths.append(name)
790  triggerPaths.append(name)
791  for name,value in self.endpaths_().iteritems():
792  scheduledPaths.append(name)
793  endpaths.append(name)
794  else:
795  for path in self.schedule_():
796  pathname = path.label_()
797  scheduledPaths.append(pathname)
798  if pathname in self.endpaths_():
799  endpaths.append(pathname)
800  else:
801  triggerPaths.append(pathname)
802  processPSet.addVString(True, "@end_paths", endpaths)
803  processPSet.addVString(True, "@paths", scheduledPaths)
804  # trigger_paths are a little different
805  p = processPSet.newPSet()
806  p.addVString(True, "@trigger_paths", triggerPaths)
807  processPSet.addPSet(True, "@trigger_paths", p)
808  # add all these paths
809  pathValidator = PathValidator()
810  endpathValidator = EndPathValidator()
811  for triggername in triggerPaths:
812  #self.paths_()[triggername].insertInto(processPSet, triggername, self.sequences_())
813  pathValidator.setLabel(triggername)
814  self.paths_()[triggername].visit(pathValidator)
815  self.paths_()[triggername].insertInto(processPSet, triggername, self.__dict__)
816  for endpathname in endpaths:
817  #self.endpaths_()[endpathname].insertInto(processPSet, endpathname, self.sequences_())
818  endpathValidator.setLabel(endpathname)
819  self.endpaths_()[endpathname].visit(endpathValidator)
820  self.endpaths_()[endpathname].insertInto(processPSet, endpathname, self.__dict__)
821  processPSet.addVString(False, "@filters_on_endpaths", endpathValidator.filtersOnEndpaths)
822 
823  def prune(self,verbose=False,keepUnresolvedSequencePlaceholders=False):
824  """ Remove clutter from the process that we think is unnecessary:
825  tracked PSets, VPSets and unused modules and sequences. If a Schedule has been set, then Paths and EndPaths
826  not in the schedule will also be removed, along with an modules and sequences used only by
827  those removed Paths and EndPaths."""
828 # need to update this to only prune psets not on refToPSets
829 # but for now, remove the delattr
830 # for name in self.psets_():
831 # if getattr(self,name).isTracked():
832 # delattr(self, name)
833  for name in self.vpsets_():
834  delattr(self, name)
835  #first we need to resolve any SequencePlaceholders being used
836  for x in self.paths.itervalues():
837  x.resolve(self.__dict__,keepUnresolvedSequencePlaceholders)
838  for x in self.endpaths.itervalues():
839  x.resolve(self.__dict__,keepUnresolvedSequencePlaceholders)
840  usedModules = set()
841  unneededPaths = set()
842  if self.schedule_():
843  usedModules=set(self.schedule_().moduleNames())
844  #get rid of unused paths
845  schedNames = set(( x.label_() for x in self.schedule_()))
846  names = set(self.paths)
847  names.update(set(self.endpaths))
848  unneededPaths = names - schedNames
849  for n in unneededPaths:
850  delattr(self,n)
851  else:
852  pths = list(self.paths.itervalues())
853  pths.extend(self.endpaths.itervalues())
854  temp = Schedule(*pths)
855  usedModules=set(temp.moduleNames())
856  unneededModules = self._pruneModules(self.producers_(), usedModules)
857  unneededModules.update(self._pruneModules(self.filters_(), usedModules))
858  unneededModules.update(self._pruneModules(self.analyzers_(), usedModules))
859  #remove sequences that do not appear in remaining paths and endpaths
860  seqs = list()
861  sv = SequenceVisitor(seqs)
862  for p in self.paths.itervalues():
863  p.visit(sv)
864  for p in self.endpaths.itervalues():
865  p.visit(sv)
866  keepSeqSet = set(( s for s in seqs if s.hasLabel_()))
867  availableSeqs = set(self.sequences.itervalues())
868  unneededSeqs = availableSeqs-keepSeqSet
869  unneededSeqLabels = []
870  for s in unneededSeqs:
871  unneededSeqLabels.append(s.label_())
872  delattr(self,s.label_())
873  if verbose:
874  print "prune removed the following:"
875  print " modules:"+",".join(unneededModules)
876  print " sequences:"+",".join(unneededSeqLabels)
877  print " paths/endpaths:"+",".join(unneededPaths)
878  def _pruneModules(self, d, scheduledNames):
879  moduleNames = set(d.keys())
880  junk = moduleNames - scheduledNames
881  for name in junk:
882  delattr(self, name)
883  return junk
884 
885  def fillProcessDesc(self, processPSet):
886  """Used by the framework to convert python to C++ objects"""
887  class ServiceInjectorAdaptor(object):
888  def __init__(self,ppset,thelist):
889  self.__thelist = thelist
890  self.__processPSet = ppset
891  def addService(self,pset):
892  self.__thelist.append(pset)
893  def newPSet(self):
894  return self.__processPSet.newPSet()
895  #This adaptor is used to 'add' the method 'getTopPSet_'
896  # to the ProcessDesc and PythonParameterSet C++ classes.
897  # This method is needed for the PSet refToPSet_ functionality.
898  class TopLevelPSetAcessorAdaptor(object):
899  def __init__(self,ppset,process):
900  self.__ppset = ppset
901  self.__process = process
902  def __getattr__(self,attr):
903  return getattr(self.__ppset,attr)
904  def getTopPSet_(self,label):
905  return getattr(self.__process,label)
906  def newPSet(self):
907  return TopLevelPSetAcessorAdaptor(self.__ppset.newPSet(),self.__process)
908  def addPSet(self,tracked,name,ppset):
909  return self.__ppset.addPSet(tracked,name,self.__extractPSet(ppset))
910  def addVPSet(self,tracked,name,vpset):
911  return self.__ppset.addVPSet(tracked,name,[self.__extractPSet(x) for x in vpset])
912  def __extractPSet(self,pset):
913  if isinstance(pset,TopLevelPSetAcessorAdaptor):
914  return pset.__ppset
915  return pset
916 
917  self.validate()
918  processPSet.addString(True, "@process_name", self.name_())
919  all_modules = self.producers_().copy()
920  all_modules.update(self.filters_())
921  all_modules.update(self.analyzers_())
922  all_modules.update(self.outputModules_())
923  adaptor = TopLevelPSetAcessorAdaptor(processPSet,self)
924  self._insertInto(adaptor, self.psets_())
925  self._insertInto(adaptor, self.vpsets_())
926  self._insertManyInto(adaptor, "@all_modules", all_modules, True)
927  self._insertOneInto(adaptor, "@all_sources", self.source_(), True)
928  self._insertOneInto(adaptor, "@all_loopers", self.looper_(), True)
929  self._insertSubProcessesInto(adaptor, "@all_subprocesses", self.subProcesses_(), False)
930  self._insertManyInto(adaptor, "@all_esmodules", self.es_producers_(), True)
931  self._insertManyInto(adaptor, "@all_essources", self.es_sources_(), True)
932  self._insertManyInto(adaptor, "@all_esprefers", self.es_prefers_(), True)
933  self._insertManyInto(adaptor, "@all_aliases", self.aliases_(), True)
934  self._insertPaths(adaptor)
935  #handle services differently
936  services = []
937  for n in self.services_():
938  getattr(self,n).insertInto(ServiceInjectorAdaptor(adaptor,services))
939  adaptor.addVPSet(False,"services",services)
940  return processPSet
941 
942  def validate(self):
943  # check if there's some input
944  # Breaks too many unit tests for now
945  #if self.source_() == None and self.looper_() == None:
946  # raise RuntimeError("No input source was found for this process")
947  pass
948 
949  def prefer(self, esmodule,*args,**kargs):
950  """Prefer this ES source or producer. The argument can
951  either be an object label, e.g.,
952  process.prefer(process.juicerProducer) (not supported yet)
953  or a name of an ESSource or ESProducer
954  process.prefer("juicer")
955  or a type of unnamed ESSource or ESProducer
956  process.prefer("JuicerProducer")
957  In addition, you can pass as a labelled arguments the name of the Record you wish to
958  prefer where the type passed is a cms.vstring and that vstring can contain the
959  name of the C++ types in the Record that are being preferred, e.g.,
960  #prefer all data in record 'OrangeRecord' from 'juicer'
961  process.prefer("juicer", OrangeRecord=cms.vstring())
962  or
963  #prefer only "Orange" data in "OrangeRecord" from "juicer"
964  process.prefer("juicer", OrangeRecord=cms.vstring("Orange"))
965  or
966  #prefer only "Orange" data with label "ExtraPulp" in "OrangeRecord" from "juicer"
967  ESPrefer("ESJuicerProd", OrangeRecord=cms.vstring("Orange/ExtraPulp"))
968  """
969  # see if this refers to a named ESProducer
970  if isinstance(esmodule, ESSource) or isinstance(esmodule, ESProducer):
971  raise RuntimeError("Syntax of process.prefer(process.esmodule) not supported yet")
972  elif self._findPreferred(esmodule, self.es_producers_(),*args,**kargs) or \
973  self._findPreferred(esmodule, self.es_sources_(),*args,**kargs):
974  pass
975  else:
976  raise RuntimeError("Cannot resolve prefer for "+repr(esmodule))
977 
978  def _findPreferred(self, esname, d,*args,**kargs):
979  # is esname a name in the dictionary?
980  if esname in d:
981  typ = d[esname].type_()
982  if typ == esname:
983  self.__setattr__( esname+"_prefer", ESPrefer(typ,*args,**kargs) )
984  else:
985  self.__setattr__( esname+"_prefer", ESPrefer(typ, esname,*args,**kargs) )
986  return True
987  else:
988  # maybe it's an unnamed ESModule?
989  found = False
990  for name, value in d.iteritems():
991  if value.type_() == esname:
992  if found:
993  raise RuntimeError("More than one ES module for "+esname)
994  found = True
995  self.__setattr__(esname+"_prefer", ESPrefer(d[esname].type_()) )
996  return found
997 
998 
999 class ProcessFragment(object):
1000  def __init__(self, process):
1001  if isinstance(process, Process):
1002  self.__process = process
1003  elif isinstance(process, str):
1004  self.__process = Process(process)
1005  else:
1006  raise TypeError('a ProcessFragment can only be constructed from an existig Process or from process name')
1007  def __dir__(self):
1008  return [ x for x in dir(self.__process) if isinstance(getattr(self.__process, x), _ConfigureComponent) ]
1009  def __getattribute__(self, name):
1010  if name == '_ProcessFragment__process':
1011  return object.__getattribute__(self, '_ProcessFragment__process')
1012  else:
1013  return getattr(self.__process, name)
1014  def __setattr__(self, name, value):
1015  if name == '_ProcessFragment__process':
1016  object.__setattr__(self, name, value)
1017  else:
1018  setattr(self.__process, name, value)
1019  def __delattr__(self, name):
1020  if name == '_ProcessFragment__process':
1021  pass
1022  else:
1023  return delattr(self.__process, name)
1024 
1025 
1027  """a dictionary with fixed keys"""
1029  raise AttributeError("An FilteredStream defintion cannot be modified after creation.")
1030  _blocked_attribute = property(_blocked_attribute)
1031  __setattr__ = __delitem__ = __setitem__ = clear = _blocked_attribute
1032  pop = popitem = setdefault = update = _blocked_attribute
1033  def __new__(cls, *args, **kw):
1034  new = dict.__new__(cls)
1035  dict.__init__(new, *args, **kw)
1036  keys = kw.keys()
1037  keys.sort()
1038  if keys != ['content', 'dataTier', 'name', 'paths', 'responsible', 'selectEvents']:
1039  raise ValueError("The needed parameters are: content, dataTier, name, paths, responsible, selectEvents")
1040  if not isinstance(kw['name'],str):
1041  raise ValueError("name must be of type string")
1042  if not isinstance(kw['content'], vstring) and not isinstance(kw['content'],str):
1043  raise ValueError("content must be of type vstring or string")
1044  if not isinstance(kw['dataTier'], string):
1045  raise ValueError("dataTier must be of type string")
1046  if not isinstance(kw['selectEvents'], PSet):
1047  raise ValueError("selectEvents must be of type PSet")
1048  if not isinstance(kw['paths'],(tuple, Path)):
1049  raise ValueError("'paths' must be a tuple of paths")
1050  return new
1051  def __init__(self, *args, **kw):
1052  pass
1053  def __repr__(self):
1054  return "FilteredStream object: %s" %self["name"]
1055  def __getattr__(self,attr):
1056  return self[attr]
1057 
1059  """Allows embedding another process within a parent process. This allows one to
1060  chain processes together directly in one cmsRun job rather than having to run
1061  separate jobs that are connected via a temporary file.
1062  """
1063  def __init__(self,process, SelectEvents = untracked.PSet(), outputCommands = untracked.vstring()):
1064  """
1065  """
1066  if not isinstance(process, Process):
1067  raise ValueError("the 'process' argument must be of type cms.Process")
1068  if not isinstance(SelectEvents,PSet):
1069  raise ValueError("the 'SelectEvents' argument must be of type cms.untracked.PSet")
1070  if not isinstance(outputCommands,vstring):
1071  raise ValueError("the 'outputCommands' argument must be of type cms.untracked.vstring")
1072  self.__process = process
1073  self.__SelectEvents = SelectEvents
1074  self.__outputCommands = outputCommands
1075  def dumpPython(self,options):
1076  out = "parentProcess"+str(hash(self))+" = process\n"
1077  out += self.__process.dumpPython()
1078  out += "childProcess = process\n"
1079  out += "process = parentProcess"+str(hash(self))+"\n"
1080  out += "process.addSubProcess(cms.SubProcess(process = childProcess, SelectEvents = "+self.__SelectEvents.dumpPython(options) +", outputCommands = "+self.__outputCommands.dumpPython(options) +"))"
1081  return out
1082  def getProcessName(self):
1083  return self.__process.name_()
1084  def process(self):
1085  return self.__process
1086  def SelectEvents(self):
1087  return self.__SelectEvents
1088  def outputCommands(self):
1089  return self.__outputCommands
1090  def type_(self):
1091  return 'subProcess'
1092  def nameInProcessDesc_(self,label):
1093  return label
1094  def _place(self,label,process):
1095  process._placeSubProcess('subProcess',self)
1096  def getSubProcessPSet(self,parameterSet):
1097  topPSet = parameterSet.newPSet()
1098  self.__process.fillProcessDesc(topPSet)
1099  subProcessPSet = parameterSet.newPSet()
1100  self.__SelectEvents.insertInto(subProcessPSet,"SelectEvents")
1101  self.__outputCommands.insertInto(subProcessPSet,"outputCommands")
1102  subProcessPSet.addPSet(False,"process",topPSet)
1103  return subProcessPSet
1104 
1105 class _ParameterModifier(object):
1106  """Helper class for Modifier that takes key/value pairs and uses them to reset parameters of the object"""
1107  def __init__(self,args):
1108  self.__args = args
1109  def __call__(self,obj):
1110  params = {}
1111  for k in self.__args.iterkeys():
1112  if hasattr(obj,k):
1113  params[k] = getattr(obj,k)
1114  else:
1115  params[k] = self.__args[k]
1117  for k in self.__args.iterkeys():
1118  if k in params:
1119  setattr(obj,k,params[k])
1120  else:
1121  #the parameter must have been removed
1122  delattr(obj,k)
1124  raise KeyError("Unknown parameter name "+k+" specified while calling Modifier")
1125 
1126 class _AndModifier(object):
1127  """A modifier which only applies if multiple Modifiers are chosen"""
1128  def __init__(self, lhs, rhs):
1129  self.__lhs = lhs
1130  self.__rhs = rhs
1131  def isChosen(self):
1132  return self.__lhs.isChosen() and self.__rhs.isChosen()
1133  def toModify(self,obj, func=None,**kw):
1134  if not self.isChosen():
1135  return
1136  self.__lhs.toModify(obj,func, **kw)
1137  def makeProcessModifier(self,func):
1138  """This is used to create a ProcessModifer that can perform actions on the process as a whole.
1139  This takes as argument a callable object (e.g. function) that takes as its sole argument an instance of Process.
1140  In order to work, the value returned from this function must be assigned to a uniquely named variable."""
1141  return ProcessModifier(self,func)
1142  def __and__(self, other):
1143  return _AndModifier(self,other)
1144 
1145 
1146 
1147 class Modifier(object):
1148  """This class is used to define standard modifications to a Process.
1149  An instance of this class is declared to denote a specific modification,e.g. era2017 could
1150  reconfigure items in a process to match our expectation of running in 2017. Once declared,
1151  these Modifier instances are imported into a configuration and items that need to be modified
1152  are then associated with the Modifier and with the action to do the modification.
1153  The registered modifications will only occur if the Modifier was passed to
1154  the cms.Process' constructor.
1155  """
1156  def __init__(self):
1158  self.__chosen = False
1159  def makeProcessModifier(self,func):
1160  """This is used to create a ProcessModifer that can perform actions on the process as a whole.
1161  This takes as argument a callable object (e.g. function) that takes as its sole argument an instance of Process.
1162  In order to work, the value returned from this function must be assigned to a uniquely named variable.
1163  """
1164  return ProcessModifier(self,func)
1165  def toModify(self,obj, func=None,**kw):
1166  """This is used to register an action to be performed on the specific object. Two different forms are allowed
1167  Form 1: A callable object (e.g. function) can be passed as the second. This callable object is expected to take one argument
1168  that will be the object passed in as the first argument.
1169  Form 2: A list of parameter name, value pairs can be passed
1170  mod.toModify(foo, fred=cms.int32(7), barney = cms.double(3.14))
1171  This form can also be used to remove a parameter by passing the value of None
1172  #remove the parameter foo.fred
1173  mod.toModify(foo, fred = None)
1174  Additionally, parameters embedded within PSets can also be modified using a dictionary
1175  #change foo.fred.pebbles to 3 and foo.fred.friend to "barney"
1176  mod.toModify(foo, fred = dict(pebbles = 3, friend = "barney)) )
1177  """
1178  if func is not None and len(kw) != 0:
1179  raise TypeError("toModify takes either two arguments or one argument and key/value pairs")
1180  if not self.isChosen():
1181  return
1182  if func is not None:
1183  func(obj)
1184  else:
1185  temp =_ParameterModifier(kw)
1186  temp(obj)
1187  def toReplaceWith(self,toObj,fromObj):
1188  """If the Modifier is chosen the internals of toObj will be associated with the internals of fromObj
1189  """
1190  if type(fromObj) != type(toObj):
1191  raise TypeError("toReplaceWith requires both arguments to be the same class type")
1192  if not self.isChosen():
1193  return
1194  if isinstance(fromObj,_ModuleSequenceType):
1195  toObj._seq = fromObj._seq
1196  elif isinstance(fromObj,_Parameterizable):
1197  #clear old items just incase fromObj is not a complete superset of toObj
1198  for p in toObj.parameterNames_():
1199  delattr(toObj,p)
1200  for p in fromObj.parameterNames_():
1201  setattr(toObj,p,getattr(fromObj,p))
1202  if isinstance(fromObj,_TypedParameterizable):
1203  toObj._TypedParameterizable__type = fromObj._TypedParameterizable__type
1204 
1205  else:
1206  raise TypeError("toReplaceWith does not work with type "+str(type(toObj)))
1207 
1208  def _setChosen(self):
1209  """Should only be called by cms.Process instances"""
1210  self.__chosen = True
1211  def isChosen(self):
1212  return self.__chosen
1213  def __and__(self, other):
1214  return _AndModifier(self,other)
1215 
1216 
1217 class ModifierChain(object):
1218  """A Modifier made up of a list of Modifiers
1219  """
1220  def __init__(self, *chainedModifiers):
1221  self.__chosen = False
1222  self.__chain = chainedModifiers
1223  def _applyNewProcessModifiers(self,process):
1224  """Should only be called by cms.Process instances
1225  applies list of accumulated changes to the process"""
1226  for m in self.__chain:
1227  m._applyNewProcessModifiers(process)
1228  def _setChosen(self):
1229  """Should only be called by cms.Process instances"""
1230  self.__chosen = True
1231  for m in self.__chain:
1232  m._setChosen()
1233  def isChosen(self):
1234  return self.__chosen
1235 
1236 class ProcessModifier(object):
1237  """A class used by a Modifier to affect an entire Process instance.
1238  When a Process 'loads' a module containing a ProcessModifier, that
1239  ProcessModifier will be applied to the Process if and only if the
1240  Modifier passed to the constructor has been chosen.
1241  """
1242  def __init__(self, modifier, func):
1243  self.__modifier = modifier
1244  self.__func = func
1245  self.__seenProcesses = set()
1246  def apply(self,process):
1247  if self.__modifier.isChosen():
1248  if process not in self.__seenProcesses:
1249  self.__func(process)
1250  self.__seenProcesses.add(process)
1251 
1252 if __name__=="__main__":
1253  import unittest
1254  import copy
1255 
1256  class TestMakePSet(object):
1257  """Has same interface as the C++ object that creates PSets
1258  """
1259  def __init__(self):
1260  self.values = dict()
1261  def __insertValue(self,tracked,label,value):
1262  self.values[label]=(tracked,value)
1263  def addInt32(self,tracked,label,value):
1264  self.__insertValue(tracked,label,value)
1265  def addVInt32(self,tracked,label,value):
1266  self.__insertValue(tracked,label,value)
1267  def addUInt32(self,tracked,label,value):
1268  self.__insertValue(tracked,label,value)
1269  def addVUInt32(self,tracked,label,value):
1270  self.__insertValue(tracked,label,value)
1271  def addInt64(self,tracked,label,value):
1272  self.__insertValue(tracked,label,value)
1273  def addVInt64(self,tracked,label,value):
1274  self.__insertValue(tracked,label,value)
1275  def addUInt64(self,tracked,label,value):
1276  self.__insertValue(tracked,label,value)
1277  def addVUInt64(self,tracked,label,value):
1278  self.__insertValue(tracked,label,value)
1279  def addDouble(self,tracked,label,value):
1280  self.__insertValue(tracked,label,value)
1281  def addVDouble(self,tracked,label,value):
1282  self.__insertValue(tracked,label,value)
1283  def addBool(self,tracked,label,value):
1284  self.__insertValue(tracked,label,value)
1285  def addString(self,tracked,label,value):
1286  self.__insertValue(tracked,label,value)
1287  def addVString(self,tracked,label,value):
1288  self.__insertValue(tracked,label,value)
1289  def addInputTag(self,tracked,label,value):
1290  self.__insertValue(tracked,label,value)
1291  def addVInputTag(self,tracked,label,value):
1292  self.__insertValue(tracked,label,value)
1293  def addESInputTag(self,tracked,label,value):
1294  self.__insertValue(tracked,label,value)
1295  def addVESInputTag(self,tracked,label,value):
1296  self.__insertValue(tracked,label,value)
1297  def addEventID(self,tracked,label,value):
1298  self.__insertValue(tracked,label,value)
1299  def addVEventID(self,tracked,label,value):
1300  self.__insertValue(tracked,label,value)
1301  def addLuminosityBlockID(self,tracked,label,value):
1302  self.__insertValue(tracked,label,value)
1303  def addLuminosityBlockID(self,tracked,label,value):
1304  self.__insertValue(tracked,label,value)
1305  def addEventRange(self,tracked,label,value):
1306  self.__insertValue(tracked,label,value)
1307  def addVEventRange(self,tracked,label,value):
1308  self.__insertValue(tracked,label,value)
1309  def addPSet(self,tracked,label,value):
1310  self.__insertValue(tracked,label,value)
1311  def addVPSet(self,tracked,label,value):
1312  self.__insertValue(tracked,label,value)
1313  def addFileInPath(self,tracked,label,value):
1314  self.__insertValue(tracked,label,value)
1315  def newPSet(self):
1316  return TestMakePSet()
1317 
1318  class TestModuleCommand(unittest.TestCase):
1319  def setUp(self):
1320  """Nothing to do """
1321  None
1323  p = _Parameterizable()
1324  self.assertEqual(len(p.parameterNames_()),0)
1325  p.a = int32(1)
1326  self.assert_('a' in p.parameterNames_())
1327  self.assertEqual(p.a.value(), 1)
1328  p.a = 10
1329  self.assertEqual(p.a.value(), 10)
1330  p.a = untracked(int32(1))
1331  self.assertEqual(p.a.value(), 1)
1332  self.failIf(p.a.isTracked())
1333  p.a = untracked.int32(1)
1334  self.assertEqual(p.a.value(), 1)
1335  self.failIf(p.a.isTracked())
1336  p = _Parameterizable(foo=int32(10), bar = untracked(double(1.0)))
1337  self.assertEqual(p.foo.value(), 10)
1338  self.assertEqual(p.bar.value(),1.0)
1339  self.failIf(p.bar.isTracked())
1340  self.assertRaises(TypeError,setattr,(p,'c',1))
1341  p = _Parameterizable(a=PSet(foo=int32(10), bar = untracked(double(1.0))))
1342  self.assertEqual(p.a.foo.value(),10)
1343  self.assertEqual(p.a.bar.value(),1.0)
1344  p.b = untracked(PSet(fii = int32(1)))
1345  self.assertEqual(p.b.fii.value(),1)
1346  self.failIf(p.b.isTracked())
1347  #test the fact that values can be shared
1348  v = int32(10)
1349  p=_Parameterizable(a=v)
1350  v.setValue(11)
1351  self.assertEqual(p.a.value(),11)
1352  p.a = 12
1353  self.assertEqual(p.a.value(),12)
1354  self.assertEqual(v.value(),12)
1356  p = _TypedParameterizable("blah", b=int32(1))
1357  #see if copy works deeply
1358  other = p.copy()
1359  other.b = 2
1360  self.assertNotEqual(p.b,other.b)
1361 
1363  p = Process("test")
1364  p.a = EDAnalyzer("MyAnalyzer")
1365  self.assert_( 'a' in p.analyzers_() )
1366  self.assert_( 'a' in p.analyzers)
1367  p.add_(Service("MessageLogger"))
1368  self.assert_('MessageLogger' in p.services_())
1369  self.assertEqual(p.MessageLogger.type_(), "MessageLogger")
1370  p.Tracer = Service("Tracer")
1371  self.assert_('Tracer' in p.services_())
1372  self.assertRaises(TypeError, setattr, *(p,'b',"this should fail"))
1373  self.assertRaises(TypeError, setattr, *(p,'bad',Service("MessageLogger")))
1374  self.assertRaises(ValueError, setattr, *(p,'bad',Source("PoolSource")))
1375  p.out = OutputModule("Outer")
1376  self.assertEqual(p.out.type_(), 'Outer')
1377  self.assert_( 'out' in p.outputModules_() )
1378 
1379  p.geom = ESSource("GeomProd")
1380  self.assert_('geom' in p.es_sources_())
1381  p.add_(ESSource("ConfigDB"))
1382  self.assert_('ConfigDB' in p.es_sources_())
1383 
1384  p.aliasfoo1 = EDAlias(foo1 = VPSet(PSet(type = string("Foo1"))))
1385  self.assert_('aliasfoo1' in p.aliases_())
1386 
1388  class FromArg(object):
1389  def __init__(self,*arg,**args):
1390  for name in args.iterkeys():
1391  self.__dict__[name]=args[name]
1392 
1393  a=EDAnalyzer("MyAnalyzer")
1394  t=EDAnalyzer("MyAnalyzer")
1395  t.setLabel("foo")
1396  s1 = Sequence(a)
1397  s2 = Sequence(s1)
1398  s3 = Sequence(s2)
1399  d = FromArg(
1400  a=a,
1401  b=Service("Full"),
1402  c=Path(a),
1403  d=s2,
1404  e=s1,
1405  f=s3,
1406  g=Sequence(s1+s2+s3)
1407  )
1408  p = Process("Test")
1409  p.extend(d)
1410  self.assertEqual(p.a.type_(),"MyAnalyzer")
1411  self.assertEqual(p.a.label_(),"a")
1412  self.assertRaises(AttributeError,getattr,p,'b')
1413  self.assertEqual(p.Full.type_(),"Full")
1414  self.assertEqual(str(p.c),'a')
1415  self.assertEqual(str(p.d),'a')
1416 
1417  z1 = FromArg(
1418  a=a,
1419  b=Service("Full"),
1420  c=Path(a),
1421  d=s2,
1422  e=s1,
1423  f=s3,
1424  s4=s3,
1425  g=Sequence(s1+s2+s3)
1426  )
1427 
1428  p1 = Process("Test")
1429  #p1.extend(z1)
1430  self.assertRaises(ValueError, p1.extend, z1)
1431 
1432  z2 = FromArg(
1433  a=a,
1434  b=Service("Full"),
1435  c=Path(a),
1436  d=s2,
1437  e=s1,
1438  f=s3,
1439  aaa=copy.deepcopy(a),
1440  s4=copy.deepcopy(s3),
1441  g=Sequence(s1+s2+s3),
1442  t=t
1443  )
1444  p2 = Process("Test")
1445  p2.extend(z2)
1446  #self.assertRaises(ValueError, p2.extend, z2)
1447  self.assertEqual(p2.s4.label_(),"s4")
1448  #p2.s4.setLabel("foo")
1449  self.assertRaises(ValueError, p2.s4.setLabel, "foo")
1450  p2.s4.setLabel("s4")
1451  p2.s4.setLabel(None)
1452  p2.s4.setLabel("foo")
1453  p2._Process__setObjectLabel(p2.s4, "foo")
1454  p2._Process__setObjectLabel(p2.s4, None)
1455  p2._Process__setObjectLabel(p2.s4, "bar")
1456 
1458  p = Process("test")
1459  p.a = EDAnalyzer("MyAnalyzer")
1460  p.p = Path(p.a)
1461  p.s = Sequence(p.a)
1462  p.r = Sequence(p.s)
1463  p.p2 = Path(p.s)
1464  p.schedule = Schedule(p.p2,p.p)
1465  d=p.dumpPython()
1466  self.assertEqual(d,
1467 """import FWCore.ParameterSet.Config as cms
1468 
1469 process = cms.Process("test")
1470 
1471 process.a = cms.EDAnalyzer("MyAnalyzer")
1472 
1473 
1474 process.s = cms.Sequence(process.a)
1475 
1476 
1477 process.r = cms.Sequence(process.s)
1478 
1479 
1480 process.p = cms.Path(process.a)
1481 
1482 
1483 process.p2 = cms.Path(process.s)
1484 
1485 
1486 process.schedule = cms.Schedule(*[ process.p2, process.p ])
1487 """)
1488  #Reverse order of 'r' and 's'
1489  p = Process("test")
1490  p.a = EDAnalyzer("MyAnalyzer")
1491  p.p = Path(p.a)
1492  p.r = Sequence(p.a)
1493  p.s = Sequence(p.r)
1494  p.p2 = Path(p.r)
1495  p.schedule = Schedule(p.p2,p.p)
1496  p.b = EDAnalyzer("YourAnalyzer")
1497  d=p.dumpPython()
1498  self.assertEqual(d,
1499 """import FWCore.ParameterSet.Config as cms
1500 
1501 process = cms.Process("test")
1502 
1503 process.a = cms.EDAnalyzer("MyAnalyzer")
1504 
1505 
1506 process.b = cms.EDAnalyzer("YourAnalyzer")
1507 
1508 
1509 process.r = cms.Sequence(process.a)
1510 
1511 
1512 process.s = cms.Sequence(process.r)
1513 
1514 
1515 process.p = cms.Path(process.a)
1516 
1517 
1518 process.p2 = cms.Path(process.r)
1519 
1520 
1521 process.schedule = cms.Schedule(*[ process.p2, process.p ])
1522 """)
1523  #use an anonymous sequence
1524  p = Process("test")
1525  p.a = EDAnalyzer("MyAnalyzer")
1526  p.p = Path(p.a)
1527  s = Sequence(p.a)
1528  p.r = Sequence(s)
1529  p.p2 = Path(p.r)
1530  p.schedule = Schedule(p.p2,p.p)
1531  d=p.dumpPython()
1532  self.assertEqual(d,
1533  """import FWCore.ParameterSet.Config as cms
1534 
1535 process = cms.Process("test")
1536 
1537 process.a = cms.EDAnalyzer("MyAnalyzer")
1538 
1539 
1540 process.r = cms.Sequence((process.a))
1541 
1542 
1543 process.p = cms.Path(process.a)
1544 
1545 
1546 process.p2 = cms.Path(process.r)
1547 
1548 
1549 process.schedule = cms.Schedule(*[ process.p2, process.p ])
1550 """)
1551 
1552  def testSecSource(self):
1553  p = Process('test')
1554  p.a = SecSource("MySecSource")
1555  self.assertEqual(p.dumpPython().replace('\n',''),'import FWCore.ParameterSet.Config as cmsprocess = cms.Process("test")process.a = cms.SecSource("MySecSource")')
1556 
1558  p = Process('test')
1559  p.a = EDAnalyzer("MyAnalyzer")
1560  p.b = EDAnalyzer("YourAnalyzer")
1561  p.c = EDAnalyzer("OurAnalyzer")
1562  p.s = Sequence(p.a*p.b)
1563  p.p = Path(p.c+p.s+p.a)
1564  new = EDAnalyzer("NewAnalyzer")
1565  p.globalReplace("a",new)
1566 
1567  def testSequence(self):
1568  p = Process('test')
1569  p.a = EDAnalyzer("MyAnalyzer")
1570  p.b = EDAnalyzer("YourAnalyzer")
1571  p.c = EDAnalyzer("OurAnalyzer")
1572  p.s = Sequence(p.a*p.b)
1573  self.assertEqual(str(p.s),'a+b')
1574  self.assertEqual(p.s.label_(),'s')
1575  path = Path(p.c+p.s)
1576  self.assertEqual(str(path),'c+a+b')
1577  p._validateSequence(path, 'p1')
1578  notInProcess = EDAnalyzer('NotInProcess')
1579  p2 = Path(p.c+p.s*notInProcess)
1580  self.assertRaises(RuntimeError, p._validateSequence, p2, 'p2')
1581 
1582  def testSequence2(self):
1583  p = Process('test')
1584  p.a = EDAnalyzer("MyAnalyzer")
1585  p.b = EDAnalyzer("YourAnalyzer")
1586  p.c = EDAnalyzer("OurAnalyzer")
1587  testseq = Sequence(p.a*p.b)
1588  p.s = testseq
1589  #p.y = testseq
1590  self.assertRaises(ValueError, p.__setattr__, "y", testseq)
1591 
1592  def testPath(self):
1593  p = Process("test")
1594  p.a = EDAnalyzer("MyAnalyzer")
1595  p.b = EDAnalyzer("YourAnalyzer")
1596  p.c = EDAnalyzer("OurAnalyzer")
1597  path = Path(p.a)
1598  path *= p.b
1599  path += p.c
1600  self.assertEqual(str(path),'a+b+c')
1601  path = Path(p.a*p.b+p.c)
1602  self.assertEqual(str(path),'a+b+c')
1603 # path = Path(p.a)*p.b+p.c #This leads to problems with sequences
1604 # self.assertEqual(str(path),'((a*b)+c)')
1605  path = Path(p.a+ p.b*p.c)
1606  self.assertEqual(str(path),'a+b+c')
1607  path = Path(p.a*(p.b+p.c))
1608  self.assertEqual(str(path),'a+b+c')
1609  path = Path(p.a*(p.b+~p.c))
1610  self.assertEqual(str(path),'a+b+~c')
1611  p.es = ESProducer("AnESProducer")
1612  self.assertRaises(TypeError,Path,p.es)
1613 
1615  p = Process("test")
1616  a = EDAnalyzer("MyAnalyzer")
1617  p.a = a
1618  a.setLabel("a")
1619  b = EDAnalyzer("YOurAnalyzer")
1620  p.b = b
1621  b.setLabel("b")
1622  path = Path(a * b)
1623  p.path = Path(p.a*p.b)
1624  lookuptable = {id(a): p.a, id(b): p.b}
1625  #self.assertEqual(str(path),str(path._postProcessFixup(lookuptable)))
1626  #lookuptable = p._cloneToObjectDict
1627  #self.assertEqual(str(path),str(path._postProcessFixup(lookuptable)))
1628  self.assertEqual(str(path),str(p.path))
1629 
1630  def testSchedule(self):
1631  p = Process("test")
1632  p.a = EDAnalyzer("MyAnalyzer")
1633  p.b = EDAnalyzer("YourAnalyzer")
1634  p.c = EDAnalyzer("OurAnalyzer")
1635  p.d = EDAnalyzer("OurAnalyzer")
1636  p.path1 = Path(p.a)
1637  p.path2 = Path(p.b)
1638  p.path3 = Path(p.d)
1639 
1640  s = Schedule(p.path1,p.path2)
1641  self.assertEqual(s[0],p.path1)
1642  self.assertEqual(s[1],p.path2)
1643  p.schedule = s
1644  self.assert_('b' in p.schedule.moduleNames())
1645  self.assert_(hasattr(p, 'b'))
1646  self.assert_(hasattr(p, 'c'))
1647  self.assert_(hasattr(p, 'd'))
1648  self.assert_(hasattr(p, 'path1'))
1649  self.assert_(hasattr(p, 'path2'))
1650  self.assert_(hasattr(p, 'path3'))
1651  p.prune()
1652  self.assert_('b' in p.schedule.moduleNames())
1653  self.assert_(hasattr(p, 'b'))
1654  self.assert_(not hasattr(p, 'c'))
1655  self.assert_(not hasattr(p, 'd'))
1656  self.assert_(hasattr(p, 'path1'))
1657  self.assert_(hasattr(p, 'path2'))
1658  self.assert_(not hasattr(p, 'path3'))
1659 
1660  #adding a path not attached to the Process should cause an exception
1661  p = Process("test")
1662  p.a = EDAnalyzer("MyAnalyzer")
1663  path1 = Path(p.a)
1664  s = Schedule(path1)
1665  self.assertRaises(RuntimeError, lambda : p.setSchedule_(s) )
1666 
1667  #make sure anonymous sequences work
1668  p = Process("test")
1669  p.a = EDAnalyzer("MyAnalyzer")
1670  p.b = EDAnalyzer("MyOtherAnalyzer")
1671  p.c = EDProducer("MyProd")
1672  path1 = Path(p.c*Sequence(p.a+p.b))
1673  s = Schedule(path1)
1674  self.assert_('a' in s.moduleNames())
1675  self.assert_('b' in s.moduleNames())
1676  self.assert_('c' in s.moduleNames())
1677  p.path1 = path1
1678  p.schedule = s
1679  p.prune()
1680  self.assert_('a' in s.moduleNames())
1681  self.assert_('b' in s.moduleNames())
1682  self.assert_('c' in s.moduleNames())
1683 
1685  p = Process("test")
1686  p.a = EDAnalyzer("MyAnalyzer")
1687  p.b = EDAnalyzer("YourAnalyzer")
1688  p.c = EDAnalyzer("OurAnalyzer")
1689  p.path1 = Path(p.a)
1690  p.path2 = Path(p.b)
1691  self.assert_(p.schedule is None)
1692  pths = p.paths
1693  keys = pths.keys()
1694  self.assertEqual(pths[keys[0]],p.path1)
1695  self.assertEqual(pths[keys[1]],p.path2)
1696  p.prune()
1697  self.assert_(hasattr(p, 'a'))
1698  self.assert_(hasattr(p, 'b'))
1699  self.assert_(not hasattr(p, 'c'))
1700  self.assert_(hasattr(p, 'path1'))
1701  self.assert_(hasattr(p, 'path2'))
1702 
1703 
1704  p = Process("test")
1705  p.a = EDAnalyzer("MyAnalyzer")
1706  p.b = EDAnalyzer("YourAnalyzer")
1707  p.c = EDAnalyzer("OurAnalyzer")
1708  p.path2 = Path(p.b)
1709  p.path1 = Path(p.a)
1710  self.assert_(p.schedule is None)
1711  pths = p.paths
1712  keys = pths.keys()
1713  self.assertEqual(pths[keys[1]],p.path1)
1714  self.assertEqual(pths[keys[0]],p.path2)
1715 
1716 
1717  def testUsing(self):
1718  p = Process('test')
1719  p.block = PSet(a = int32(1))
1720  p.modu = EDAnalyzer('Analyzer', p.block, b = int32(2))
1721  self.assertEqual(p.modu.a.value(),1)
1722  self.assertEqual(p.modu.b.value(),2)
1723 
1724  def testOverride(self):
1725  p = Process('test')
1726  a = EDProducer("A", a1=int32(0))
1727  self.assert_(not a.isModified())
1728  a.a1 = 1
1729  self.assert_(a.isModified())
1730  p.a = a
1731  self.assertEqual(p.a.a1.value(), 1)
1732  # try adding an unmodified module.
1733  # should accept it
1734  p.a = EDProducer("A", a1=int32(2))
1735  self.assertEqual(p.a.a1.value(), 2)
1736  # try adding a modified module. Should throw
1737  # no longer, since the same (modified) say, geometry
1738  # could come from more than one cff
1739  b = EDProducer("A", a1=int32(3))
1740  b.a1 = 4
1741  #self.assertRaises(RuntimeError, setattr, *(p,'a',b))
1742  ps1 = PSet(a = int32(1))
1743  ps2 = PSet(a = int32(2))
1744  self.assertRaises(ValueError, EDProducer, 'C', ps1, ps2)
1745  self.assertRaises(ValueError, EDProducer, 'C', ps1, a=int32(3))
1746 
1747  def testExamples(self):
1748  p = Process("Test")
1749  p.source = Source("PoolSource",fileNames = untracked(string("file:reco.root")))
1750  p.foos = EDProducer("FooProducer")
1751  p.bars = EDProducer("BarProducer", foos=InputTag("foos"))
1752  p.out = OutputModule("PoolOutputModule",fileName=untracked(string("file:foos.root")))
1753  p.bars.foos = 'Foosball'
1754  self.assertEqual(p.bars.foos, InputTag('Foosball'))
1755  p.p = Path(p.foos*p.bars)
1756  p.e = EndPath(p.out)
1757  p.add_(Service("MessageLogger"))
1758 
1759  def testPrefers(self):
1760  p = Process("Test")
1761  p.add_(ESSource("ForceSource"))
1762  p.juicer = ESProducer("JuicerProducer")
1763  p.prefer("ForceSource")
1764  p.prefer("juicer")
1765  self.assertEqual(p.dumpConfig(),
1766 """process Test = {
1767  es_module juicer = JuicerProducer {
1768  }
1769  es_source = ForceSource {
1770  }
1771  es_prefer = ForceSource {
1772  }
1773  es_prefer juicer = JuicerProducer {
1774  }
1775 }
1776 """)
1777  p.prefer("juicer",fooRcd=vstring("Foo"))
1778  self.assertEqual(p.dumpConfig(),
1779 """process Test = {
1780  es_module juicer = JuicerProducer {
1781  }
1782  es_source = ForceSource {
1783  }
1784  es_prefer = ForceSource {
1785  }
1786  es_prefer juicer = JuicerProducer {
1787  vstring fooRcd = {
1788  'Foo'
1789  }
1790 
1791  }
1792 }
1793 """)
1794  self.assertEqual(p.dumpPython(),
1795 """import FWCore.ParameterSet.Config as cms
1796 
1797 process = cms.Process("Test")
1798 
1799 process.juicer = cms.ESProducer("JuicerProducer")
1800 
1801 
1802 process.ForceSource = cms.ESSource("ForceSource")
1803 
1804 
1805 process.prefer("ForceSource")
1806 
1807 process.prefer("juicer",
1808  fooRcd = cms.vstring('Foo')
1809 )
1810 
1811 """)
1812 
1813  def testFreeze(self):
1814  process = Process("Freeze")
1815  m = EDProducer("M", p=PSet(i = int32(1)))
1816  m.p.i = 2
1817  process.m = m
1818  # should be frozen
1819  #self.assertRaises(ValueError, setattr, m.p, 'i', 3)
1820  #self.assertRaises(ValueError, setattr, m, 'p', PSet(i=int32(1)))
1821  #self.assertRaises(ValueError, setattr, m.p, 'j', 1)
1822  #self.assertRaises(ValueError, setattr, m, 'j', 1)
1823  # But OK to change through the process
1824  process.m.p.i = 4
1825  self.assertEqual(process.m.p.i.value(), 4)
1826  process.m.p = PSet(j=int32(1))
1827  # should work to clone it, though
1828  m2 = m.clone(p = PSet(i = int32(5)), j = int32(8))
1829  m2.p.i = 6
1830  m2.j = 8
1831  def testSubProcess(self):
1832  process = Process("Parent")
1833  subProcess = Process("Child")
1834  subProcess.a = EDProducer("A")
1835  subProcess.p = Path(subProcess.a)
1836  subProcess.add_(Service("Foo"))
1837  process.addSubProcess(SubProcess(subProcess))
1838  d = process.dumpPython()
1839  equalD ="""import FWCore.ParameterSet.Config as cms
1840 
1841 process = cms.Process("Parent")
1842 
1843 parentProcess = process
1844 import FWCore.ParameterSet.Config as cms
1845 
1846 process = cms.Process("Child")
1847 
1848 process.a = cms.EDProducer("A")
1849 
1850 
1851 process.p = cms.Path(process.a)
1852 
1853 
1854 process.Foo = cms.Service("Foo")
1855 
1856 
1857 childProcess = process
1858 process = parentProcess
1859 process.addSubProcess(cms.SubProcess(process = childProcess, SelectEvents = cms.untracked.PSet(
1860 
1861 ), outputCommands = cms.untracked.vstring()))
1862 
1863 """
1864  equalD = equalD.replace("parentProcess","parentProcess"+str(hash(process.subProcesses_()[0])))
1865  self.assertEqual(d,equalD)
1866  p = TestMakePSet()
1867  process.fillProcessDesc(p)
1868  self.assertEqual((True,['a']),p.values["subProcesses"][1][0].values["process"][1].values['@all_modules'])
1869  self.assertEqual((True,['p']),p.values["subProcesses"][1][0].values["process"][1].values['@paths'])
1870  self.assertEqual({'@service_type':(True,'Foo')}, p.values["subProcesses"][1][0].values["process"][1].values["services"][1][0].values)
1871  def testRefToPSet(self):
1872  proc = Process("test")
1873  proc.top = PSet(a = int32(1))
1874  proc.ref = PSet(refToPSet_ = string("top"))
1875  proc.ref2 = PSet( a = int32(1), b = PSet( refToPSet_ = string("top")))
1876  proc.ref3 = PSet(refToPSet_ = string("ref"))
1877  proc.ref4 = VPSet(PSet(refToPSet_ = string("top")),
1878  PSet(refToPSet_ = string("ref2")))
1879  p = TestMakePSet()
1880  proc.fillProcessDesc(p)
1881  self.assertEqual((True,1),p.values["ref"][1].values["a"])
1882  self.assertEqual((True,1),p.values["ref3"][1].values["a"])
1883  self.assertEqual((True,1),p.values["ref2"][1].values["a"])
1884  self.assertEqual((True,1),p.values["ref2"][1].values["b"][1].values["a"])
1885  self.assertEqual((True,1),p.values["ref4"][1][0].values["a"])
1886  self.assertEqual((True,1),p.values["ref4"][1][1].values["a"])
1887  def testPrune(self):
1888  p = Process("test")
1889  p.a = EDAnalyzer("MyAnalyzer")
1890  p.b = EDAnalyzer("YourAnalyzer")
1891  p.c = EDAnalyzer("OurAnalyzer")
1892  p.d = EDAnalyzer("OurAnalyzer")
1893  p.s = Sequence(p.d)
1894  p.path1 = Path(p.a)
1895  p.path2 = Path(p.b)
1896  self.assert_(p.schedule is None)
1897  pths = p.paths
1898  keys = pths.keys()
1899  self.assertEqual(pths[keys[0]],p.path1)
1900  self.assertEqual(pths[keys[1]],p.path2)
1901  p.pset1 = PSet(parA = string("pset1"))
1902  p.pset2 = untracked.PSet(parA = string("pset2"))
1903  p.vpset1 = VPSet()
1904  p.vpset2 = untracked.VPSet()
1905  p.prune()
1906  self.assert_(hasattr(p, 'a'))
1907  self.assert_(hasattr(p, 'b'))
1908  self.assert_(not hasattr(p, 'c'))
1909  self.assert_(not hasattr(p, 'd'))
1910  self.assert_(not hasattr(p, 's'))
1911  self.assert_(hasattr(p, 'path1'))
1912  self.assert_(hasattr(p, 'path2'))
1913 # self.assert_(not hasattr(p, 'pset1'))
1914 # self.assert_(hasattr(p, 'pset2'))
1915 # self.assert_(not hasattr(p, 'vpset1'))
1916 # self.assert_(not hasattr(p, 'vpset2'))
1917 
1918  p = Process("test")
1919  p.a = EDAnalyzer("MyAnalyzer")
1920  p.b = EDAnalyzer("YourAnalyzer")
1921  p.c = EDAnalyzer("OurAnalyzer")
1922  p.d = EDAnalyzer("OurAnalyzer")
1923  p.e = EDAnalyzer("OurAnalyzer")
1924  p.s = Sequence(p.d)
1925  p.s2 = Sequence(p.b)
1926  p.s3 = Sequence(p.e)
1927  p.path1 = Path(p.a)
1928  p.path2 = Path(p.b)
1929  p.path3 = Path(p.b+p.s2)
1930  p.path4 = Path(p.b+p.s3)
1931  p.schedule = Schedule(p.path1,p.path2,p.path3)
1932  pths = p.paths
1933  keys = pths.keys()
1934  self.assertEqual(pths[keys[0]],p.path1)
1935  self.assertEqual(pths[keys[1]],p.path2)
1936  p.prune()
1937  self.assert_(hasattr(p, 'a'))
1938  self.assert_(hasattr(p, 'b'))
1939  self.assert_(not hasattr(p, 'c'))
1940  self.assert_(not hasattr(p, 'd'))
1941  self.assert_(not hasattr(p, 'e'))
1942  self.assert_(not hasattr(p, 's'))
1943  self.assert_(hasattr(p, 's2'))
1944  self.assert_(not hasattr(p, 's3'))
1945  self.assert_(hasattr(p, 'path1'))
1946  self.assert_(hasattr(p, 'path2'))
1947  self.assert_(hasattr(p, 'path3'))
1948  self.assert_(not hasattr(p, 'path4'))
1949  #test SequencePlaceholder
1950  p = Process("test")
1951  p.a = EDAnalyzer("MyAnalyzer")
1952  p.b = EDAnalyzer("YourAnalyzer")
1953  p.s = Sequence(SequencePlaceholder("a")+p.b)
1954  p.pth = Path(p.s)
1955  p.prune()
1956  self.assert_(hasattr(p, 'a'))
1957  self.assert_(hasattr(p, 'b'))
1958  self.assert_(hasattr(p, 's'))
1959  self.assert_(hasattr(p, 'pth'))
1960  #test unresolved SequencePlaceholder
1961  p = Process("test")
1962  p.b = EDAnalyzer("YourAnalyzer")
1963  p.s = Sequence(SequencePlaceholder("a")+p.b)
1964  p.pth = Path(p.s)
1965  p.prune(keepUnresolvedSequencePlaceholders=True)
1966  self.assert_(hasattr(p, 'b'))
1967  self.assert_(hasattr(p, 's'))
1968  self.assert_(hasattr(p, 'pth'))
1969  self.assertEqual(p.s.dumpPython(''),'cms.Sequence(cms.SequencePlaceholder("a")+process.b)\n')
1970  def testModifier(self):
1971  m1 = Modifier()
1972  p = Process("test",m1)
1973  p.a = EDAnalyzer("MyAnalyzer", fred = int32(1))
1974  def _mod_fred(obj):
1975  obj.fred = 2
1976  m1.toModify(p.a,_mod_fred)
1977  self.assertEqual(p.a.fred.value(),2)
1978  p.b = EDAnalyzer("YourAnalyzer", wilma = int32(1))
1979  m1.toModify(p.b, wilma = 2)
1980  self.assertEqual(p.b.wilma.value(),2)
1981  #check that Modifier not attached to a process doesn't run
1982  m1 = Modifier()
1983  p = Process("test")
1984  p.a = EDAnalyzer("MyAnalyzer", fred = int32(1))
1985  m1.toModify(p.a,_mod_fred)
1986  p.b = EDAnalyzer("YourAnalyzer", wilma = int32(1))
1987  m1.toModify(p.b, wilma = 2)
1988  self.assertEqual(p.a.fred.value(),1)
1989  self.assertEqual(p.b.wilma.value(),1)
1990  #make sure clones get the changes
1991  m1 = Modifier()
1992  p = Process("test",m1)
1993  p.a = EDAnalyzer("MyAnalyzer", fred = int32(1), wilma = int32(1))
1994  m1.toModify(p.a, fred = int32(2))
1995  p.b = p.a.clone(wilma = int32(3))
1996  self.assertEqual(p.a.fred.value(),2)
1997  self.assertEqual(p.a.wilma.value(),1)
1998  self.assertEqual(p.b.fred.value(),2)
1999  self.assertEqual(p.b.wilma.value(),3)
2000  #test removal of parameter
2001  m1 = Modifier()
2002  p = Process("test",m1)
2003  p.a = EDAnalyzer("MyAnalyzer", fred = int32(1), wilma = int32(1))
2004  m1.toModify(p.a, fred = None)
2005  self.assertEqual(hasattr(p.a, "fred"), False)
2006  self.assertEqual(p.a.wilma.value(),1)
2007  #test adding a parameter
2008  m1 = Modifier()
2009  p = Process("test",m1)
2010  p.a = EDAnalyzer("MyAnalyzer", fred = int32(1))
2011  m1.toModify(p.a, wilma = int32(2))
2012  self.assertEqual(p.a.fred.value(), 1)
2013  self.assertEqual(p.a.wilma.value(),2)
2014  #test setting of value in PSet
2015  m1 = Modifier()
2016  p = Process("test",m1)
2017  p.a = EDAnalyzer("MyAnalyzer", flintstones = PSet(fred = int32(1), wilma = int32(1)))
2018  m1.toModify(p.a, flintstones = dict(fred = int32(2)))
2019  self.assertEqual(p.a.flintstones.fred.value(),2)
2020  self.assertEqual(p.a.flintstones.wilma.value(),1)
2021  #test that load causes process wide methods to run
2022  def _rem_a(proc):
2023  del proc.a
2024  class ProcModifierMod(object):
2025  def __init__(self,modifier,func):
2026  self.proc_mod_ = modifier.makeProcessModifier(func)
2027  class DummyMod(object):
2028  def __init__(self):
2029  self.a = EDAnalyzer("Dummy")
2030  testMod = DummyMod()
2031  p.extend(testMod)
2032  self.assert_(hasattr(p,"a"))
2033  m1 = Modifier()
2034  p = Process("test",m1)
2035  testProcMod = ProcModifierMod(m1,_rem_a)
2036  p.extend(testMod)
2037  p.extend(testProcMod)
2038  self.assert_(not hasattr(p,"a"))
2039  #test ModifierChain
2040  m1 = Modifier()
2041  mc = ModifierChain(m1)
2042  p = Process("test",mc)
2043  testMod = DummyMod()
2044  p.b = EDAnalyzer("Dummy2", fred = int32(1))
2045  m1.toModify(p.b, fred = int32(3))
2046  p.extend(testMod)
2047  testProcMod = ProcModifierMod(m1,_rem_a)
2048  p.extend(testProcMod)
2049  self.assert_(not hasattr(p,"a"))
2050  self.assertEqual(p.b.fred.value(),3)
2051  #check combining
2052  m1 = Modifier()
2053  m2 = Modifier()
2054  p = Process("test",m1)
2055  p.a = EDAnalyzer("MyAnalyzer", fred = int32(1), wilma = int32(1))
2056  (m1 & m2).toModify(p.a, fred = int32(2))
2057  self.assertEqual(p.a.fred, 1)
2058  m1 = Modifier()
2059  m2 = Modifier()
2060  p = Process("test",m1,m2)
2061  p.a = EDAnalyzer("MyAnalyzer", fred = int32(1), wilma = int32(1))
2062  (m1 & m2).toModify(p.a, fred = int32(2))
2063  self.assertEqual(p.a.fred, 2)
2064  m1 = Modifier()
2065  m2 = Modifier()
2066  m3 = Modifier()
2067  p = Process("test",m1,m2,m3)
2068  p.a = EDAnalyzer("MyAnalyzer", fred = int32(1), wilma = int32(1))
2069  (m1 & m2 & m3).toModify(p.a, fred = int32(2))
2070  self.assertEqual(p.a.fred, 2)
2071  #check toReplaceWith
2072  m1 = Modifier()
2073  p = Process("test",m1)
2074  p.a =EDAnalyzer("MyAnalyzer", fred = int32(1))
2075  m1.toReplaceWith(p.a, EDAnalyzer("YourAnalyzer", wilma = int32(3)))
2076  p.b =EDAnalyzer("BAn")
2077  p.s = Sequence(p.a)
2078  m1.toReplaceWith(p.s, Sequence(p.a+p.b))
2079  self.assertEqual(p.a.wilma.value(),3)
2080  self.assertEqual(p.a.type_(),"YourAnalyzer")
2081  self.assertEqual(hasattr(p,"fred"),False)
2082  self.assertEqual(p.s.dumpPython(""),"cms.Sequence(process.a+process.b)\n")
2083  #check toReplaceWith doesn't activate not chosen
2084  m1 = Modifier()
2085  p = Process("test")
2086  p.a =EDAnalyzer("MyAnalyzer", fred = int32(1))
2087  m1.toReplaceWith(p.a, EDAnalyzer("YourAnalyzer", wilma = int32(3)))
2088  self.assertEqual(p.a.type_(),"MyAnalyzer")
2089  unittest.main()
def __setObjectLabel
Definition: Config.py:271
def filterNames
Definition: Config.py:147
def es_sources_
Definition: Config.py:250
def _replaceInSequences
Definition: Config.py:735
def setSchedule_
Definition: Config.py:230
def _insertManyInto
Definition: Config.py:760
def __delattr__
Definition: Config.py:387
def _validateSequence
Definition: Config.py:662
def _dumpConfigUnnamedList
Definition: Config.py:569
def _placeEndPath
Definition: Config.py:466
def setSource_
Definition: Config.py:189
def _findPreferred
Definition: Config.py:978
def es_producers_
Definition: Config.py:246
def addSubProcess
Definition: Config.py:504
def aliases_
Definition: Config.py:258
def _dumpConfigESPrefers
Definition: Config.py:643
def _placeSequence
Definition: Config.py:473
def _dumpConfigOptionallyNamedList
Definition: Config.py:574
def _placeOutputModule
Definition: Config.py:451
def setLooper_
Definition: Config.py:195
def _placePSet
Definition: Config.py:484
def filters_
Definition: Config.py:171
def _placeProducer
Definition: Config.py:453
def _okToPlace
Definition: Config.py:422
def getSubProcessPSet
Definition: Config.py:1096
def dumpPython
Definition: Config.py:707
def es_prefers_
Definition: Config.py:254
def _placePath
Definition: Config.py:459
def _insertPaths
Definition: Config.py:782
def _dumpPythonSubProcesses
Definition: Config.py:648
def visit
Retrieve data from a perf suite output (sub) directory, only examines TimeSize at the moment...
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
def _insertSubProcessesInto
Definition: Config.py:769
def _sequencesInDependencyOrder
Definition: Config.py:670
def outputModules_
Definition: Config.py:206
def producers_
Definition: Config.py:182
def __findFirstSequenceUsingModule
Definition: Config.py:376
def fillProcessDesc
Definition: Config.py:885
def __init__
Definition: Config.py:101
def _insertInto
Definition: Config.py:750
def analyzers_
Definition: Config.py:202
def addLuminosityBlockID
Definition: Config.py:1301
def _placeVPSet
Definition: Config.py:486
def setPartialSchedule_
Definition: Config.py:225
def setStrict
Definition: Config.py:136
def globalReplace
Definition: Config.py:744
def __setattr__
Definition: Config.py:298
def _placeLooper
Definition: Config.py:496
def dumpConfig
Definition: Config.py:581
def nameInProcessDesc_
Definition: Config.py:1092
def services_
Definition: Config.py:242
def validate
Definition: Config.py:942
def sequences_
Definition: Config.py:218
def schedule_
Definition: Config.py:222
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
def setName_
Definition: Config.py:177
def _applyNewProcessModifiers
Definition: Config.py:1223
def __setstate__
Definition: Config.py:154
def analyzerNames
Definition: Config.py:144
def _placeAnalyzer
Definition: Config.py:457
def _modifyParametersFromDict
Definition: Mixins.py:613
def _pruneModules
Definition: Config.py:878
def _placeAlias
Definition: Config.py:482
def _insertOneInto
Definition: Config.py:753
def _dumpConfigNamedList
Definition: Config.py:564
def pathNames
Definition: Config.py:150
def _placeFilter
Definition: Config.py:455
def _dumpPythonList
Definition: Config.py:653
def findProcess
Definition: Config.py:79
def checkImportPermission
Definition: Config.py:26
dbl *** dir
Definition: mlp_gen.cc:35
def producerNames
Definition: Config.py:141
def _placeSource
Definition: Config.py:488
def makeProcessModifier
Definition: Config.py:1159
def _placeSubProcess
Definition: Config.py:501
tuple untracked
Definition: Types.py:27
def _placeESSource
Definition: Config.py:480
def _placeESPrefer
Definition: Config.py:478
def subProcesses_
Definition: Config.py:198
def toReplaceWith
Definition: Config.py:1187
def _dumpPython
Definition: Config.py:702
def endpaths_
Definition: Config.py:214
def _placeService
Definition: Config.py:506
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger list("!*","!HLTx*"if it matches 2 triggers or more) will accept the event if all the matching triggers are FAIL.It will reject the event if any of the triggers are PASS or EXCEPTION(this matches the behavior of"!*"before the partial wildcard feature was incorporated).Triggers which are in the READY state are completely ignored.(READY should never be returned since the trigger paths have been run
def _placeESProducer
Definition: Config.py:476