File indexing completed on 2023-03-17 11:03:24
0001 from __future__ import absolute_import
0002 import sys
0003
0004 from builtins import range
0005 from .Mixins import _ConfigureComponent, PrintOptions
0006 from .Mixins import _Labelable, _Unlabelable
0007 from .Mixins import _ValidatingParameterListBase
0008 from .ExceptionHandling import *
0009 from .OrderedSet import OrderedSet
0010
0011 class _HardDependency(object):
0012 """Information relevant for when a hard dependency,
0013 which uses the * operator, is found"""
0014 def __init__(self, sequenceName, depSet):
0015 self.sequenceName = sequenceName
0016 self.depSet = depSet
0017
0018 class _Sequenceable(object):
0019 """Denotes an object which can be placed in a sequence"""
0020 def __init__(self):
0021 pass
0022 def __mul__(self,rhs):
0023 return _SequenceCollection(self,rhs)
0024 def __add__(self,rhs):
0025 return _SequenceCollection(self,rhs)
0026 def __invert__(self):
0027 return _SequenceNegation(self)
0028 def _clonesequence(self, lookuptable):
0029 try:
0030 return lookuptable[id(self)]
0031 except:
0032 raise KeyError("no "+str(type(self))+" with id "+str(id(self))+" found")
0033 def resolve(self, processDict,keepIfCannotResolve=False):
0034 return self
0035 def isOperation(self):
0036 """Returns True if the object is an operator (e.g. *,+ or !) type"""
0037 return False
0038 def isLeaf(self):
0039 return False
0040 def _visitSubNodes(self,visitor):
0041 pass
0042 def visitNode(self,visitor):
0043 visitor.enter(self)
0044 self._visitSubNodes(visitor)
0045 visitor.leave(self)
0046 def _appendToCollection(self,collection):
0047 collection.append(self)
0048 def _errorstr(self):
0049 return "A Sequenceable type"
0050
0051 def _checkIfSequenceable(caller, v):
0052 if not isinstance(v,_Sequenceable):
0053 typename = format_typename(caller)
0054 msg = format_outerframe(2)
0055 msg += "%s only takes arguments of types which are allowed in a sequence, but was given:\n" %typename
0056 msg +=format_typename(v)
0057 msg +="\nPlease remove the problematic object from the argument list"
0058 raise TypeError(msg)
0059
0060 def _checkIfBooleanLogicSequenceable(caller, v):
0061 if not isinstance(v,_BooleanLogicSequenceable):
0062 typename = format_typename(caller)
0063 msg = format_outerframe(2)
0064 msg += "%s only takes arguments of types which are allowed in a boolean logic sequence, but was given:\n" %typename
0065 msg +=format_typename(v)
0066 msg +="\nPlease remove the problematic object from the argument list"
0067 raise TypeError(msg)
0068
0069 class _BooleanLogicSequenceable(_Sequenceable):
0070 """Denotes an object which can be used in a boolean logic sequence"""
0071 def __init__(self):
0072 super(_BooleanLogicSequenceable,self).__init__()
0073 def __or__(self,other):
0074 return _BooleanLogicExpression(_BooleanLogicExpression.OR,self,other)
0075 def __and__(self,other):
0076 return _BooleanLogicExpression(_BooleanLogicExpression.AND,self,other)
0077
0078
0079 class _BooleanLogicExpression(_BooleanLogicSequenceable):
0080 """Contains the operation of a boolean logic expression"""
0081 OR = 0
0082 AND = 1
0083 def __init__(self,op,left,right):
0084 _checkIfBooleanLogicSequenceable(self,left)
0085 _checkIfBooleanLogicSequenceable(self,right)
0086 self._op = op
0087 self._items = list()
0088
0089
0090
0091 if isinstance(left,_BooleanLogicExpression) and left._op == self._op:
0092 self._items.extend(left._items)
0093 else:
0094 self._items.append(left)
0095 if isinstance(right,_BooleanLogicExpression) and right._op == self._op:
0096 self._items.extend(right._items)
0097 else:
0098 self._items.append(right)
0099 def isOperation(self):
0100 return True
0101 def _visitSubNodes(self,visitor):
0102 for i in self._items:
0103 i.visitNode(visitor)
0104 def dumpSequencePython(self, options=PrintOptions()):
0105 returnValue = ''
0106 join = ''
0107 operatorJoin =self.operatorString()
0108 for m in self._items:
0109 returnValue +=join
0110 join = operatorJoin
0111 if not isinstance(m,_BooleanLogicSequenceLeaf):
0112 returnValue += '('+m.dumpSequencePython(options)+')'
0113 else:
0114 returnValue += m.dumpSequencePython(options)
0115 return returnValue
0116 def operatorString(self):
0117 returnValue ='|'
0118 if self._op == self.AND:
0119 returnValue = '&'
0120 return returnValue
0121
0122
0123 class _SequenceLeaf(_Sequenceable):
0124 def __init__(self):
0125 pass
0126 def isLeaf(self):
0127 return True
0128
0129
0130 class _BooleanLogicSequenceLeaf(_BooleanLogicSequenceable):
0131 def __init__(self):
0132 pass
0133 def isLeaf(self):
0134 return True
0135
0136 class _SequenceCollection(_Sequenceable):
0137 """Holds representation of the operations without having to use recursion.
0138 Operations are added to the beginning of the list and their operands are
0139 added to the end of the list, with the left added before the right
0140 """
0141 def __init__(self,*seqList):
0142 self._collection = list()
0143 for s in seqList:
0144 _checkIfSequenceable(self,s)
0145 s._appendToCollection(self._collection)
0146 def __mul__(self,rhs):
0147 _checkIfSequenceable(self,rhs)
0148 rhs._appendToCollection(self._collection)
0149 return self
0150 def __add__(self,rhs):
0151 _checkIfSequenceable(self,rhs)
0152 rhs._appendToCollection(self._collection)
0153 return self
0154 def __str__(self):
0155 sep = ''
0156 returnValue = ''
0157 for m in self._collection:
0158 if m is not None:
0159 returnValue += sep+str(m)
0160 sep = '+'
0161 return returnValue
0162 def _appendToCollection(self,collection):
0163 collection.extend(self._collection)
0164
0165 def dumpSequencePython(self, options=PrintOptions()):
0166 returnValue = ''
0167 separator = ''
0168 for item in self._collection:
0169 itemDump = item.dumpSequencePython(options)
0170 if itemDump:
0171 returnValue += (separator + itemDump)
0172 separator = '+'
0173 return returnValue
0174
0175 def dumpSequenceConfig(self):
0176 returnValue = self._collection[0].dumpSequenceConfig()
0177 for m in self._collection[1:]:
0178 returnValue += '&'+m.dumpSequenceConfig()
0179 return returnValue
0180
0181 def directDependencies(self,sortByType=True):
0182 return findDirectDependencies(self, self._collection,sortByType=sortByType)
0183
0184 def visitNode(self,visitor):
0185 for m in self._collection:
0186 m.visitNode(visitor)
0187
0188 def resolve(self, processDict,keepIfCannotResolve=False):
0189 self._collection = [x.resolve(processDict,keepIfCannotResolve) for x in self._collection]
0190 return self
0191
0192 def index(self,item):
0193 return self._collection.index(item)
0194
0195 def insert(self,index,item):
0196 self._collection.insert(index,item)
0197 def _replaceIfHeldDirectly(self,original,replacement):
0198 didReplace = False
0199 for i in self._collection:
0200 if original == i:
0201 self._collection[self._collection.index(original)] = replacement
0202 didReplace = True
0203 elif isinstance(i,_UnarySequenceOperator) and i._has(original):
0204 didReplace = True
0205 if replacement is None:
0206 self._collection[self._collection.index(i)] = None
0207 else:
0208 self._collection[self._collection.index(i)] = type(i)(replacement)
0209 if replacement is None:
0210 self._collection = [ i for i in self._collection if i is not None]
0211 return didReplace
0212
0213
0214 def findDirectDependencies(element, collection,sortByType=True):
0215 dependencies = []
0216 for item in collection:
0217
0218 if item is None:
0219 continue
0220
0221
0222 elif isinstance(item, _SequenceLeaf):
0223 t = 'modules'
0224
0225 elif isinstance(item, (_SequenceIgnore, _SequenceNegation)):
0226 if isinstance(item._operand, _SequenceCollection):
0227 dependencies += item.directDependencies(sortByType)
0228 continue
0229 t = 'modules'
0230
0231 elif isinstance(item, _SequenceCollection):
0232 dependencies += item.directDependencies(sortByType)
0233 continue
0234
0235 elif isinstance(item, Sequence):
0236 if not item.hasLabel_():
0237 dependencies += item.directDependencies(sortByType)
0238 continue
0239 t = 'sequences'
0240
0241 elif isinstance(item, Task):
0242 if not item.hasLabel_():
0243 dependencies += item.directDependencies(sortByType)
0244 continue
0245 t = 'tasks'
0246
0247 elif isinstance(item, ConditionalTask):
0248 if not item.hasLabel_():
0249 dependencies += item.directDependencies(sortByType)
0250 continue
0251 t = 'conditionaltasks'
0252
0253 elif isinstance(item, (SequencePlaceholder, TaskPlaceholder, ConditionalTaskPlaceholder)):
0254 continue
0255
0256 else:
0257 sys.stderr.write("Warning: unsupported element '%s' in %s '%s'\n" % (str(item), type(element).__name__, element.label_()))
0258 continue
0259 dependencies.append((t, item.label_()))
0260 if sortByType:
0261 return sorted(set(dependencies), key = lambda t_item: (t_item[0].lower(), t_item[1].lower().replace('_cfi', '')))
0262 else:
0263 return dependencies
0264
0265
0266 class _ModuleSequenceType(_ConfigureComponent, _Labelable):
0267 """Base class for classes which define a sequence of modules"""
0268 def __init__(self,*arg, **argv):
0269 self.__dict__["_isFrozen"] = False
0270 self._seq = None
0271 if (len(arg) > 1 and not isinstance(arg[1], _TaskBase)) or (len(arg) > 0 and not isinstance(arg[0],_Sequenceable) and not isinstance(arg[0],_TaskBase)):
0272 typename = format_typename(self)
0273 msg = format_outerframe(2)
0274 msg += "The %s constructor takes zero or one sequenceable argument followed by zero or more arguments of type Task. But the following types are given:\n" %typename
0275 for item,i in zip(arg, range(1,20)):
0276 try:
0277 msg += " %i) %s \n" %(i, item._errorstr())
0278 except:
0279 msg += " %i) Not sequenceable and not a Task\n" %(i)
0280 if len(arg) > 1 and isinstance(arg[0],_Sequenceable) and isinstance(arg[1], _Sequenceable):
0281 msg += "Maybe you forgot to combine the sequenceable arguments via '*' or '+'."
0282 raise TypeError(msg)
0283 tasks = arg
0284 if len(arg) > 0 and isinstance(arg[0], _Sequenceable):
0285 self._seq = _SequenceCollection()
0286 arg[0]._appendToCollection(self._seq._collection)
0287 tasks = arg[1:]
0288 self._isModified = False
0289
0290 self._tasks = OrderedSet()
0291
0292 if len(tasks) > 0:
0293 self.associate(*tasks)
0294 def associate(self,*tasks):
0295 for task in tasks:
0296 if not isinstance(task, _TaskBase):
0297 raise TypeError("associate only works with objects of type Task")
0298 self._tasks.add(task)
0299 def isFrozen(self):
0300 return self._isFrozen
0301 def setIsFrozen(self):
0302 self._isFrozen = True
0303 def _place(self,name,proc):
0304 self._placeImpl(name,proc)
0305 def __imul__(self,rhs):
0306 _checkIfSequenceable(self, rhs)
0307 if self._seq is None:
0308 self.__dict__["_seq"] = _SequenceCollection()
0309 self._seq+=rhs
0310 return self
0311 def __iadd__(self,rhs):
0312 _checkIfSequenceable(self, rhs)
0313 if self._seq is None:
0314 self.__dict__["_seq"] = _SequenceCollection()
0315 self._seq += rhs
0316 return self
0317 def __str__(self):
0318 v = ExpandVisitor(type(self))
0319 self.visit(v)
0320 return v.resultString()
0321
0322 def dumpConfig(self, options):
0323 s = ''
0324 if self._seq is not None:
0325 s = self._seq.dumpSequenceConfig()
0326 return '{'+s+'}\n'
0327
0328 def dumpPython(self, options=PrintOptions()):
0329 """Returns a string which is the python representation of the object"""
0330 s = self.dumpPythonNoNewline(options)
0331 return s + "\n"
0332
0333 def dumpPythonNoNewline(self, options=PrintOptions()):
0334 s=''
0335 if self._seq is not None:
0336 s =self._seq.dumpSequencePython(options)
0337 associationContents = set()
0338 for task in self._tasks:
0339 if task.hasLabel_():
0340 associationContents.add(_Labelable.dumpSequencePython(task, options))
0341 else:
0342 associationContents.add(task.dumpPythonNoNewline(options))
0343 for iString in sorted(associationContents):
0344 if s:
0345 s += ", "
0346 s += iString
0347 if len(associationContents) > 254:
0348 return 'cms.'+type(self).__name__+'(*['+s+'])'
0349 return 'cms.'+type(self).__name__+'('+s+')'
0350
0351 def dumpSequencePython(self, options=PrintOptions()):
0352 """Returns a string which contains the python representation of just the internal sequence"""
0353
0354 if self.hasLabel_():
0355 return _Labelable.dumpSequencePython(self, options)
0356 elif len(self._tasks) == 0:
0357 if self._seq is None:
0358 return ''
0359 s = self._seq.dumpSequencePython(options)
0360 if s:
0361 return '('+s+')'
0362 return ''
0363 return self.dumpPythonNoNewline(options)
0364
0365 def dumpSequenceConfig(self):
0366 """Returns a string which contains the old config language representation of just the internal sequence"""
0367
0368 if self.hasLabel_():
0369 return _Labelable.dumpSequenceConfig(self)
0370 else:
0371
0372 if self._seq is None:
0373 return ''
0374 return '('+self._seq.dumpSequenceConfig()+')'
0375
0376 def __repr__(self):
0377 s = ''
0378 if self._seq is not None:
0379 s = str(self._seq)
0380 return "cms."+type(self).__name__+'('+s+')\n'
0381
0382 def directDependencies(self,sortByType=True):
0383 """Returns the list of modules and other entities that are directly used"""
0384 result = []
0385 if self._seq:
0386 result += self._seq.directDependencies(sortByType=sortByType)
0387 if self._tasks:
0388 result += findDirectDependencies(self, self._tasks,sortByType=sortByType)
0389 return result
0390
0391 def moduleNames(self):
0392 """Returns a set containing the names of all modules being used"""
0393 result = set()
0394 visitor = NodeNameVisitor(result)
0395 self.visit(visitor)
0396 return result
0397
0398 def contains(self, mod):
0399 visitor = ContainsModuleVisitor(mod)
0400 self.visit(visitor)
0401 return visitor.result()
0402
0403 def copy(self):
0404 returnValue =_ModuleSequenceType.__new__(type(self))
0405 if self._seq is not None:
0406 returnValue.__init__(self._seq)
0407 else:
0408 returnValue.__init__()
0409 returnValue._tasks = OrderedSet(self._tasks)
0410 return returnValue
0411
0412 def copyAndExclude(self,listOfModulesToExclude):
0413 """Returns a copy of the sequence which excludes those module in 'listOfModulesToExclude'"""
0414
0415
0416
0417
0418
0419
0420 v = _CopyAndExcludeSequenceVisitor(listOfModulesToExclude)
0421 self.visit(v)
0422 result = self.__new__(type(self))
0423 result.__init__(v.result(self)[0], *v.result(self)[1])
0424 return result
0425 def expandAndClone(self):
0426
0427
0428
0429
0430
0431 visitor = ExpandVisitor(type(self))
0432 self.visit(visitor)
0433 return visitor.result()
0434 def _postProcessFixup(self,lookuptable):
0435 self._seq = self._seq._clonesequence(lookuptable)
0436 return self
0437 def replace(self, original, replacement):
0438 """Finds all instances of 'original' and substitutes 'replacement' for them.
0439 Returns 'True' if a replacement occurs."""
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453 if (isinstance(original,Task) != isinstance(replacement,Task)):
0454 raise TypeError("replace only works if both arguments are Tasks or neither")
0455 if (isinstance(original,ConditionalTask) != isinstance(replacement,ConditionalTask)):
0456 raise TypeError("replace only works if both arguments are ConditionalTasks or neither")
0457 v = _CopyAndReplaceSequenceVisitor(original,replacement)
0458 self.visit(v)
0459 if v.didReplace():
0460 self._seq = v.result(self)[0]
0461 if v.result(self)[1]:
0462 self._tasks.clear()
0463 self.associate(*v.result(self)[1])
0464 return v.didReplace()
0465 def _replaceIfHeldDirectly(self,original,replacement):
0466 """Only replaces an 'original' with 'replacement' if 'original' is directly held.
0467 If another Sequence or Task holds 'original' it will not be replaced."""
0468 didReplace = False
0469 if original in self._tasks:
0470 self._tasks.remove(original)
0471 if replacement is not None:
0472 self._tasks.add(replacement)
0473 didReplace = True
0474 if self._seq is not None:
0475 didReplace |= self._seq._replaceIfHeldDirectly(original,replacement)
0476 return didReplace
0477
0478
0479 def index(self,item):
0480 """Returns the index at which the item is found or raises an exception"""
0481 if self._seq is not None:
0482 return self._seq.index(item)
0483 raise ValueError(str(item)+" is not in the sequence")
0484 def insert(self,index,item):
0485 """Inserts the item at the index specified"""
0486 _checkIfSequenceable(self, item)
0487 if self._seq is None:
0488 self.__dict__["_seq"] = _SequenceCollection()
0489 self._seq.insert(index,item)
0490 def remove(self, something):
0491 """Remove the first occurrence of 'something' (a sequence or a module)
0492 Returns 'True' if the module has been removed, False if it was not found"""
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503 v = _CopyAndRemoveFirstSequenceVisitor(something)
0504 self.visit(v)
0505 if v.didRemove():
0506 self._seq = v.result(self)[0]
0507 if v.result(self)[1]:
0508 self._tasks.clear()
0509 self.associate(*v.result(self)[1])
0510 return v.didRemove()
0511 def resolve(self, processDict,keepIfCannotResolve=False):
0512 if self._seq is not None:
0513 self._seq = self._seq.resolve(processDict,keepIfCannotResolve)
0514 for task in self._tasks:
0515 task.resolve(processDict,keepIfCannotResolve)
0516 return self
0517 def __setattr__(self,name,value):
0518 if not name.startswith("_"):
0519 raise AttributeError("You cannot set parameters for sequence like objects.")
0520 else:
0521 self.__dict__[name] = value
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533 def nameInProcessDesc_(self, myname):
0534 return myname
0535 def insertInto(self, parameterSet, myname, decoratedList):
0536 parameterSet.addVString(True, myname, decoratedList)
0537 def visit(self,visitor):
0538 """Passes to visitor's 'enter' and 'leave' method each item describing the module sequence.
0539 If the item contains 'sub' items then visitor will see those 'sub' items between the
0540 item's 'enter' and 'leave' calls.
0541 """
0542 if self._seq is not None:
0543 self._seq.visitNode(visitor)
0544 for item in self._tasks:
0545 visitor.enter(item)
0546 item.visit(visitor)
0547 visitor.leave(item)
0548
0549 class _UnarySequenceOperator(_BooleanLogicSequenceable):
0550 """For ~ and - operators"""
0551 def __init__(self, operand):
0552 self._operand = operand
0553 if isinstance(operand, _ModuleSequenceType):
0554 raise RuntimeError("This operator cannot accept a sequence")
0555 if not isinstance(operand, _Sequenceable):
0556 raise RuntimeError("This operator cannot accept a non sequenceable type")
0557 def __eq__(self, other):
0558
0559 return type(self) is type(other) and self._operand==other._operand
0560 def __ne__(self, other):
0561 return not self.__eq__(other)
0562 def __hash__(self):
0563
0564 return hash((type(self), self._operand))
0565 def _findDependencies(self,knownDeps, presentDeps):
0566 self._operand._findDependencies(knownDeps, presentDeps)
0567 def _clonesequence(self, lookuptable):
0568 return type(self)(self._operand._clonesequence(lookuptable))
0569 def _has(self, op):
0570 return self._operand == op
0571 def resolve(self, processDict,keepIfCannotResolve=False):
0572 return type(self)(self._operand.resolve(processDict,keepIfCannotResolve))
0573 def isOperation(self):
0574 return True
0575 def _visitSubNodes(self,visitor):
0576 self._operand.visitNode(visitor)
0577 def decoration(self):
0578 self._operand.decoration()
0579 def directDependencies(self,sortByType=True):
0580 return self._operand.directDependencies(sortByType=sortByType)
0581 def label_(self):
0582 return self._operand.label_()
0583
0584 class _SequenceNegation(_UnarySequenceOperator):
0585 """Used in the expression tree for a sequence as a stand in for the '!' operator"""
0586 def __init__(self, operand):
0587 super(_SequenceNegation,self).__init__(operand)
0588 def __str__(self):
0589 return '~%s' %self._operand
0590 def dumpSequenceConfig(self):
0591 return '!%s' %self._operand.dumpSequenceConfig()
0592 def dumpSequencePython(self, options=PrintOptions()):
0593 if self._operand.isOperation():
0594 return '~(%s)' %self._operand.dumpSequencePython(options)
0595 return '~%s' %self._operand.dumpSequencePython(options)
0596 def decoration(self):
0597 return '!'
0598
0599 class _SequenceIgnore(_UnarySequenceOperator):
0600 """Used in the expression tree for a sequence as a stand in for the '-' operator"""
0601 def __init__(self, operand):
0602 super(_SequenceIgnore,self).__init__(operand)
0603 def __str__(self):
0604 return 'ignore(%s)' %self._operand
0605 def dumpSequenceConfig(self):
0606 return '-%s' %self._operand.dumpSequenceConfig()
0607 def dumpSequencePython(self, options=PrintOptions()):
0608 return 'cms.ignore(%s)' %self._operand.dumpSequencePython(options)
0609 def decoration(self):
0610 return '-'
0611
0612 class _SequenceWait(_UnarySequenceOperator):
0613 """Used in the expression tree for a sequence as a stand in for the '|' operator"""
0614 def __init__(self, operand):
0615 super(_SequenceWait,self).__init__(operand)
0616 def __str__(self):
0617 return 'wait(%s)' %self._operand
0618 def dumpSequenceConfig(self):
0619 return '|%s' %self._operand.dumpSequenceConfig()
0620 def dumpSequencePython(self, options=PrintOptions()):
0621 return 'cms.wait(%s)' %self._operand.dumpSequencePython(options)
0622 def decoration(self):
0623 return '|'
0624
0625 class _SequenceWaitAndIgnore(_UnarySequenceOperator):
0626 """Used in the expression tree for a sequence as a stand in for the '+' operator"""
0627 def __init__(self, operand):
0628 super(_SequenceWaitAndIgnore,self).__init__(operand)
0629 def __str__(self):
0630 return 'wait(ignore(%s))' %self._operand
0631 def dumpSequenceConfig(self):
0632 return '+%s' %self._operand.dumpSequenceConfig()
0633 def dumpSequencePython(self, options=PrintOptions()):
0634 return 'cms.wait(cms.ignore(%s))' %self._operand.dumpSequencePython(options)
0635 def decoration(self):
0636 return '+'
0637
0638 def ignore(seq):
0639 """The EDFilter passed as an argument will be run but its filter value will be ignored
0640 """
0641 if isinstance(seq,_SequenceWait):
0642 return _SequenceWaitAndIgnore(seq._operand)
0643 return _SequenceIgnore(seq)
0644
0645 def wait(seq):
0646 """All modules after this module in the sequence will wait for this module to finish before being scheduled to run.
0647 """
0648 if isinstance(seq,_SequenceIgnore):
0649 return _SequenceWaitAndIgnore(seq._operand)
0650 return _SequenceWait(seq)
0651
0652 class Path(_ModuleSequenceType):
0653 def __init__(self,*arg,**argv):
0654 super(Path,self).__init__(*arg,**argv)
0655 def _placeImpl(self,name,proc):
0656 proc._placePath(name,self)
0657
0658 class EndPath(_ModuleSequenceType):
0659 def __init__(self,*arg,**argv):
0660 super(EndPath,self).__init__(*arg,**argv)
0661 def _placeImpl(self,name,proc):
0662 proc._placeEndPath(name,self)
0663
0664 class FinalPath(_ModuleSequenceType):
0665 def __init__(self,*arg,**argv):
0666 super(FinalPath,self).__init__(*arg,**argv)
0667 def _placeImpl(self,name,proc):
0668 proc._placeFinalPath(name,self)
0669 def associate(self,task):
0670 raise TypeError("FinalPath does not allow associations with Tasks")
0671
0672 class Sequence(_ModuleSequenceType,_Sequenceable):
0673 def __init__(self,*arg,**argv):
0674 super(Sequence,self).__init__(*arg,**argv)
0675 def _placeImpl(self,name,proc):
0676 proc._placeSequence(name,self)
0677 def _clonesequence(self, lookuptable):
0678 if id(self) not in lookuptable:
0679
0680
0681 if self._seq is not None:
0682 clone = type(self)(self._seq._clonesequence(lookuptable))
0683 else:
0684 clone = type(self)()
0685 lookuptable[id(self)]=clone
0686 lookuptable[id(clone)]=clone
0687 return lookuptable[id(self)]
0688 def _visitSubNodes(self,visitor):
0689 self.visit(visitor)
0690 class SequencePlaceholder(_Sequenceable):
0691 def __init__(self, name):
0692 self._name = name
0693 def _placeImpl(self,name,proc):
0694 pass
0695 def __str__(self):
0696 return self._name
0697 def insertInto(self, parameterSet, myname):
0698 raise RuntimeError("The SequencePlaceholder "+self._name
0699 +" was never overridden")
0700 def resolve(self, processDict,keepIfCannotResolve=False):
0701 if not self._name in processDict:
0702
0703 if keepIfCannotResolve:
0704 return self
0705 raise RuntimeError("The SequencePlaceholder "+self._name+ " cannot be resolved.\n Known keys are:"+str(processDict.keys()))
0706 o = processDict[self._name]
0707 if not isinstance(o,_Sequenceable):
0708 raise RuntimeError("The SequencePlaceholder "+self._name+ " refers to an object type which is not allowed to be on a sequence: "+str(type(o)))
0709 return o.resolve(processDict)
0710
0711 def _clonesequence(self, lookuptable):
0712 if id(self) not in lookuptable:
0713
0714
0715 clone = type(self)(self._name)
0716 lookuptable[id(self)]=clone
0717 lookuptable[id(clone)]=clone
0718 return lookuptable[id(self)]
0719 def copy(self):
0720 returnValue =SequencePlaceholder.__new__(type(self))
0721 returnValue.__init__(self._name)
0722 return returnValue
0723 def dumpSequenceConfig(self):
0724 return 'cms.SequencePlaceholder("%s")' %self._name
0725 def dumpSequencePython(self, options=PrintOptions()):
0726 return 'cms.SequencePlaceholder("%s")'%self._name
0727 def dumpPython(self, options=PrintOptions()):
0728 result = 'cms.SequencePlaceholder(\"'
0729 if options.isCfg:
0730 result += 'process.'
0731 result += self._name+'\")\n'
0732 return result
0733
0734
0735 class Schedule(_ValidatingParameterListBase,_ConfigureComponent,_Unlabelable):
0736
0737 def __init__(self,*arg,**argv):
0738 super(Schedule,self).__init__(*arg)
0739 self._tasks = OrderedSet()
0740 theKeys = list(argv.keys())
0741 if theKeys:
0742 if len(theKeys) > 1 or theKeys[0] != "tasks":
0743 raise RuntimeError("The Schedule constructor can only have one keyword argument after its Path and\nEndPath arguments and it must use the keyword 'tasks'")
0744 taskList = argv["tasks"]
0745
0746 if isinstance(taskList,Task):
0747 self.associate(taskList)
0748 else:
0749 try:
0750
0751 self.__dummy(*taskList)
0752 except:
0753 raise RuntimeError("The Schedule constructor argument with keyword 'tasks' must have a\nlist (or other iterable object) as its value")
0754 if taskList:
0755 self.associate(*taskList)
0756
0757 def __dummy(self, *args):
0758 pass
0759
0760 def associate(self,*tasks):
0761 for task in tasks:
0762 if not isinstance(task, Task):
0763 raise TypeError("The associate function in the class Schedule only works with arguments of type Task")
0764 self._tasks.add(task)
0765 @staticmethod
0766 def _itemIsValid(item):
0767 return isinstance(item,Path) or isinstance(item,EndPath) or isinstance(item,FinalPath)
0768 def copy(self):
0769 import copy
0770 aCopy = copy.copy(self)
0771 aCopy._tasks = OrderedSet(self._tasks)
0772 return aCopy
0773 def _place(self,label,process):
0774 process.setPartialSchedule_(self,label)
0775 def _replaceIfHeldDirectly(self,original,replacement):
0776 """Only replaces an 'original' with 'replacement' if 'original' is directly held.
0777 If a contained Path or Task holds 'original' it will not be replaced."""
0778 didReplace = False
0779 if original in self._tasks:
0780 self._tasks.remove(original)
0781 if replacement is not None:
0782 self._tasks.add(replacement)
0783 didReplace = True
0784 indices = []
0785 for i, e in enumerate(self):
0786 if original == e:
0787 indices.append(i)
0788 for i in reversed(indices):
0789 self.pop(i)
0790 if replacement is not None:
0791 self.insert(i, replacement)
0792 didReplace = True
0793 return didReplace
0794
0795 def moduleNames(self):
0796 result = set()
0797 visitor = NodeNameVisitor(result)
0798 for seq in self:
0799 seq.visit(visitor)
0800 for t in self._tasks:
0801 t.visit(visitor)
0802 return result
0803 def contains(self, mod):
0804 visitor = ContainsModuleVisitor(mod)
0805 for seq in self:
0806 seq.visit(visitor)
0807 if visitor.result():
0808 return True
0809 for t in self._tasks:
0810 t.visit(visitor)
0811 if visitor.result():
0812 return True
0813 return visitor.result()
0814 def tasks(self):
0815 """Returns the list of Tasks (that may contain other Tasks) that are associated directly to the Schedule."""
0816 return self._tasks
0817 def dumpPython(self, options=PrintOptions()):
0818 pathNames = ['process.'+p.label_() for p in self]
0819 if pathNames:
0820 s=', '.join(pathNames)
0821 else:
0822 s = ''
0823 associationContents = set()
0824 for task in self._tasks:
0825 if task.hasLabel_():
0826 associationContents.add(_Labelable.dumpSequencePython(task, options))
0827 else:
0828 associationContents.add(task.dumpPythonNoNewline(options))
0829 taskStrings = list()
0830 for iString in sorted(associationContents):
0831 taskStrings.append(iString)
0832 if taskStrings and s:
0833 return 'cms.Schedule(*[ ' + s + ' ], tasks=[' + ', '.join(taskStrings) + '])\n'
0834 elif s:
0835 return 'cms.Schedule(*[ ' + s + ' ])\n'
0836 elif taskStrings:
0837 return 'cms.Schedule(tasks=[' + ', '.join(taskStrings) + '])\n'
0838 else:
0839 return 'cms.Schedule()\n'
0840
0841 def __str__(self):
0842 return self.dumpPython()
0843
0844
0845
0846 class SequenceVisitor(object):
0847 def __init__(self,d):
0848 self.deps = d
0849 def enter(self,visitee):
0850 if isinstance(visitee,Sequence):
0851 self.deps.append(visitee)
0852 pass
0853 def leave(self,visitee):
0854 pass
0855
0856
0857
0858 class TaskVisitor(object):
0859 def __init__(self,d):
0860 self.deps = d
0861 def enter(self,visitee):
0862 if isinstance(visitee,Task):
0863 self.deps.append(visitee)
0864 pass
0865 def leave(self,visitee):
0866 pass
0867
0868
0869
0870 class ConditionalTaskVisitor(object):
0871 def __init__(self,d):
0872 self.deps = d
0873 def enter(self,visitee):
0874 if isinstance(visitee,ConditionalTask):
0875 self.deps.append(visitee)
0876 pass
0877 def leave(self,visitee):
0878 pass
0879
0880
0881
0882
0883
0884
0885
0886
0887
0888 class ModuleNodeVisitor(object):
0889 def __init__(self,l):
0890 self.l = l
0891 def enter(self,visitee):
0892 if visitee.isLeaf():
0893 self.l.append(visitee)
0894 pass
0895 def leave(self,visitee):
0896 pass
0897
0898
0899
0900
0901
0902
0903 class ModuleNodeOnTaskVisitor(object):
0904 def __init__(self,l):
0905 self.l = l
0906 self._levelInTasks = 0
0907 def enter(self,visitee):
0908 if isinstance(visitee, Task):
0909 self._levelInTasks += 1
0910 if self._levelInTasks == 0:
0911 return
0912 if visitee.isLeaf():
0913 self.l.append(visitee)
0914 pass
0915 def leave(self,visitee):
0916 if self._levelInTasks > 0:
0917 if isinstance(visitee, Task):
0918 self._levelInTasks -= 1
0919
0920 class ModuleNodeOnConditionalTaskVisitor(object):
0921 def __init__(self,l):
0922 self.l = l
0923 self._levelInTasks = 0
0924 def enter(self,visitee):
0925 if isinstance(visitee, ConditionalTask):
0926 self._levelInTasks += 1
0927
0928
0929
0930
0931 if hasattr(visitee, "modulesForConditionalTask_"):
0932 self.l.extend(visitee.modulesForConditionalTask_())
0933 if self._levelInTasks == 0:
0934 return
0935 if visitee.isLeaf():
0936 self.l.append(visitee)
0937 pass
0938 def leave(self,visitee):
0939 if self._levelInTasks > 0:
0940 if isinstance(visitee, ConditionalTask):
0941 self._levelInTasks -= 1
0942
0943
0944
0945
0946
0947
0948
0949 class ModuleNodeNotOnTaskVisitor(object):
0950 def __init__(self,l):
0951 self.l = l
0952 self._levelInTasks = 0
0953 def enter(self,visitee):
0954 if isinstance(visitee, Task):
0955 self._levelInTasks += 1
0956 if self._levelInTasks > 0:
0957 return
0958 if visitee.isLeaf():
0959 self.l.append(visitee)
0960 pass
0961 def leave(self,visitee):
0962 if self._levelInTasks > 0:
0963 if isinstance(visitee, Task):
0964 self._levelInTasks -= 1
0965
0966
0967
0968
0969
0970
0971 class ContainsModuleVisitor(object):
0972 def __init__(self,mod):
0973 self._mod = mod
0974 self._result = False
0975
0976 def result(self):
0977 return self._result
0978
0979 def enter(self,visitee):
0980 if self._mod is visitee:
0981 self._result = True
0982
0983 def leave(self,visitee):
0984 pass
0985
0986
0987
0988
0989
0990
0991
0992
0993
0994
0995 class NodeNameVisitor(object):
0996 """ takes a set as input"""
0997 def __init__(self,l):
0998 self.l = l
0999 def enter(self,visitee):
1000 if visitee.isLeaf():
1001 if isinstance(visitee, _Labelable):
1002 self.l.add(visitee.label_())
1003 else:
1004 if visitee._inProcess:
1005 self.l.add(visitee.type_())
1006 else:
1007 raise RuntimeError("Service not attached to process: {}".format(visitee.dumpPython()))
1008 def leave(self,visitee):
1009 pass
1010
1011
1012
1013 class ExpandVisitor(object):
1014 """ Expands the sequence into leafs and UnaryOperators """
1015 def __init__(self, type):
1016 self._type = type
1017 self.l = []
1018 self.taskLeaves = []
1019 self.taskLeavesInConditionalTasks = []
1020 self.presentTaskLeaves = self.taskLeaves
1021 self._levelInTasks = 0
1022 self.conditionaltaskLeaves = []
1023 self._levelInConditionalTasks = 0
1024
1025 def enter(self,visitee):
1026 if isinstance(visitee, Task):
1027 self._levelInTasks += 1
1028 return
1029 if isinstance(visitee, ConditionalTask):
1030 self.presentTaskLeaves = self.taskLeavesInConditionalTasks
1031 self._levelInConditionalTasks += 1
1032 return
1033 if visitee.isLeaf():
1034 if self._levelInTasks > 0:
1035 self.presentTaskLeaves.append(visitee)
1036 elif self._levelInConditionalTasks > 0:
1037 self.conditionaltaskLeaves.append(visitee)
1038 else:
1039 self.l.append(visitee)
1040 def leave(self, visitee):
1041 if self._levelInTasks > 0:
1042 if isinstance(visitee, Task):
1043 self._levelInTasks -= 1
1044 return
1045 if self._levelInConditionalTasks > 0:
1046 if isinstance(visitee, ConditionalTask):
1047 self._levelInConditionalTasks -= 1
1048 if 0 == self._levelInConditionalTasks:
1049 self.presentTaskLeaves = self.taskLeaves
1050 return
1051 if isinstance(visitee,_UnarySequenceOperator):
1052 self.l[-1] = visitee
1053 def result(self):
1054 tsks = []
1055 if self.taskLeaves:
1056 tsks.append(Task(*self.taskLeaves))
1057 if self.conditionaltaskLeaves:
1058 ct = ConditionalTask(*self.conditionaltaskLeaves)
1059 if self.taskLeavesInConditionalTasks:
1060 ct.append(*self.taskLeavesInConditionalTasks)
1061 tsks.append(ct)
1062 if len(self.l) > 0:
1063
1064 seq = self.l[0]
1065 for el in self.l[1:]:
1066 seq += el
1067 return self._type(seq, *tsks)
1068 else:
1069 return self._type(*tsks)
1070 def resultString(self):
1071 sep = ''
1072 returnValue = ''
1073 for m in self.l:
1074 if m is not None:
1075 returnValue += sep+str(m)
1076 sep = '+'
1077 if returnValue:
1078 sep = ','
1079 for n in self.taskLeaves:
1080 if n is not None:
1081 returnValue += sep+str(n)
1082 sep = ','
1083 return returnValue
1084
1085
1086
1087
1088 class DecoratedNodeNameVisitor(object):
1089 """ Adds any '!' or '-' needed. Takes a list """
1090 def __init__(self,l):
1091 self.l = l
1092 self._decoration =''
1093 self._levelInTasks = 0
1094
1095 def initialize(self):
1096 self.l[:] = []
1097 self._decoration =''
1098 self._levelInTasks = 0
1099
1100 def enter(self,visitee):
1101 if isinstance(visitee, _TaskBase):
1102 self._levelInTasks += 1
1103 if self._levelInTasks > 0:
1104 return
1105 if visitee.isLeaf():
1106 if hasattr(visitee, "_Labelable__label"):
1107 self.l.append(self._decoration+visitee.label_())
1108 else:
1109 error = "An object in a sequence was not found in the process\n"
1110 if hasattr(visitee, "_filename"):
1111 error += "From file " + visitee._filename
1112 else:
1113 error += "Dump follows\n" + repr(visitee)
1114 raise RuntimeError(error)
1115 if isinstance(visitee,_BooleanLogicExpression):
1116 self.l.append(self._decoration+visitee.operatorString())
1117 if isinstance(visitee,_UnarySequenceOperator):
1118 self._decoration=visitee.decoration()
1119 else:
1120 self._decoration=''
1121
1122 def leave(self,visitee):
1123
1124 if self._levelInTasks > 0:
1125 if isinstance(visitee, _TaskBase):
1126 self._levelInTasks -= 1
1127 return
1128 if isinstance(visitee,_BooleanLogicExpression):
1129
1130 self.l.append('@')
1131
1132
1133
1134
1135 class DecoratedNodeNamePlusVisitor(object):
1136 """ Adds any '!' or '-' needed. Takes a list """
1137 def __init__(self,l):
1138 self.l = l
1139 self._decoration =''
1140 self._levelInTasks = 0
1141 self._leavesOnTasks = []
1142
1143 def initialize(self):
1144 self.l[:] = []
1145 self._decoration =''
1146 self._levelInTasks = 0
1147 self._leavesOnTasks[:] = []
1148
1149 def enter(self,visitee):
1150 if isinstance(visitee, Task):
1151 self._levelInTasks += 1
1152 if self._levelInTasks > 0:
1153 if visitee.isLeaf():
1154 self._leavesOnTasks.append(visitee)
1155 return
1156 if visitee.isLeaf():
1157 if hasattr(visitee, "_Labelable__label"):
1158 self.l.append(self._decoration+visitee.label_())
1159 else:
1160 error = "An object in a sequence was not found in the process\n"
1161 if hasattr(visitee, "_filename"):
1162 error += "From file " + visitee._filename
1163 else:
1164 error += "Dump follows\n" + repr(visitee)
1165 raise RuntimeError(error)
1166 if isinstance(visitee,_BooleanLogicExpression):
1167 self.l.append(self._decoration+visitee.operatorString())
1168 if isinstance(visitee,_UnarySequenceOperator):
1169 self._decoration=visitee.decoration()
1170 else:
1171 self._decoration=''
1172
1173 def leave(self,visitee):
1174
1175 if self._levelInTasks > 0:
1176 if isinstance(visitee, Task):
1177 self._levelInTasks -= 1
1178 return
1179 if isinstance(visitee,_BooleanLogicExpression):
1180
1181 self.l.append('@')
1182
1183 def leavesOnTasks(self):
1184 return self._leavesOnTasks
1185
1186 class _CopyAndExcludeSequenceVisitorOld(object):
1187 """Traverses a Sequence and constructs a new sequence which does not contain modules from the specified list"""
1188 def __init__(self,modulesToRemove):
1189 self.__modulesToIgnore = modulesToRemove
1190 self.__stack = list()
1191 self.__stack.append(list())
1192 self.__result = None
1193 self.__didExclude = False
1194 def enter(self,visitee):
1195 if len(self.__stack) > 0:
1196
1197 self.__stack[-1].append([visitee,False])
1198 if visitee.isLeaf():
1199 if visitee in self.__modulesToIgnore:
1200 self.__didExclude = True
1201 self.__stack[-1][-1]=[None,True]
1202 elif isinstance(visitee, Sequence):
1203 if visitee in self.__modulesToIgnore:
1204 self.__didExclude = True
1205 self.__stack[-1][-1]=[None,True]
1206 self.__stack.append(list())
1207 else:
1208
1209 self.__stack.append(list())
1210 def leave(self,visitee):
1211 node = visitee
1212 if not visitee.isLeaf():
1213
1214 l = self.__stack[-1]
1215 changed = False
1216 countNulls = 0
1217 nonNulls = list()
1218 for c in l:
1219 if c[1] == True:
1220 changed = True
1221 if c[0] is None:
1222 countNulls +=1
1223 else:
1224 nonNulls.append(c[0])
1225 if changed:
1226 self.__didExclude = True
1227 if countNulls != 0:
1228
1229 if len(nonNulls) == 0:
1230
1231 node = None
1232 else:
1233 node = nonNulls[0]
1234 for n in nonNulls[1:]:
1235 node = node+n
1236 else:
1237
1238
1239
1240 children = [x[0] for x in l ]
1241 if not isinstance(visitee,Sequence):
1242 node = visitee.__new__(type(visitee))
1243 node.__init__(*children)
1244 else:
1245 node = nonNulls[0]
1246 if node != visitee:
1247
1248
1249 if len(self.__stack) > 1:
1250 p = self.__stack[-2]
1251
1252 for i,c in enumerate(p):
1253 if c[0]==visitee:
1254 c[0]=node
1255 c[1]=True
1256 break
1257 if not visitee.isLeaf():
1258 self.__stack = self.__stack[:-1]
1259 def result(self):
1260 result = None
1261 for n in (x[0] for x in self.__stack[0]):
1262 if n is None:
1263 continue
1264 if result is None:
1265 result = n
1266 else:
1267 result = result+n
1268 return result
1269 def didExclude(self):
1270 return self.__didExclude
1271
1272
1273
1274 class _MutatingSequenceVisitor(object):
1275 """Traverses a Sequence and constructs a new sequence by applying the operator to each element of the sequence"""
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324 def __init__(self,operator):
1325 self.__operator = operator
1326
1327
1328 self.__stack = list()
1329 self.__stack.append(list())
1330 self.__didApply = False
1331 self.__levelInModifiedNonLeaf = 0
1332 def enter(self,visitee):
1333
1334
1335 if self.__levelInModifiedNonLeaf > 0:
1336 if not visitee.isLeaf():
1337 self.__levelInModifiedNonLeaf += 1
1338 return
1339
1340
1341 if not len(self.__stack) > 0:
1342 raise RuntimeError("LogicError Empty stack in MutatingSequenceVisitor.\n"
1343 "This should never happen. Contact a Framework developer.")
1344
1345
1346
1347
1348 v = self.__operator(visitee)
1349
1350 if v is visitee:
1351
1352
1353
1354
1355
1356
1357
1358
1359 self.__stack[-1].append([visitee, False, None])
1360 if not visitee.isLeaf():
1361
1362
1363 self.__stack.append(list())
1364 else:
1365
1366 self.__didApply = True
1367 self.__stack[-1].append([v, True, None])
1368 if not visitee.isLeaf():
1369
1370 self.__levelInModifiedNonLeaf = 1
1371 def leave(self,visitee):
1372
1373
1374 if visitee.isLeaf():
1375 return
1376
1377
1378
1379 if self.__levelInModifiedNonLeaf > 0:
1380 self.__levelInModifiedNonLeaf -= 1
1381 return
1382
1383
1384
1385
1386
1387
1388 contents = self.__stack[-1]
1389 changed = False
1390 allNull = True
1391 for c in contents:
1392 if c[1] == True:
1393 changed = True
1394 if c[0] is not None:
1395 allNull = False
1396 if changed:
1397 if allNull:
1398 self.__stack[-2][-1] = [None, True, None]
1399
1400 elif isinstance(visitee, _UnarySequenceOperator):
1401 node = visitee.__new__(type(visitee))
1402 node.__init__(contents[0][0])
1403 self.__stack[-2][-1] = [node, True, None]
1404
1405 elif isinstance(visitee, _TaskBase):
1406 nonNull = []
1407 for c in contents:
1408 if c[0] is not None:
1409 nonNull.append(c[0])
1410 self.__stack[-2][-1] = [visitee._makeInstance(*nonNull), True, None]
1411 elif isinstance(visitee, Sequence):
1412 seq = _SequenceCollection()
1413 tasks = list()
1414 for c in contents:
1415 if c[0] is None:
1416 continue
1417 if isinstance(c[0], _TaskBase):
1418 tasks.append(c[0])
1419 else:
1420 seq = seq + c[0]
1421 if c[2] is not None:
1422 tasks.extend(c[2])
1423
1424 self.__stack[-2][-1] = [seq, True, tasks]
1425
1426
1427
1428
1429 if not visitee.isLeaf():
1430 self.__stack = self.__stack[:-1]
1431
1432 def result(self, visitedContainer):
1433
1434 if isinstance(visitedContainer, _TaskBase):
1435 result = list()
1436 for n in (x[0] for x in self.__stack[0]):
1437 if n is not None:
1438 result.append(n)
1439 return result
1440
1441 seq = _SequenceCollection()
1442 tasks = list()
1443 for c in self.__stack[0]:
1444 if c[0] is None:
1445 continue
1446 if isinstance(c[0], _TaskBase):
1447 tasks.append(c[0])
1448 else:
1449 seq = seq + c[0]
1450 if c[2] is not None:
1451 tasks.extend(c[2])
1452 return [seq, tasks]
1453
1454 def _didApply(self):
1455 return self.__didApply
1456
1457
1458 class _CopyAndRemoveFirstSequenceVisitor(_MutatingSequenceVisitor):
1459 """Traverses a Sequence and constructs a new sequence which does not contain modules from the specified list"""
1460 def __init__(self,moduleToRemove):
1461 class _RemoveFirstOperator(object):
1462 def __init__(self,moduleToRemove):
1463 self.__moduleToRemove = moduleToRemove
1464 self.__found = False
1465 def __call__(self,test):
1466 if not self.__found and test is self.__moduleToRemove:
1467 self.__found = True
1468 return None
1469 return test
1470 super(type(self),self).__init__(_RemoveFirstOperator(moduleToRemove))
1471 def didRemove(self):
1472 return self._didApply()
1473
1474
1475 class _CopyAndExcludeSequenceVisitor(_MutatingSequenceVisitor):
1476 """Traverses a Sequence and constructs a new sequence which does not contain the module specified"""
1477 def __init__(self,modulesToRemove):
1478 class _ExcludeOperator(object):
1479 def __init__(self,modulesToRemove):
1480 self.__modulesToIgnore = modulesToRemove
1481 def __call__(self,test):
1482 if test in modulesToRemove:
1483 return None
1484 return test
1485 super(type(self),self).__init__(_ExcludeOperator(modulesToRemove))
1486 def didExclude(self):
1487 return self._didApply()
1488
1489
1490 class _CopyAndReplaceSequenceVisitor(_MutatingSequenceVisitor):
1491 """Traverses a Sequence and constructs a new sequence which replaces a specified module with a different module"""
1492 def __init__(self,target,replace):
1493 class _ReplaceOperator(object):
1494 def __init__(self,target,replace):
1495 self.__target = target
1496 self.__replace = replace
1497 def __call__(self,test):
1498 if test == self.__target:
1499 return self.__replace
1500 return test
1501 super(type(self),self).__init__(_ReplaceOperator(target,replace))
1502 def didReplace(self):
1503 return self._didApply()
1504
1505 class _TaskBase(_ConfigureComponent, _Labelable) :
1506 def __init__(self, *items):
1507 self._collection = OrderedSet()
1508 self.add(*items)
1509
1510 def __setattr__(self,name,value):
1511 if not name.startswith("_"):
1512 raise AttributeError("You cannot set parameters for {} objects.".format(self._taskType()))
1513 else:
1514 self.__dict__[name] = value
1515
1516 def add(self, *items):
1517 for item in items:
1518 if not self._allowedInTask(item):
1519 raise RuntimeError("Adding an entry of type '{0}' to a {1}.\n"
1520 "It is illegal to add this type to a {1}.".format(type(item).__name__, self._taskType()))
1521 self._collection.add(item)
1522
1523 def fillContents(self, taskContents, options=PrintOptions()):
1524
1525 if self.hasLabel_():
1526 taskContents.add(_Labelable.dumpSequencePython(self, options))
1527 else:
1528 for i in self._collection:
1529 if isinstance(i, _TaskBase):
1530 i.fillContents(taskContents, options)
1531 else:
1532 taskContents.add(i.dumpSequencePython(options))
1533
1534 def dumpPython(self, options=PrintOptions()):
1535 s = self.dumpPythonNoNewline(options)
1536 return s + "\n"
1537
1538 def dumpPythonNoNewline(self, options=PrintOptions()):
1539 """Returns a string which is the python representation of the object"""
1540 taskContents = set()
1541 for i in self._collection:
1542 if isinstance(i, _TaskBase):
1543 i.fillContents(taskContents, options)
1544 else:
1545 taskContents.add(i.dumpSequencePython(options))
1546 s=''
1547 iFirst = True
1548 for item in sorted(taskContents):
1549 if not iFirst:
1550 s += ", "
1551 iFirst = False
1552 s += item
1553 if len(taskContents) > 255:
1554 s = "*[" + s + "]"
1555 return "cms.{}({})".format(self._taskType(),s)
1556
1557 def directDependencies(self,sortByType=True):
1558 return findDirectDependencies(self, self._collection,sortByType=sortByType)
1559
1560 def _isTaskComponent(self):
1561 return False
1562
1563 def isLeaf(self):
1564 return False
1565
1566 def visit(self,visitor):
1567 for i in self._collection:
1568 visitor.enter(i)
1569 if not i.isLeaf():
1570 i.visit(visitor)
1571 visitor.leave(i)
1572
1573 def _errorstr(self):
1574 return "{}(...)".format(self.taskType_())
1575
1576 def __iter__(self):
1577 for key in self._collection:
1578 yield key
1579
1580 def __str__(self):
1581 l = []
1582 v = ModuleNodeVisitor(l)
1583 self.visit(v)
1584 s = ''
1585 for i in l:
1586 if s:
1587 s += ', '
1588 s += str (i)
1589 return s
1590
1591 def __repr__(self):
1592 s = str(self)
1593 return "cms."+type(self).__name__+'('+s+')\n'
1594
1595 def moduleNames(self):
1596 """Returns a set containing the names of all modules being used"""
1597 result = set()
1598 visitor = NodeNameVisitor(result)
1599 self.visit(visitor)
1600 return result
1601 def contains(self, mod):
1602 visitor = ContainsModuleVisitor(mod)
1603 self.visit(visitor)
1604 return visitor.result()
1605 def copy(self):
1606 return self._makeInstance(*self._collection)
1607 def copyAndExclude(self,listOfModulesToExclude):
1608 """Returns a copy of the sequence which excludes those module in 'listOfModulesToExclude'"""
1609
1610
1611
1612
1613
1614 for i in listOfModulesToExclude:
1615 if not i._isTaskComponent():
1616 raise TypeError("copyAndExclude can only exclude objects that can be placed on a Task")
1617 v = _CopyAndExcludeSequenceVisitor(listOfModulesToExclude)
1618 self.visit(v)
1619 return self._makeInstance(*v.result(self))
1620 def copyAndAdd(self, *modulesToAdd):
1621 """Returns a copy of the Task adding modules/tasks"""
1622 t = self.copy()
1623 t.add(*modulesToAdd)
1624 return t
1625 def expandAndClone(self):
1626
1627
1628
1629
1630 l = []
1631 v = ModuleNodeVisitor(l)
1632 self.visit(v)
1633 return self._makeInstance(*l)
1634 def replace(self, original, replacement):
1635 """Finds all instances of 'original' and substitutes 'replacement' for them.
1636 Returns 'True' if a replacement occurs."""
1637
1638
1639
1640
1641
1642
1643
1644 if not self._allowedInTask(original) or (not replacement is None and not self._allowedInTask(replacement)):
1645 raise TypeError("The {0} replace function only works with objects that can be placed on a {0}\n".format(self._taskType()) + \
1646 " replace was called with original type = {}\n".format(str(type(original))) + \
1647 " and replacement type = {}\n".format(str(type(replacement))))
1648 else:
1649 v = _CopyAndReplaceSequenceVisitor(original,replacement)
1650 self.visit(v)
1651 if v.didReplace():
1652 self._collection.clear()
1653 self.add(*v.result(self))
1654 return v.didReplace()
1655
1656 def remove(self, something):
1657 """Remove the first occurrence of a module
1658 Returns 'True' if the module has been removed, False if it was not found"""
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669 if not self._allowedInTask(something):
1670 raise TypeError("remove only works with objects that can be placed on a Task")
1671 v = _CopyAndRemoveFirstSequenceVisitor(something)
1672 self.visit(v)
1673 if v.didRemove():
1674 self._collection.clear()
1675 self.add(*v.result(self))
1676 return v.didRemove()
1677
1678 def resolve(self, processDict,keepIfCannotResolve=False):
1679 temp = OrderedSet()
1680 for i in self._collection:
1681 if self._mustResolve(i):
1682 temp.add(i.resolve(processDict,keepIfCannotResolve))
1683 else:
1684 temp.add(i)
1685 self._collection = temp
1686 return self
1687
1688 class _TaskBasePlaceholder(object):
1689 def __init__(self, name):
1690 self._name = name
1691 def _isTaskComponent(self):
1692 return False
1693 def isLeaf(self):
1694 return False
1695 def visit(self,visitor):
1696 pass
1697 def __str__(self):
1698 return self._name
1699 def insertInto(self, parameterSet, myname):
1700 raise RuntimeError("The {} {} was never overridden".format(self._typeName(), self._name))
1701 def resolve(self, processDict,keepIfCannotResolve=False):
1702 if not self._name in processDict:
1703 if keepIfCannotResolve:
1704 return self
1705 raise RuntimeError("The {} {} cannot be resolved.\n Known keys are: {}".format(self._typeName(), self._name,str(processDict.keys())))
1706 o = processDict[self._name]
1707 if not self._allowedInTask(o):
1708 raise RuntimeError("The {} {} refers to an object type which is not allowed to be on a task: {}".format(self._typeName(), self._name, str(type(o))))
1709 if isinstance(o, self._taskClass()):
1710 return o.resolve(processDict)
1711 return o
1712 def copy(self):
1713 return self._makeInstance(self._name)
1714 def dumpSequencePython(self, options=PrintOptions()):
1715 return 'cms.{}("{}")'.format(self._typeName(), self._name)
1716 def dumpPython(self, options=PrintOptions()):
1717 result = 'cms.{}(\"'.format(self._typeName())
1718 if options.isCfg:
1719 result += 'process.'
1720 result += self._name+'\")\n'
1721 return result
1722
1723 class Task(_TaskBase) :
1724 """Holds EDProducers, EDFilters, ESProducers, ESSources, Services, and Tasks.
1725 A Task can be associated with Sequences, Paths, EndPaths, ConditionalTasks and the Schedule.
1726 An EDProducer or EDFilter will be enabled to run unscheduled if it is on
1727 a task associated with the Schedule or any scheduled Path or EndPath (directly
1728 or indirectly through Sequences) and not be on any scheduled Path or EndPath.
1729 ESSources, ESProducers, and Services will be enabled to run if they are on
1730 a Task associated with the Schedule or a scheduled Path or EndPath. In other
1731 cases, they will be enabled to run if and only if they are not on a Task attached
1732 to the process.
1733 """
1734 @staticmethod
1735 def _taskType():
1736 return "Task"
1737 def _place(self, name, proc):
1738 proc._placeTask(name,self)
1739 def _isTaskComponent(self):
1740 return True
1741 @staticmethod
1742 def _makeInstance(*items):
1743 return Task(*items)
1744 @staticmethod
1745 def _allowedInTask(item ):
1746 return (isinstance(item, _ConfigureComponent) and item._isTaskComponent()) or isinstance(item, TaskPlaceholder)
1747 @staticmethod
1748 def _mustResolve(item):
1749 return isinstance(item, Task) or isinstance(item, TaskPlaceholder)
1750
1751 class TaskPlaceholder(_TaskBasePlaceholder):
1752 def _isTaskComponent(self):
1753 return True
1754 @staticmethod
1755 def _typeName():
1756 return "TaskPlaceholder"
1757 @staticmethod
1758 def _makeInstance(name):
1759 return TaskPlaceholder(name)
1760 @staticmethod
1761 def _allowedInTask(obj):
1762 return Task._allowedInTask(obj)
1763 @staticmethod
1764 def _taskClass():
1765 return Task
1766
1767
1768 class ConditionalTask(_TaskBase) :
1769 """Holds EDProducers, EDFilters, ESProducers, ESSources, Services, Tasks and ConditionalTasks.
1770 A ConditionalTask can be associated with Sequences, Paths, and EndPaths.
1771 An EDProducer or EDFilter will be added to a Path or EndPath based on which other
1772 modules on the Path consumes its data products. If that ConditionalTask assigned module
1773 is placed after an EDFilter, the module will only run if the EDFilter passes. If no module
1774 on the Path needs the module's data products, the module will be treated as if it were on a Task.
1775 """
1776 @staticmethod
1777 def _taskType():
1778 return "ConditionalTask"
1779 def _place(self, name, proc):
1780 proc._placeConditionalTask(name,self)
1781 def _isTaskComponent(self):
1782 return False
1783 @staticmethod
1784 def _makeInstance(*items):
1785 return ConditionalTask(*items)
1786 @staticmethod
1787 def _allowedInTask(item):
1788 return isinstance(item, ConditionalTask) or isinstance(item, ConditionalTaskPlaceholder) or Task._allowedInTask(item)
1789 @staticmethod
1790 def _mustResolve(item):
1791 return Task._mustResolve(item) or isinstance(item, ConditionalTask) or isinstance(item, ConditionalTaskPlaceholder)
1792
1793
1794 class ConditionalTaskPlaceholder(_TaskBasePlaceholder):
1795 def _isTaskComponent(self):
1796 return False
1797 @staticmethod
1798 def _typeName():
1799 return "ConditionalTaskPlaceholder"
1800 @staticmethod
1801 def _makeInstance(name):
1802 return ConditionalTaskPlaceholder(name)
1803 @staticmethod
1804 def _allowedInTask(obj):
1805 return Task._allowedInTask(obj) or ConditionalTask._allowedInTask(obj)
1806 @staticmethod
1807 def _taskClass():
1808 return ConditionalTask
1809
1810
1811 if __name__=="__main__":
1812 import unittest
1813 class DummyModule(_Labelable, _SequenceLeaf, _ConfigureComponent):
1814 def __init__(self,name):
1815 self.setLabel(name)
1816 def _isTaskComponent(self):
1817 return True
1818 def __repr__(self):
1819 return self.label_()
1820 class DummyBooleanModule(_Labelable, _BooleanLogicSequenceLeaf):
1821 def __init__(self,name):
1822 self.setLabel(name)
1823 class TestModuleCommand(unittest.TestCase):
1824 def setUp(self):
1825 """Nothing to do """
1826 pass
1827 def testBoolean(self):
1828 a = DummyBooleanModule("a")
1829 b = DummyBooleanModule("b")
1830 p = Path( a & b)
1831 self.assertEqual(p.dumpPython(),"cms.Path(process.a&process.b)\n")
1832 l = list()
1833 namesVisitor = DecoratedNodeNameVisitor(l)
1834 p.visit(namesVisitor)
1835 self.assertEqual(l,['&','a','b','@'])
1836 p2 = Path( a | b)
1837 self.assertEqual(p2.dumpPython(),"cms.Path(process.a|process.b)\n")
1838 l[:]=[]
1839 p2.visit(namesVisitor)
1840 self.assertEqual(l,['|','a','b','@'])
1841 c = DummyBooleanModule("c")
1842 d = DummyBooleanModule("d")
1843 p3 = Path(a & b & c & d)
1844 self.assertEqual(p3.dumpPython(),"cms.Path(process.a&process.b&process.c&process.d)\n")
1845 l[:]=[]
1846 p3.visit(namesVisitor)
1847 self.assertEqual(l,['&','a','b','c','d','@'])
1848 p3 = Path(((a & b) & c) & d)
1849 self.assertEqual(p3.dumpPython(),"cms.Path(process.a&process.b&process.c&process.d)\n")
1850 p3 = Path(a & (b & (c & d)))
1851 self.assertEqual(p3.dumpPython(),"cms.Path(process.a&process.b&process.c&process.d)\n")
1852 p3 = Path((a & b) & (c & d))
1853 self.assertEqual(p3.dumpPython(),"cms.Path(process.a&process.b&process.c&process.d)\n")
1854 p3 = Path(a & (b & c) & d)
1855 self.assertEqual(p3.dumpPython(),"cms.Path(process.a&process.b&process.c&process.d)\n")
1856 p4 = Path(a | b | c | d)
1857 self.assertEqual(p4.dumpPython(),"cms.Path(process.a|process.b|process.c|process.d)\n")
1858 p5 = Path(a | b & c & d )
1859 self.assertEqual(p5.dumpPython(),"cms.Path(process.a|(process.b&process.c&process.d))\n")
1860 l[:]=[]
1861 p5.visit(namesVisitor)
1862 self.assertEqual(l,['|','a','&','b','c','d','@','@'])
1863 p5 = Path(a & b | c & d )
1864 self.assertEqual(p5.dumpPython(),"cms.Path((process.a&process.b)|(process.c&process.d))\n")
1865 l[:]=[]
1866 p5.visit(namesVisitor)
1867 self.assertEqual(l,['|','&','a','b','@','&','c','d','@','@'])
1868 p5 = Path(a & (b | c) & d )
1869 self.assertEqual(p5.dumpPython(),"cms.Path(process.a&(process.b|process.c)&process.d)\n")
1870 l[:]=[]
1871 p5.visit(namesVisitor)
1872 self.assertEqual(l,['&','a','|','b','c','@','d','@'])
1873 p5 = Path(a & b & c | d )
1874 self.assertEqual(p5.dumpPython(),"cms.Path((process.a&process.b&process.c)|process.d)\n")
1875 l[:]=[]
1876 p5.visit(namesVisitor)
1877 self.assertEqual(l,['|','&','a','b','c','@','d','@'])
1878 p6 = Path( a & ~b)
1879 self.assertEqual(p6.dumpPython(),"cms.Path(process.a&(~process.b))\n")
1880 l[:]=[]
1881 p6.visit(namesVisitor)
1882 self.assertEqual(l,['&','a','!b','@'])
1883 p6 = Path( a & ignore(b))
1884 self.assertEqual(p6.dumpPython(),"cms.Path(process.a&(cms.ignore(process.b)))\n")
1885 l[:]=[]
1886 p6.visit(namesVisitor)
1887 self.assertEqual(l,['&','a','-b','@'])
1888 p6 = Path( a & wait(b))
1889 self.assertEqual(p6.dumpPython(),"cms.Path(process.a&(cms.wait(process.b)))\n")
1890 l[:]=[]
1891 p6.visit(namesVisitor)
1892 self.assertEqual(l,['&','a','|b','@'])
1893 p6 = Path( a & wait(ignore(b)))
1894 self.assertEqual(p6.dumpPython(),"cms.Path(process.a&(cms.wait(cms.ignore(process.b))))\n")
1895 l[:]=[]
1896 p6.visit(namesVisitor)
1897 self.assertEqual(l,['&','a','+b','@'])
1898 p6 = Path( a & ignore(wait(b)))
1899 self.assertEqual(p6.dumpPython(),"cms.Path(process.a&(cms.wait(cms.ignore(process.b))))\n")
1900 l[:]=[]
1901 p6.visit(namesVisitor)
1902 self.assertEqual(l,['&','a','+b','@'])
1903 p6 = Path(~(a&b))
1904 self.assertEqual(p6.dumpPython(),"cms.Path(~(process.a&process.b))\n")
1905 l[:]=[]
1906 p6.visit(namesVisitor)
1907 self.assertEqual(l,['!&','a','b','@'])
1908
1909 def testTaskConstructor(self):
1910 a = DummyModule("a")
1911 self.assertRaises(RuntimeError, lambda : Task(ConditionalTask(a)) )
1912
1913 def testDumpPython(self):
1914 a = DummyModule("a")
1915 b = DummyModule('b')
1916 p = Path((a*b))
1917
1918 self.assertEqual(p.dumpPython(),"cms.Path(process.a+process.b)\n")
1919 p2 = Path((b+a))
1920
1921 self.assertEqual(p2.dumpPython(),"cms.Path(process.b+process.a)\n")
1922 c = DummyModule('c')
1923 p3 = Path(c*(a+b))
1924
1925 self.assertEqual(p3.dumpPython(),"cms.Path(process.c+process.a+process.b)\n")
1926 p4 = Path(c*a+b)
1927
1928 self.assertEqual(p4.dumpPython(),"cms.Path(process.c+process.a+process.b)\n")
1929 p5 = Path(a+ignore(b))
1930
1931 self.assertEqual(p5.dumpPython(),"cms.Path(process.a+cms.ignore(process.b))\n")
1932 p5a = Path(a+wait(b))
1933 self.assertEqual(p5a.dumpPython(),"cms.Path(process.a+cms.wait(process.b))\n")
1934 p5b = Path(a+ignore(wait(b)))
1935 self.assertEqual(p5b.dumpPython(),"cms.Path(process.a+cms.wait(cms.ignore(process.b)))\n")
1936 p5c = Path(a+wait(ignore(b)))
1937 self.assertEqual(p5c.dumpPython(),"cms.Path(process.a+cms.wait(cms.ignore(process.b)))\n")
1938 p6 = Path(c+a*b)
1939
1940 self.assertEqual(p6.dumpPython(),"cms.Path(process.c+process.a+process.b)\n")
1941 p7 = Path(a+~b)
1942 self.assertEqual(p7.dumpPython(),"cms.Path(process.a+~process.b)\n")
1943 p8 = Path((a+b)*c)
1944 self.assertEqual(p8.dumpPython(),"cms.Path(process.a+process.b+process.c)\n")
1945 t1 = Task(a)
1946 t2 = Task(c, b)
1947 t3 = Task()
1948 p9 = Path((a+b)*c, t1)
1949 self.assertEqual(p9.dumpPython(),"cms.Path(process.a+process.b+process.c, cms.Task(process.a))\n")
1950 p10 = Path((a+b)*c, t2, t1)
1951 self.assertEqual(p10.dumpPython(),"cms.Path(process.a+process.b+process.c, cms.Task(process.a), cms.Task(process.b, process.c))\n")
1952 p11 = Path(t1, t2, t3)
1953 self.assertEqual(p11.dumpPython(),"cms.Path(cms.Task(), cms.Task(process.a), cms.Task(process.b, process.c))\n")
1954 d = DummyModule("d")
1955 e = DummyModule('e')
1956 f = DummyModule('f')
1957 t4 = Task(d, Task(f))
1958 s = Sequence(e, t4)
1959 p12 = Path(a+b+s+c,t1)
1960 self.assertEqual(p12.dumpPython(),"cms.Path(process.a+process.b+cms.Sequence(process.e, cms.Task(process.d, process.f))+process.c, cms.Task(process.a))\n")
1961 ct1 = ConditionalTask(a)
1962 ct2 = ConditionalTask(c, b)
1963 ct3 = ConditionalTask()
1964 p13 = Path((a+b)*c, ct1)
1965 self.assertEqual(p13.dumpPython(),"cms.Path(process.a+process.b+process.c, cms.ConditionalTask(process.a))\n")
1966 p14 = Path((a+b)*c, ct2, ct1)
1967 self.assertEqual(p14.dumpPython(),"cms.Path(process.a+process.b+process.c, cms.ConditionalTask(process.a), cms.ConditionalTask(process.b, process.c))\n")
1968 p15 = Path(ct1, ct2, ct3)
1969 self.assertEqual(p15.dumpPython(),"cms.Path(cms.ConditionalTask(), cms.ConditionalTask(process.a), cms.ConditionalTask(process.b, process.c))\n")
1970 ct4 = ConditionalTask(d, Task(f))
1971 s = Sequence(e, ct4)
1972 p16 = Path(a+b+s+c,ct1)
1973 self.assertEqual(p16.dumpPython(),"cms.Path(process.a+process.b+cms.Sequence(process.e, cms.ConditionalTask(process.d, process.f))+process.c, cms.ConditionalTask(process.a))\n")
1974
1975 n = 260
1976 mods = []
1977 labels = []
1978 for i in range(0, n):
1979 l = "a{}".format(i)
1980 labels.append("process."+l)
1981 mods.append(DummyModule(l))
1982 labels.sort()
1983 task = Task(*mods)
1984 self.assertEqual(task.dumpPython(), "cms.Task(*[" + ", ".join(labels) + "])\n")
1985 conditionalTask = ConditionalTask(*mods)
1986 self.assertEqual(conditionalTask.dumpPython(), "cms.ConditionalTask(*[" + ", ".join(labels) + "])\n")
1987
1988 l = list()
1989 namesVisitor = DecoratedNodeNameVisitor(l)
1990 p.visit(namesVisitor)
1991 self.assertEqual(l, ['a', 'b'])
1992 l[:] = []
1993 p5.visit(namesVisitor)
1994 self.assertEqual(l, ['a', '-b'])
1995 l[:] = []
1996 p5a.visit(namesVisitor)
1997 self.assertEqual(l, ['a', '|b'])
1998 l[:] = []
1999 p5b.visit(namesVisitor)
2000 self.assertEqual(l, ['a', '+b'])
2001 l[:] = []
2002 p5c.visit(namesVisitor)
2003 self.assertEqual(l, ['a', '+b'])
2004 l[:] = []
2005 p7.visit(namesVisitor)
2006 self.assertEqual(l, ['a', '!b'])
2007 l[:] = []
2008 p10.visit(namesVisitor)
2009 self.assertEqual(l, ['a', 'b', 'c'])
2010 l[:] = []
2011 p12.visit(namesVisitor)
2012 self.assertEqual(l, ['a', 'b', 'e', 'c'])
2013 l[:] = []
2014 p16.visit(namesVisitor)
2015 self.assertEqual(l, ['a', 'b', 'e', 'c'])
2016 l[:] = []
2017 moduleVisitor = ModuleNodeVisitor(l)
2018 p8.visit(moduleVisitor)
2019 names = [m.label_() for m in l]
2020 self.assertEqual(names, ['a', 'b', 'c'])
2021 tph = TaskPlaceholder('a')
2022 self.assertEqual(tph.dumpPython(), 'cms.TaskPlaceholder("process.a")\n')
2023 sph = SequencePlaceholder('a')
2024 self.assertEqual(sph.dumpPython(), 'cms.SequencePlaceholder("process.a")\n')
2025 ctph = ConditionalTaskPlaceholder('a')
2026 self.assertEqual(ctph.dumpPython(), 'cms.ConditionalTaskPlaceholder("process.a")\n')
2027
2028 def testDumpConfig(self):
2029 a = DummyModule("a")
2030 b = DummyModule('b')
2031 p = Path((a*b))
2032
2033 self.assertEqual(p.dumpConfig(None),"{a&b}\n")
2034 p2 = Path((b+a))
2035
2036 self.assertEqual(p2.dumpConfig(None),"{b&a}\n")
2037 c = DummyModule('c')
2038 p3 = Path(c*(a+b))
2039
2040 self.assertEqual(p3.dumpConfig(None),"{c&a&b}\n")
2041 p4 = Path(c*a+b)
2042
2043 self.assertEqual(p4.dumpConfig(None),"{c&a&b}\n")
2044 p5 = Path(a+ignore(b))
2045
2046 self.assertEqual(p5.dumpConfig(None),"{a&-b}\n")
2047 p6 = Path(c+a*b)
2048
2049 self.assertEqual(p6.dumpConfig(None),"{c&a&b}\n")
2050 p7 = Path(a+~b)
2051 self.assertEqual(p7.dumpConfig(None),"{a&!b}\n")
2052 p8 = Path((a+b)*c)
2053 self.assertEqual(p8.dumpConfig(None),"{a&b&c}\n")
2054 def testVisitor(self):
2055 class TestVisitor(object):
2056 def __init__(self, enters, leaves):
2057 self._enters = enters
2058 self._leaves = leaves
2059 def enter(self,visitee):
2060
2061 if self._enters[0] != visitee:
2062 raise RuntimeError("wrong node ("+str(visitee)+") on 'enter'")
2063 else:
2064 self._enters = self._enters[1:]
2065 def leave(self,visitee):
2066 if self._leaves[0] != visitee:
2067 raise RuntimeError("wrong node ("+str(visitee)+") on 'leave'\n expected ("+str(self._leaves[0])+")")
2068 else:
2069 self._leaves = self._leaves[1:]
2070 a = DummyModule("a")
2071 b = DummyModule('b')
2072 multAB = a*b
2073 p = Path(multAB)
2074 t = TestVisitor(enters=[a,b],
2075 leaves=[a,b])
2076 p.visit(t)
2077
2078 plusAB = a+b
2079 p = Path(plusAB)
2080 t = TestVisitor(enters=[a,b],
2081 leaves=[a,b])
2082 p.visit(t)
2083
2084 c=DummyModule("c")
2085 d=DummyModule("d")
2086 e=DummyModule("e")
2087 f=DummyModule("f")
2088 g=DummyModule("g")
2089 ct1 = ConditionalTask(d)
2090 ct2 = ConditionalTask(e, ct1)
2091 ct3 = ConditionalTask(f, g, ct2)
2092 s=Sequence(plusAB, ct3, ct2)
2093 multSC = s*c
2094 p=Path(multSC, ct1, ct2)
2095 l = []
2096 v = ModuleNodeVisitor(l)
2097 p.visit(v)
2098 expected = [a,b,f,g,e,d,e,d,c,d,e,d]
2099 self.assertEqual(expected,l)
2100
2101
2102 t1 = Task(d)
2103 t2 = Task(e, t1)
2104 t3 = Task(f, g, t2)
2105 s=Sequence(plusAB, t3, t2)
2106 multSC = s*c
2107 p=Path(multSC, t1, t2)
2108
2109 l = []
2110 v = ModuleNodeVisitor(l)
2111 p.visit(v)
2112 expected = [a,b,f,g,e,d,e,d,c,d,e,d]
2113 self.assertEqual(expected,l)
2114
2115 l[:] = []
2116 v = ModuleNodeOnTaskVisitor(l)
2117 p.visit(v)
2118 expected = [f,g,e,d,e,d,d,e,d]
2119 self.assertEqual(expected,l)
2120
2121 l[:] = []
2122 v = ModuleNodeNotOnTaskVisitor(l)
2123 p.visit(v)
2124 expected = [a,b,c]
2125 self.assertEqual(expected,l)
2126
2127
2128 t=TestVisitor(enters=[s,a,b,t3,f,g,t2,e,t1,d,t2,e,t1,d,c,t1,d,t2,e,t1,d],
2129 leaves=[a,b,f,g,e,d,t1,t2,t3,e,d,t1,t2,s,c,d,t1,e,d,t1,t2])
2130 p.visit(t)
2131
2132 notA= ~a
2133 p=Path(notA)
2134 t=TestVisitor(enters=[notA,a],leaves=[a,notA])
2135 p.visit(t)
2136 def testResolve(self):
2137 m1 = DummyModule("m1")
2138 m2 = DummyModule("m2")
2139 s1 = Sequence(m1)
2140 s2 = SequencePlaceholder("s3")
2141 s3 = Sequence(m2)
2142 p = Path(s1*s2)
2143 l = list()
2144
2145
2146 namesVisitor = DecoratedNodeNameVisitor(l)
2147 p.visit(namesVisitor)
2148 self.assertEqual(l, ['m1'])
2149 p.resolve(dict(s1=s1, s2=s2, s3=s3))
2150 l[:] = []
2151 p.visit(namesVisitor)
2152 self.assertEqual(l, ['m1', 'm2'])
2153 l[:]=[]
2154 s1 = Sequence(m1)
2155 s2 = SequencePlaceholder("s3")
2156 s3 = Sequence(m2)
2157 s4 = SequencePlaceholder("s2")
2158 p=Path(s1+s4)
2159 p.resolve(dict(s1=s1, s2=s2, s3=s3, s4=s4))
2160 p.visit(namesVisitor)
2161 self.assertEqual(l, ['m1', 'm2'])
2162 l[:]=[]
2163 m3 = DummyModule("m3")
2164 m4 = DummyModule("m4")
2165 s1 = Sequence(~m1)
2166 s2 = SequencePlaceholder("s3")
2167 s3 = Sequence(ignore(m2))
2168 s4 = Sequence(wait(m3) + ignore(wait(m4)))
2169 d = dict(s1=s1, s2=s2, s3=s3, s4=s4)
2170 p = Path(s1*s2*s4)
2171 p.resolve(dict(s1=s1, s2=s2, s3=s3, s4=s4))
2172 p.visit(namesVisitor)
2173 self.assertEqual(l, ['!m1', '-m2', '|m3', '+m4'])
2174 def testReplace(self):
2175 m1 = DummyModule("m1")
2176 m2 = DummyModule("m2")
2177 m3 = DummyModule("m3")
2178 m4 = DummyModule("m4")
2179 m5 = DummyModule("m5")
2180
2181 s1 = Sequence(m1*~m2*m1*m2*ignore(m2))
2182 s2 = Sequence(m1*m2)
2183 l = []
2184 namesVisitor = DecoratedNodeNameVisitor(l)
2185 s1.visit(namesVisitor)
2186 self.assertEqual(l,['m1', '!m2', 'm1', 'm2', '-m2'])
2187
2188 s3 = Sequence(~m1*s2)
2189 s3.replace(~m1, m2)
2190 l[:] = []
2191 s3.visit(namesVisitor)
2192 self.assertEqual(l, ['m2', 'm1', 'm2'])
2193 s3.replace(m2, ~m1)
2194 l[:] = []
2195 s3.visit(namesVisitor)
2196 self.assertEqual(l, ['!m1', 'm1', '!m1'])
2197
2198 s3 = Sequence(ignore(m1)*s2)
2199 s3.replace(ignore(m1), m2)
2200 l[:] = []
2201 s3.visit(namesVisitor)
2202 self.assertEqual(l, ['m2', 'm1', 'm2'])
2203 s3.replace(m2, ignore(m1))
2204 l[:] = []
2205 s3.visit(namesVisitor)
2206 self.assertEqual(l, ['-m1', 'm1', '-m1'])
2207
2208 ph = SequencePlaceholder('x')
2209 s4 = Sequence(Sequence(ph))
2210 s4.replace(ph,m2)
2211 self.assertEqual(s4.dumpPython(), "cms.Sequence(process.m2)\n")
2212
2213 s1.replace(m2,m3)
2214 l[:] = []
2215 s1.visit(namesVisitor)
2216 self.assertEqual(l,['m1', '!m3', 'm1', 'm3', '-m3'])
2217 s2 = Sequence(m1*m2)
2218 s3 = Sequence(~m1*s2)
2219 l[:] = []
2220 s3.visit(namesVisitor)
2221 self.assertEqual(l,['!m1', 'm1', 'm2'])
2222 l[:] = []
2223 s3.replace(s2,m1)
2224 s3.visit(namesVisitor)
2225 self.assertEqual(l,['!m1', 'm1'])
2226
2227 s1 = Sequence(m1+m2)
2228 s2 = Sequence(m3+m4)
2229 s3 = Sequence(s1+s2)
2230 s3.replace(m3,m5)
2231 l[:] = []
2232 s3.visit(namesVisitor)
2233 self.assertEqual(l,['m1','m2','m5','m4'])
2234
2235 m6 = DummyModule("m6")
2236 m7 = DummyModule("m7")
2237 m8 = DummyModule("m8")
2238 m9 = DummyModule("m9")
2239
2240
2241 t6 = Task(m6)
2242 t7 = Task(m7)
2243 t89 = Task(m8, m9)
2244
2245 s1 = Sequence(m1+m2, t6)
2246 s2 = Sequence(m3+m4, t7)
2247 s3 = Sequence(s1+s2, t89)
2248 s3.replace(m3,m5)
2249 l[:] = []
2250 s3.visit(namesVisitor)
2251 self.assertEqual(l,['m1','m2','m5','m4'])
2252
2253 s3.replace(m8,m1)
2254 self.assertTrue(s3.dumpPython() == "cms.Sequence(cms.Sequence(process.m1+process.m2, cms.Task(process.m6))+process.m5+process.m4, cms.Task(process.m1, process.m9), cms.Task(process.m7))\n")
2255
2256 s3.replace(m1,m7)
2257 self.assertTrue(s3.dumpPython() == "cms.Sequence(process.m7+process.m2+process.m5+process.m4, cms.Task(process.m6), cms.Task(process.m7), cms.Task(process.m7, process.m9))\n")
2258 result = s3.replace(t7, t89)
2259 self.assertTrue(s3.dumpPython() == "cms.Sequence(process.m7+process.m2+process.m5+process.m4, cms.Task(process.m6), cms.Task(process.m7, process.m9), cms.Task(process.m8, process.m9))\n")
2260 self.assertTrue(result)
2261 result = s3.replace(t7, t89)
2262 self.assertFalse(result)
2263
2264 t1 = Task()
2265 t1.replace(m1,m2)
2266 self.assertTrue(t1.dumpPython() == "cms.Task()\n")
2267
2268 t1 = Task(m1)
2269 t1.replace(m1,m2)
2270 self.assertTrue(t1.dumpPython() == "cms.Task(process.m2)\n")
2271
2272 t1 = Task(m1,m2, m2)
2273 t1.replace(m2,m3)
2274 self.assertTrue(t1.dumpPython() == "cms.Task(process.m1, process.m3)\n")
2275
2276 t1 = Task(m1,m2)
2277 t2 = Task(m1,m3,t1)
2278 t2.replace(m1,m4)
2279 self.assertTrue(t2.dumpPython() == "cms.Task(process.m2, process.m3, process.m4)\n")
2280
2281 t1 = Task(m2)
2282 t2 = Task(m1,m3,t1)
2283 t2.replace(m1,m4)
2284 self.assertTrue(t2.dumpPython() == "cms.Task(process.m2, process.m3, process.m4)\n")
2285
2286 t1 = Task(m2)
2287 t2 = Task(m1,m3,t1)
2288 t2.replace(t1,m4)
2289 self.assertTrue(t2.dumpPython() == "cms.Task(process.m1, process.m3, process.m4)\n")
2290
2291 t1 = Task(m2)
2292 t2 = Task(m1,m3,t1)
2293 t3 = Task(m5)
2294 t2.replace(m2,t3)
2295 self.assertTrue(t2.dumpPython() == "cms.Task(process.m1, process.m3, process.m5)\n")
2296
2297
2298 ct6 = ConditionalTask(m6)
2299 ct7 = ConditionalTask(m7)
2300 ct89 = ConditionalTask(m8, m9)
2301
2302 cs1 = Sequence(m1+m2, ct6)
2303 cs2 = Sequence(m3+m4, ct7)
2304 cs3 = Sequence(cs1+cs2, ct89)
2305 cs3.replace(m3,m5)
2306 l[:] = []
2307 cs3.visit(namesVisitor)
2308 self.assertEqual(l,['m1','m2','m5','m4'])
2309
2310 cs3.replace(m8,m1)
2311 self.assertEqual(cs3.dumpPython(), "cms.Sequence(cms.Sequence(process.m1+process.m2, cms.ConditionalTask(process.m6))+process.m5+process.m4, cms.ConditionalTask(process.m1, process.m9), cms.ConditionalTask(process.m7))\n")
2312
2313 cs3.replace(m1,m7)
2314 self.assertEqual(cs3.dumpPython(), "cms.Sequence(process.m7+process.m2+process.m5+process.m4, cms.ConditionalTask(process.m6), cms.ConditionalTask(process.m7), cms.ConditionalTask(process.m7, process.m9))\n")
2315 result = cs3.replace(ct7, ct89)
2316 self.assertEqual(cs3.dumpPython(), "cms.Sequence(process.m7+process.m2+process.m5+process.m4, cms.ConditionalTask(process.m6), cms.ConditionalTask(process.m7, process.m9), cms.ConditionalTask(process.m8, process.m9))\n")
2317 self.assertTrue(result)
2318 result = cs3.replace(ct7, ct89)
2319 self.assertFalse(result)
2320
2321 ct1 = ConditionalTask()
2322 ct1.replace(m1,m2)
2323 self.assertEqual(ct1.dumpPython(), "cms.ConditionalTask()\n")
2324
2325 ct1 = ConditionalTask(m1)
2326 ct1.replace(m1,m2)
2327 self.assertEqual(ct1.dumpPython(), "cms.ConditionalTask(process.m2)\n")
2328
2329 ct1 = ConditionalTask(m1,m2, m2)
2330 ct1.replace(m2,m3)
2331 self.assertEqual(ct1.dumpPython(), "cms.ConditionalTask(process.m1, process.m3)\n")
2332
2333 ct1 = ConditionalTask(m1,m2)
2334 ct2 = ConditionalTask(m1,m3,ct1)
2335 ct2.replace(m1,m4)
2336 self.assertEqual(ct2.dumpPython(), "cms.ConditionalTask(process.m2, process.m3, process.m4)\n")
2337
2338 ct1 = ConditionalTask(m2)
2339 ct2 = ConditionalTask(m1,m3,ct1)
2340 ct2.replace(m1,m4)
2341 self.assertEqual(ct2.dumpPython(), "cms.ConditionalTask(process.m2, process.m3, process.m4)\n")
2342
2343 ct1 = ConditionalTask(m2)
2344 ct2 = ConditionalTask(m1,m3,ct1)
2345 ct2.replace(ct1,m4)
2346 self.assertEqual(ct2.dumpPython(), "cms.ConditionalTask(process.m1, process.m3, process.m4)\n")
2347
2348 ct1 = ConditionalTask(m2)
2349 ct2 = ConditionalTask(m1,m3,ct1)
2350 ct3 = ConditionalTask(m5)
2351 ct2.replace(m2,ct3)
2352 self.assertEqual(ct2.dumpPython(), "cms.ConditionalTask(process.m1, process.m3, process.m5)\n")
2353
2354
2355 fp = FinalPath()
2356 fp.replace(m1,m2)
2357 self.assertEqual(fp.dumpPython(), "cms.FinalPath()\n")
2358 fp = FinalPath(m1)
2359 fp.replace(m1,m2)
2360 self.assertEqual(fp.dumpPython(), "cms.FinalPath(process.m2)\n")
2361
2362 def testReplaceIfHeldDirectly(self):
2363 m1 = DummyModule("m1")
2364 m2 = DummyModule("m2")
2365 m3 = DummyModule("m3")
2366 m4 = DummyModule("m4")
2367 m5 = DummyModule("m5")
2368
2369 s1 = Sequence(m1*~m2*m1*m2*ignore(m2))
2370 s1._replaceIfHeldDirectly(m2,m3)
2371 self.assertEqual(s1.dumpPython()[:-1],
2372 "cms.Sequence(process.m1+~process.m3+process.m1+process.m3+cms.ignore(process.m3))")
2373
2374 s2 = Sequence(m1*m2)
2375 l = []
2376 s3 = Sequence(~m1*s2)
2377 s3._replaceIfHeldDirectly(~m1, m2)
2378 self.assertEqual(s3.dumpPython()[:-1],
2379 "cms.Sequence(process.m2+(process.m1+process.m2))")
2380
2381 m6 = DummyModule("m6")
2382 m7 = DummyModule("m7")
2383 m8 = DummyModule("m8")
2384 m9 = DummyModule("m9")
2385 t6 = Task(m6)
2386 t7 = Task(m7)
2387 t89 = Task(m8, m9)
2388
2389 s1 = Sequence(m1+m2, t6)
2390 s2 = Sequence(m3+m4, t7)
2391 s3 = Sequence(s1+s2, t89)
2392 s3._replaceIfHeldDirectly(m3,m5)
2393 self.assertEqual(s3.dumpPython()[:-1], "cms.Sequence(cms.Sequence(process.m1+process.m2, cms.Task(process.m6))+cms.Sequence(process.m3+process.m4, cms.Task(process.m7)), cms.Task(process.m8, process.m9))")
2394 s2._replaceIfHeldDirectly(m3,m5)
2395 self.assertEqual(s2.dumpPython()[:-1],"cms.Sequence(process.m5+process.m4, cms.Task(process.m7))")
2396 self.assertEqual(s3.dumpPython()[:-1], "cms.Sequence(cms.Sequence(process.m1+process.m2, cms.Task(process.m6))+cms.Sequence(process.m5+process.m4, cms.Task(process.m7)), cms.Task(process.m8, process.m9))")
2397
2398 s1 = Sequence(t6)
2399 s1._replaceIfHeldDirectly(t6,t7)
2400 self.assertEqual(s1.dumpPython()[:-1],"cms.Sequence(cms.Task(process.m7))")
2401
2402
2403 ct6 = ConditionalTask(m6)
2404 ct7 = ConditionalTask(m7)
2405 ct89 = ConditionalTask(m8, m9)
2406
2407 s1 = Sequence(m1+m2, ct6)
2408 s2 = Sequence(m3+m4, ct7)
2409 s3 = Sequence(s1+s2, ct89)
2410 s3._replaceIfHeldDirectly(m3,m5)
2411 self.assertEqual(s3.dumpPython()[:-1], "cms.Sequence(cms.Sequence(process.m1+process.m2, cms.ConditionalTask(process.m6))+cms.Sequence(process.m3+process.m4, cms.ConditionalTask(process.m7)), cms.ConditionalTask(process.m8, process.m9))")
2412 s2._replaceIfHeldDirectly(m3,m5)
2413 self.assertEqual(s2.dumpPython()[:-1],"cms.Sequence(process.m5+process.m4, cms.ConditionalTask(process.m7))")
2414 self.assertEqual(s3.dumpPython()[:-1], "cms.Sequence(cms.Sequence(process.m1+process.m2, cms.ConditionalTask(process.m6))+cms.Sequence(process.m5+process.m4, cms.ConditionalTask(process.m7)), cms.ConditionalTask(process.m8, process.m9))")
2415
2416 s1 = Sequence(ct6)
2417 s1._replaceIfHeldDirectly(ct6,ct7)
2418 self.assertEqual(s1.dumpPython()[:-1],"cms.Sequence(cms.ConditionalTask(process.m7))")
2419 def testIndex(self):
2420 m1 = DummyModule("a")
2421 m2 = DummyModule("b")
2422 m3 = DummyModule("c")
2423
2424 s = Sequence(m1+m2+m3)
2425 self.assertEqual(s.index(m1),0)
2426 self.assertEqual(s.index(m2),1)
2427 self.assertEqual(s.index(m3),2)
2428
2429 def testInsert(self):
2430 m1 = DummyModule("a")
2431 m2 = DummyModule("b")
2432 m3 = DummyModule("c")
2433 s = Sequence(m1+m3)
2434 s.insert(1,m2)
2435 self.assertEqual(s.index(m1),0)
2436 self.assertEqual(s.index(m2),1)
2437 self.assertEqual(s.index(m3),2)
2438
2439 s = Sequence()
2440 s.insert(0, m1)
2441 self.assertEqual(s.index(m1),0)
2442
2443 p = Path()
2444 p.insert(0, m1)
2445 self.assertEqual(s.index(m1),0)
2446
2447 def testExpandAndClone(self):
2448 m1 = DummyModule("m1")
2449 m2 = DummyModule("m2")
2450 m3 = DummyModule("m3")
2451 m4 = DummyModule("m4")
2452 m5 = DummyModule("m5")
2453
2454 s1 = Sequence(m1*~m2*m1*m2*ignore(m2))
2455 s2 = Sequence(m1*m2)
2456 s3 = Sequence(~m1*s2)
2457
2458 p = Path(s1+s3)
2459 p2 = p.expandAndClone()
2460 l = []
2461 namesVisitor = DecoratedNodeNameVisitor(l)
2462 p2.visit(namesVisitor)
2463 self.assertEqual(l, ['m1', '!m2', 'm1', 'm2', '-m2', '!m1', 'm1', 'm2'])
2464
2465
2466 m6 = DummyModule("m6")
2467 m7 = DummyModule("m7")
2468 m8 = DummyModule("m8")
2469 m9 = DummyModule("m9")
2470 p = Path(s1+s3, Task(m6))
2471 p2 = p.expandAndClone()
2472 l[:] = []
2473 p2.visit(namesVisitor)
2474 self.assertEqual(l, ['m1', '!m2', 'm1', 'm2', '-m2', '!m1', 'm1', 'm2'])
2475 self.assertEqual(p2.dumpPython(), "cms.Path(process.m1+~process.m2+process.m1+process.m2+cms.ignore(process.m2)+~process.m1+process.m1+process.m2, cms.Task(process.m6))\n")
2476
2477 s2 = Sequence(m1*m2, Task(m9))
2478 s3 = Sequence(~m1*s2)
2479 t8 = Task(m8)
2480 t8.setLabel("t8")
2481 p = Path(s1+s3, Task(m6, Task(m7, t8)))
2482 p2 = p.expandAndClone()
2483 l[:] = []
2484 p2.visit(namesVisitor)
2485 self.assertEqual(l, ['m1', '!m2', 'm1', 'm2', '-m2', '!m1', 'm1', 'm2'])
2486 self.assertTrue(p2.dumpPython() == "cms.Path(process.m1+~process.m2+process.m1+process.m2+cms.ignore(process.m2)+~process.m1+process.m1+process.m2, cms.Task(process.m6, process.m7, process.m8, process.m9))\n")
2487
2488 t1 = Task(m1,m2,m3)
2489 s1 = Sequence(t1)
2490 s2 = s1.expandAndClone()
2491 l[:] = []
2492 s2.visit(namesVisitor)
2493 self.assertEqual(l, [])
2494 self.assertTrue(s2.dumpPython() == "cms.Sequence(cms.Task(process.m1, process.m2, process.m3))\n")
2495
2496 t1 = Task(m1,m2)
2497 t2 = Task(m1,m3,t1)
2498 t3 = t2.expandAndClone()
2499 self.assertTrue(t3.dumpPython() == "cms.Task(process.m1, process.m2, process.m3)\n")
2500 t4 = Task()
2501 t5 = t4.expandAndClone()
2502 self.assertTrue(t5.dumpPython() == "cms.Task()\n")
2503
2504 s1 = Sequence(m1*~m2*m1*m2*ignore(m2))
2505 s2 = Sequence(m1*m2)
2506 s3 = Sequence(~m1*s2)
2507 p = Path(s1+s3, ConditionalTask(m6))
2508 p2 = p.expandAndClone()
2509 l[:] = []
2510 p2.visit(namesVisitor)
2511 self.assertEqual(l, ['m1', '!m2', 'm1', 'm2', '-m2', '!m1', 'm1', 'm2'])
2512 self.assertEqual(p2.dumpPython(), "cms.Path(process.m1+~process.m2+process.m1+process.m2+cms.ignore(process.m2)+~process.m1+process.m1+process.m2, cms.ConditionalTask(process.m6))\n")
2513
2514 s2 = Sequence(m1*m2, ConditionalTask(m9))
2515 s3 = Sequence(~m1*s2)
2516 ct8 = ConditionalTask(m8)
2517 ct8.setLabel("ct8")
2518 p = Path(s1+s3, ConditionalTask(m6, ConditionalTask(m7, ct8)))
2519 p2 = p.expandAndClone()
2520 l[:] = []
2521 p2.visit(namesVisitor)
2522 self.assertEqual(l, ['m1', '!m2', 'm1', 'm2', '-m2', '!m1', 'm1', 'm2'])
2523 self.assertEqual(p2.dumpPython(), "cms.Path(process.m1+~process.m2+process.m1+process.m2+cms.ignore(process.m2)+~process.m1+process.m1+process.m2, cms.ConditionalTask(process.m6, process.m7, process.m8, process.m9))\n")
2524
2525 t1 = ConditionalTask(m1,m2,m3)
2526 s1 = Sequence(t1)
2527 s2 = s1.expandAndClone()
2528 l[:] = []
2529 s2.visit(namesVisitor)
2530 self.assertEqual(l, [])
2531 self.assertEqual(s2.dumpPython(), "cms.Sequence(cms.ConditionalTask(process.m1, process.m2, process.m3))\n")
2532
2533 t1 = ConditionalTask(m1,m2)
2534 t2 = ConditionalTask(m1,m3,t1)
2535 t3 = t2.expandAndClone()
2536 self.assertEqual(t3.dumpPython(), "cms.ConditionalTask(process.m1, process.m2, process.m3)\n")
2537 t4 = ConditionalTask()
2538 t5 = t4.expandAndClone()
2539 self.assertTrue(t5.dumpPython() == "cms.ConditionalTask()\n")
2540
2541 def testAdd(self):
2542 m1 = DummyModule("m1")
2543 m2 = DummyModule("m2")
2544 m3 = DummyModule("m3")
2545 m4 = DummyModule("m4")
2546 s1 = Sequence(m1)
2547 s3 = Sequence(m3+ignore(m4))
2548 p = Path(s1)
2549 p += ~m2
2550 p *= s3
2551
2552 l = []
2553 namesVisitor = DecoratedNodeNameVisitor(l)
2554 p.visit(namesVisitor)
2555 self.assertEqual(l, ['m1', '!m2', 'm3', '-m4'])
2556
2557 s4 = Sequence()
2558 s4 +=m1
2559 l[:]=[]; s1.visit(namesVisitor); self.assertEqual(l,['m1'])
2560 self.assertEqual(s4.dumpPython(),"cms.Sequence(process.m1)\n")
2561 s4 = Sequence()
2562 s4 *=m1
2563 l[:]=[]; s1.visit(namesVisitor); self.assertEqual(l,['m1'])
2564 self.assertEqual(s4.dumpPython(),"cms.Sequence(process.m1)\n")
2565
2566
2567 def testRemove(self):
2568 m1 = DummyModule("m1")
2569 m2 = DummyModule("m2")
2570 m3 = DummyModule("m3")
2571 m4 = DummyModule("m4")
2572 s1 = Sequence(m1*m2+~m3)
2573 s2 = Sequence(m1*s1)
2574 l = []
2575 namesVisitor = DecoratedNodeNameVisitor(l)
2576 d = {'m1':m1 ,'m2':m2, 'm3':m3,'s1':s1, 's2':s2}
2577 l[:] = []; s1.visit(namesVisitor); self.assertEqual(l,['m1', 'm2', '!m3'])
2578 l[:] = []; s2.visit(namesVisitor); self.assertEqual(l,['m1', 'm1', 'm2', '!m3'])
2579 s1.remove(m2)
2580 l[:] = []; s1.visit(namesVisitor); self.assertEqual(l,['m1', '!m3'])
2581 l[:] = []; s2.visit(namesVisitor); self.assertEqual(l,['m1', 'm1', '!m3'])
2582 s2.remove(m3)
2583 l[:] = []; s1.visit(namesVisitor); self.assertEqual(l,['m1', '!m3'])
2584 l[:] = []; s2.visit(namesVisitor); self.assertEqual(l,['m1', 'm1'])
2585 s1 = Sequence( m1 + m2 + m1 + m2 )
2586 l[:] = []; s1.visit(namesVisitor); self.assertEqual(l,['m1', 'm2', 'm1', 'm2'])
2587 s1.remove(m2)
2588 l[:] = []; s1.visit(namesVisitor); self.assertEqual(l,['m1', 'm1', 'm2'])
2589 s1 = Sequence( m1 + m3 )
2590 s2 = Sequence( m2 + ignore(m3) + s1 + m3 )
2591 l[:] = []; s2.visit(namesVisitor); self.assertEqual(l,['m2', '-m3', 'm1', 'm3', 'm3'])
2592 s2.remove(s1)
2593 l[:] = []; s2.visit(namesVisitor); self.assertEqual(l,['m2', '-m3', 'm3'])
2594 s2.remove(m3)
2595 l[:] = []; s2.visit(namesVisitor); self.assertEqual(l,['m2','m3'])
2596 s1 = Sequence(m1*m2*m3)
2597 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2+process.m3)\n")
2598 s1.remove(m2)
2599 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m3)\n")
2600 s1 = Sequence(m1+m2+m3)
2601 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2+process.m3)\n")
2602 s1.remove(m2)
2603 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m3)\n")
2604 s1 = Sequence(m1*m2+m3)
2605 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2+process.m3)\n")
2606 s1.remove(m2)
2607 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m3)\n")
2608 s1 = Sequence(m1+m2*m3)
2609 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2+process.m3)\n")
2610 s1.remove(m2)
2611 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m3)\n")
2612 s1.remove(m1)
2613 s1.remove(m3)
2614 l[:]=[]; s1.visit(namesVisitor); self.assertEqual(l,[])
2615 self.assertEqual(s1.dumpPython(), "cms.Sequence()\n")
2616 s3 = Sequence(m1)
2617 s3.remove(m1)
2618 l[:]=[]; s3.visit(namesVisitor); self.assertEqual(l,[])
2619 self.assertEqual(s3.dumpPython(), "cms.Sequence()\n")
2620 s3 = Sequence(m1)
2621 s4 = Sequence(s3)
2622 s4.remove(m1)
2623 l[:]=[]; s4.visit(namesVisitor); self.assertEqual(l,[])
2624 self.assertEqual(s4.dumpPython(), "cms.Sequence()\n")
2625
2626 s1 = Sequence(m1+m2, Task(m3), Task(m4))
2627 s1.remove(m4)
2628 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2, cms.Task(process.m3))\n")
2629 s1 = Sequence(m1+m2+Sequence(Task(m3,m4), Task(m3), Task(m4)))
2630 s1.remove(m4)
2631 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2, cms.Task(process.m3), cms.Task(process.m4))\n")
2632 t1 = Task(m1)
2633 t1.setLabel("t1")
2634 t2 = Task(m2,t1)
2635 t2.setLabel("t2")
2636 t3 = Task(t1,t2,m1)
2637 t3.remove(m1)
2638 self.assertTrue(t3.dumpPython() == "cms.Task(process.m1, process.t2)\n")
2639 t3.remove(m1)
2640 self.assertTrue(t3.dumpPython() == "cms.Task(process.m1, process.m2)\n")
2641 t3.remove(m1)
2642 self.assertTrue(t3.dumpPython() == "cms.Task(process.m2)\n")
2643 t3.remove(m2)
2644 self.assertTrue(t3.dumpPython() == "cms.Task()\n")
2645
2646 s1 = Sequence(m1+m2, ConditionalTask(m3), ConditionalTask(m4))
2647 s1.remove(m4)
2648 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2, cms.ConditionalTask(process.m3))\n")
2649 s1 = Sequence(m1+m2+Sequence(ConditionalTask(m3,m4), ConditionalTask(m3), ConditionalTask(m4)))
2650 s1.remove(m4)
2651 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2, cms.ConditionalTask(process.m3), cms.ConditionalTask(process.m4))\n")
2652 t1 = ConditionalTask(m1)
2653 t1.setLabel("t1")
2654 t2 = ConditionalTask(m2,t1)
2655 t2.setLabel("t2")
2656 t3 = ConditionalTask(t1,t2,m1)
2657 t3.remove(m1)
2658 self.assertEqual(t3.dumpPython(), "cms.ConditionalTask(process.m1, process.t2)\n")
2659 t3.remove(m1)
2660 self.assertEqual(t3.dumpPython(), "cms.ConditionalTask(process.m1, process.m2)\n")
2661 t3.remove(m1)
2662 self.assertEqual(t3.dumpPython(), "cms.ConditionalTask(process.m2)\n")
2663 t3.remove(m2)
2664 self.assertEqual(t3.dumpPython(), "cms.ConditionalTask()\n")
2665
2666 fp = FinalPath(m1+m2)
2667 fp.remove(m1)
2668 self.assertEqual(fp.dumpPython(), "cms.FinalPath(process.m2)\n")
2669 fp = FinalPath(m1)
2670 fp.remove(m1)
2671 self.assertEqual(fp.dumpPython(), "cms.FinalPath()\n")
2672
2673 def testCopyAndExclude(self):
2674 a = DummyModule("a")
2675 b = DummyModule("b")
2676 c = DummyModule("c")
2677 d = DummyModule("d")
2678 s = Sequence(a+b+c)
2679 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+process.b+process.c)\n")
2680 s = Sequence(a+b+c+d)
2681 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2682 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2683 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+process.b+process.d)\n")
2684 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+process.b+process.c)\n")
2685 s=Sequence(a*b+c+d)
2686 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2687 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2688 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+process.b+process.d)\n")
2689 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+process.b+process.c)\n")
2690 s = Sequence(a+b*c+d)
2691 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2692 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2693 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+process.b+process.d)\n")
2694 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+process.b+process.c)\n")
2695 s2 = Sequence(a+b)
2696 s = Sequence(c+s2+d)
2697 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.c+process.b+process.d)\n")
2698 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.c+process.a+process.d)\n")
2699 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence((process.a+process.b)+process.d)\n")
2700 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.c+(process.a+process.b))\n")
2701 self.assertEqual(s.copyAndExclude([a,b]).dumpPython(),"cms.Sequence(process.c+process.d)\n")
2702 s3 = s.copyAndExclude([c])
2703 s2.remove(a)
2704 self.assertEqual(s3.dumpPython(),"cms.Sequence((process.b)+process.d)\n")
2705 s4 = s.copyAndExclude([a,b])
2706 seqs = []
2707 sequenceVisitor = SequenceVisitor(seqs)
2708 s.visit(sequenceVisitor)
2709 self.assertEqual(len(seqs),1)
2710 seqs[:] = []
2711 s4.visit(sequenceVisitor)
2712 self.assertEqual(len(seqs),0)
2713 self.assertEqual(s4.dumpPython(),"cms.Sequence(process.c+process.d)\n")
2714 holder = SequencePlaceholder("x")
2715 s3 = Sequence(b+d,Task(a))
2716 s2 = Sequence(a+b+holder+s3)
2717 s = Sequence(c+s2+d)
2718 seqs[:] = []
2719 s.visit(sequenceVisitor)
2720 self.assertTrue(seqs == [s2,s3])
2721 s2 = Sequence(a+b+holder)
2722 s = Sequence(c+s2+d)
2723 self.assertEqual(s.copyAndExclude([holder]).dumpPython(),"cms.Sequence(process.c+process.a+process.b+process.d)\n")
2724 s2 = Sequence(a+b+c)
2725 s = Sequence(s2+d)
2726 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2727 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2728 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+process.b+process.d)\n")
2729 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence((process.a+process.b+process.c))\n")
2730 self.assertEqual(s.copyAndExclude([s2]).dumpPython(),"cms.Sequence(process.d)\n")
2731 s2 = Sequence(a+b+c)
2732 s = Sequence(s2*d)
2733 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2734 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2735 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+process.b+process.d)\n")
2736 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence((process.a+process.b+process.c))\n")
2737 self.assertEqual(s.copyAndExclude([a,b,c]).dumpPython(),"cms.Sequence(process.d)\n")
2738 s = Sequence(ignore(a)+b+c+d)
2739 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2740 self.assertEqual(s.copyAndExclude([ignore(a)]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2741 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(cms.ignore(process.a)+process.c+process.d)\n")
2742 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(cms.ignore(process.a)+process.b+process.d)\n")
2743 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(cms.ignore(process.a)+process.b+process.c)\n")
2744 s = Sequence(a+ignore(b)+c+d)
2745 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(cms.ignore(process.b)+process.c+process.d)\n")
2746 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2747 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+cms.ignore(process.b)+process.d)\n")
2748 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+cms.ignore(process.b)+process.c)\n")
2749 s = Sequence(a+b+c+ignore(d))
2750 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+cms.ignore(process.d))\n")
2751 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+cms.ignore(process.d))\n")
2752 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+process.b+cms.ignore(process.d))\n")
2753 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+process.b+process.c)\n")
2754 s = Sequence(~a+b+c+d)
2755 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2756 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(~process.a+process.c+process.d)\n")
2757 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(~process.a+process.b+process.d)\n")
2758 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(~process.a+process.b+process.c)\n")
2759 s = Sequence(a+~b+c+d)
2760 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(~process.b+process.c+process.d)\n")
2761 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2762 self.assertEqual(s.copyAndExclude([~b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2763 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+~process.b+process.d)\n")
2764 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+~process.b+process.c)\n")
2765 s = Sequence(a+b+c+~d)
2766 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d)\n")
2767 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+~process.d)\n")
2768 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+process.b+~process.d)\n")
2769 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+process.b+process.c)\n")
2770 self.assertEqual(s.copyAndExclude([a,b,c,d]).dumpPython(),"cms.Sequence()\n")
2771
2772
2773 e = DummyModule("e")
2774 f = DummyModule("f")
2775 g = DummyModule("g")
2776 h = DummyModule("h")
2777 t1 = Task(h)
2778 s = Sequence(a+b+c+~d, Task(e,f,Task(g,t1)))
2779 self.assertEqual(s.copyAndExclude([a,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.Task(process.e, process.f, process.g))\n")
2780 self.assertEqual(s.copyAndExclude([a,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.Task(process.e, process.f, process.g))\n")
2781 self.assertEqual(s.copyAndExclude([a,e,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.Task(process.f, process.g))\n")
2782 self.assertEqual(s.copyAndExclude([a,e,f,g,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d)\n")
2783 self.assertEqual(s.copyAndExclude([a,b,c,d]).dumpPython(),"cms.Sequence(cms.Task(process.e, process.f, process.g, process.h))\n")
2784 self.assertEqual(s.copyAndExclude([t1]).dumpPython(),"cms.Sequence(process.a+process.b+process.c+~process.d, cms.Task(process.e, process.f, process.g))\n")
2785 taskList = []
2786 taskVisitor = TaskVisitor(taskList)
2787 s.visit(taskVisitor)
2788 self.assertEqual(len(taskList),3)
2789 s2 = s.copyAndExclude([g,h])
2790 taskList[:] = []
2791 s2.visit(taskVisitor)
2792 self.assertEqual(len(taskList),1)
2793 t2 = Task(t1)
2794 taskList[:] = []
2795 t2.visit(taskVisitor)
2796 self.assertEqual(taskList[0],t1)
2797 s3 = Sequence(s)
2798 self.assertEqual(s3.copyAndExclude([a,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.Task(process.e, process.f, process.g))\n")
2799 s4 = Sequence(s)
2800 self.assertEqual(s4.copyAndExclude([a,b,c,d,e,f,g,h]).dumpPython(),"cms.Sequence()\n")
2801 t1 = Task(e,f)
2802 t11 = Task(a)
2803 t11.setLabel("t11")
2804 t2 = Task(g,t1,h,t11)
2805 t3 = t2.copyAndExclude([e,h])
2806 self.assertTrue(t3.dumpPython() == "cms.Task(process.f, process.g, process.t11)\n")
2807 t4 = t2.copyAndExclude([e,f,g,h,a])
2808 self.assertTrue(t4.dumpPython() == "cms.Task()\n")
2809
2810 t1 = ConditionalTask(h)
2811 s = Sequence(a+b+c+~d, ConditionalTask(e,f,ConditionalTask(g,t1)))
2812 self.assertEqual(s.copyAndExclude([a,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.ConditionalTask(process.e, process.f, process.g))\n")
2813 self.assertEqual(s.copyAndExclude([a,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.ConditionalTask(process.e, process.f, process.g))\n")
2814 self.assertEqual(s.copyAndExclude([a,e,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.ConditionalTask(process.f, process.g))\n")
2815 self.assertEqual(s.copyAndExclude([a,e,f,g,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d)\n")
2816 self.assertEqual(s.copyAndExclude([a,b,c,d]).dumpPython(),"cms.Sequence(cms.ConditionalTask(process.e, process.f, process.g, process.h))\n")
2817 self.assertEqual(s.copyAndExclude([t1]).dumpPython(),"cms.Sequence(process.a+process.b+process.c+~process.d, cms.ConditionalTask(process.e, process.f, process.g))\n")
2818 taskList = []
2819 taskVisitor = ConditionalTaskVisitor(taskList)
2820 s.visit(taskVisitor)
2821 self.assertEqual(len(taskList),3)
2822 s2 = s.copyAndExclude([g,h])
2823 taskList[:] = []
2824 s2.visit(taskVisitor)
2825 self.assertEqual(len(taskList),1)
2826 t2 = ConditionalTask(t1)
2827 taskList[:] = []
2828 t2.visit(taskVisitor)
2829 self.assertEqual(taskList[0],t1)
2830 s3 = Sequence(s)
2831 self.assertEqual(s3.copyAndExclude([a,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.ConditionalTask(process.e, process.f, process.g))\n")
2832 s4 = Sequence(s)
2833 self.assertEqual(s4.copyAndExclude([a,b,c,d,e,f,g,h]).dumpPython(),"cms.Sequence()\n")
2834 t1 = ConditionalTask(e,f)
2835 t11 = ConditionalTask(a)
2836 t11.setLabel("t11")
2837 t2 = ConditionalTask(g,t1,h,t11)
2838 t3 = t2.copyAndExclude([e,h])
2839 self.assertEqual(t3.dumpPython(), "cms.ConditionalTask(process.f, process.g, process.t11)\n")
2840 t4 = t2.copyAndExclude([e,f,g,h,a])
2841 self.assertEqual(t4.dumpPython(), "cms.ConditionalTask()\n")
2842
2843 def testSequenceTypeChecks(self):
2844 m1 = DummyModule("m1")
2845 m2 = DummyModule("m2")
2846 s1 = Sequence(m1*m2)
2847 def testRaise():
2848 s1.something = 1
2849 self.assertRaises(AttributeError,testRaise)
2850 def testRaise2():
2851 s2 = Sequence(m1*None)
2852 self.assertRaises(TypeError,testRaise2)
2853 def testCopy(self):
2854 a = DummyModule("a")
2855 b = DummyModule("b")
2856 c = DummyModule("c")
2857 p1 = Path(a+b+c)
2858 p2 = p1.copy()
2859 e = DummyModule("e")
2860 p2.replace(b,e)
2861 self.assertEqual(p1.dumpPython(),"cms.Path(process.a+process.b+process.c)\n")
2862 self.assertEqual(p2.dumpPython(),"cms.Path(process.a+process.e+process.c)\n")
2863 p1 = Path(a+b+c)
2864 p2 = p1.copy()
2865 p1 += e
2866 self.assertEqual(p1.dumpPython(),"cms.Path(process.a+process.b+process.c+process.e)\n")
2867 self.assertEqual(p2.dumpPython(),"cms.Path(process.a+process.b+process.c)\n")
2868
2869 t1 = Task(a, b)
2870 t2 = t1.copy()
2871 self.assertTrue(t1.dumpPython() == t2.dumpPython())
2872 t1Contents = list(t1._collection)
2873 t2Contents = list(t2._collection)
2874 self.assertTrue(id(t1Contents[0]) == id(t2Contents[0]))
2875 self.assertTrue(id(t1Contents[1]) == id(t2Contents[1]))
2876 self.assertTrue(id(t1._collection) != id(t2._collection))
2877
2878 t1 = ConditionalTask(a, b)
2879 t2 = t1.copy()
2880 self.assertTrue(t1.dumpPython() == t2.dumpPython())
2881 t1Contents = list(t1._collection)
2882 t2Contents = list(t2._collection)
2883 self.assertTrue(id(t1Contents[0]) == id(t2Contents[0]))
2884 self.assertTrue(id(t1Contents[1]) == id(t2Contents[1]))
2885 self.assertTrue(id(t1._collection) != id(t2._collection))
2886
2887 def testCopyAndAdd(self):
2888 a = DummyModule("a")
2889 b = DummyModule("b")
2890 c = DummyModule("c")
2891 d = DummyModule("d")
2892 e = DummyModule("e")
2893
2894 t1 = Task(a, b, c)
2895 self.assertEqual(t1.dumpPython(), "cms.Task(process.a, process.b, process.c)\n")
2896 t2 = t1.copyAndAdd(d, e)
2897 self.assertEqual(t1.dumpPython(), "cms.Task(process.a, process.b, process.c)\n")
2898 self.assertEqual(t2.dumpPython(), "cms.Task(process.a, process.b, process.c, process.d, process.e)\n")
2899 t3 = t2.copyAndExclude([b])
2900 self.assertEqual(t1.dumpPython(), "cms.Task(process.a, process.b, process.c)\n")
2901 self.assertEqual(t2.dumpPython(), "cms.Task(process.a, process.b, process.c, process.d, process.e)\n")
2902 self.assertEqual(t3.dumpPython(), "cms.Task(process.a, process.c, process.d, process.e)\n")
2903 t4 = t1.copyAndExclude([b]).copyAndAdd(d)
2904 self.assertEqual(t4.dumpPython(), "cms.Task(process.a, process.c, process.d)\n")
2905 t5 = t2.copyAndExclude([b]).copyAndAdd(d)
2906 self.assertEqual(t5.dumpPython(), "cms.Task(process.a, process.c, process.d, process.e)\n")
2907 t6 = t4.copyAndAdd(Task(b))
2908 self.assertEqual(t6.dumpPython(), "cms.Task(process.a, process.b, process.c, process.d)\n")
2909
2910 t1 = ConditionalTask(a, b, c)
2911 self.assertEqual(t1.dumpPython(), "cms.ConditionalTask(process.a, process.b, process.c)\n")
2912 t2 = t1.copyAndAdd(d, e)
2913 self.assertEqual(t1.dumpPython(), "cms.ConditionalTask(process.a, process.b, process.c)\n")
2914 self.assertEqual(t2.dumpPython(), "cms.ConditionalTask(process.a, process.b, process.c, process.d, process.e)\n")
2915 t3 = t2.copyAndExclude([b])
2916 self.assertEqual(t1.dumpPython(), "cms.ConditionalTask(process.a, process.b, process.c)\n")
2917 self.assertEqual(t2.dumpPython(), "cms.ConditionalTask(process.a, process.b, process.c, process.d, process.e)\n")
2918 self.assertEqual(t3.dumpPython(), "cms.ConditionalTask(process.a, process.c, process.d, process.e)\n")
2919 t4 = t1.copyAndExclude([b]).copyAndAdd(d)
2920 self.assertEqual(t4.dumpPython(), "cms.ConditionalTask(process.a, process.c, process.d)\n")
2921 t5 = t2.copyAndExclude([b]).copyAndAdd(d)
2922 self.assertEqual(t5.dumpPython(), "cms.ConditionalTask(process.a, process.c, process.d, process.e)\n")
2923 t6 = t4.copyAndAdd(Task(b))
2924 self.assertEqual(t6.dumpPython(), "cms.ConditionalTask(process.a, process.b, process.c, process.d)\n")
2925
2926 def testInsertInto(self):
2927 from FWCore.ParameterSet.Types import vstring
2928 class TestPSet(object):
2929 def __init__(self):
2930 self._dict = dict()
2931 def addVString(self,isTracked,label,value):
2932 self._dict[label]=value
2933 a = DummyModule("a")
2934 b = DummyModule("b")
2935 c = DummyModule("c")
2936 d = DummyModule("d")
2937 p = Path(a+b+c+d)
2938 decoratedList = []
2939 lister = DecoratedNodeNameVisitor(decoratedList)
2940 p.visit(lister)
2941 ps = TestPSet()
2942 p.insertInto(ps,"p",decoratedList)
2943 self.assertEqual(ps._dict, {"p":vstring("a","b","c","d")})
2944 s = Sequence(b+c)
2945 p = Path(a+s+d)
2946 decoratedList[:] = []
2947 p.visit(lister)
2948 ps = TestPSet()
2949 p.insertInto(ps,"p",decoratedList)
2950 self.assertEqual(ps._dict, {"p":vstring("a","b","c","d")})
2951
2952 unittest.main()