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