File indexing completed on 2024-12-01 23:40:20
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 FinalPath(_ModuleSequenceType):
0664 def __init__(self,*arg,**argv):
0665 super(FinalPath,self).__init__(*arg,**argv)
0666 def _placeImpl(self,name:str,proc):
0667 proc._placeFinalPath(name,self)
0668 def associate(self,task):
0669 raise TypeError("FinalPath does not allow associations with Tasks")
0670
0671 class Sequence(_ModuleSequenceType,_Sequenceable):
0672 def __init__(self,*arg,**argv):
0673 super(Sequence,self).__init__(*arg,**argv)
0674 def _placeImpl(self,name:str,proc):
0675 proc._placeSequence(name,self)
0676 def _clonesequence(self, lookuptable):
0677 if id(self) not in lookuptable:
0678
0679
0680 if self._seq is not None:
0681 clone = type(self)(self._seq._clonesequence(lookuptable))
0682 else:
0683 clone = type(self)()
0684 lookuptable[id(self)]=clone
0685 lookuptable[id(clone)]=clone
0686 return lookuptable[id(self)]
0687 def _visitSubNodes(self,visitor):
0688 self.visit(visitor)
0689 class SequencePlaceholder(_Sequenceable):
0690 def __init__(self, name:str):
0691 self._name = name
0692 def _placeImpl(self,name:str,proc):
0693 pass
0694 def __str__(self):
0695 return self._name
0696 def insertInto(self, parameterSet, myname:str):
0697 raise RuntimeError("The SequencePlaceholder "+self._name
0698 +" was never overridden")
0699 def resolve(self, processDict,keepIfCannotResolve:bool=False):
0700 if not self._name in processDict:
0701
0702 if keepIfCannotResolve:
0703 return self
0704 raise RuntimeError("The SequencePlaceholder "+self._name+ " cannot be resolved.\n Known keys are:"+str(processDict.keys()))
0705 o = processDict[self._name]
0706 if not isinstance(o,_Sequenceable):
0707 raise RuntimeError("The SequencePlaceholder "+self._name+ " refers to an object type which is not allowed to be on a sequence: "+str(type(o)))
0708 return o.resolve(processDict)
0709
0710 def _clonesequence(self, lookuptable):
0711 if id(self) not in lookuptable:
0712
0713
0714 clone = type(self)(self._name)
0715 lookuptable[id(self)]=clone
0716 lookuptable[id(clone)]=clone
0717 return lookuptable[id(self)]
0718 def copy(self):
0719 returnValue =SequencePlaceholder.__new__(type(self))
0720 returnValue.__init__(self._name)
0721 return returnValue
0722 def dumpSequenceConfig(self) -> str:
0723 return 'cms.SequencePlaceholder("%s")' %self._name
0724 def dumpSequencePython(self, options=PrintOptions()) -> str:
0725 return 'cms.SequencePlaceholder("%s")'%self._name
0726 def dumpPython(self, options:PrintOptions=PrintOptions()) -> str:
0727 result = 'cms.SequencePlaceholder(\"'
0728 if options.isCfg:
0729 result += 'process.'
0730 result += self._name+'\")\n'
0731 return result
0732
0733
0734 class Schedule(_ValidatingParameterListBase,_ConfigureComponent,_Unlabelable):
0735
0736 def __init__(self,*arg,**argv):
0737 super(Schedule,self).__init__(*arg)
0738 self._tasks = OrderedSet()
0739 theKeys = list(argv.keys())
0740 if theKeys:
0741 if len(theKeys) > 1 or theKeys[0] != "tasks":
0742 raise RuntimeError("The Schedule constructor can only have one keyword argument after its Path and\nEndPath arguments and it must use the keyword 'tasks'")
0743 taskList = argv["tasks"]
0744
0745 if isinstance(taskList,Task):
0746 self.associate(taskList)
0747 else:
0748 try:
0749
0750 self.__dummy(*taskList)
0751 except:
0752 raise RuntimeError("The Schedule constructor argument with keyword 'tasks' must have a\nlist (or other iterable object) as its value")
0753 if taskList:
0754 self.associate(*taskList)
0755
0756 def __dummy(self, *args):
0757 pass
0758
0759 def associate(self,*tasks):
0760 for task in tasks:
0761 if not isinstance(task, Task):
0762 raise TypeError("The associate function in the class Schedule only works with arguments of type Task")
0763 self._tasks.add(task)
0764 @staticmethod
0765 def _itemIsValid(item) -> bool:
0766 return isinstance(item,Path) or isinstance(item,EndPath) or isinstance(item,FinalPath)
0767 def copy(self):
0768 import copy
0769 aCopy = copy.copy(self)
0770 aCopy._tasks = OrderedSet(self._tasks)
0771 return aCopy
0772 def _place(self,label:str,process):
0773 process.setPartialSchedule_(self,label)
0774 def _replaceIfHeldDirectly(self,original,replacement) -> bool:
0775 """Only replaces an 'original' with 'replacement' if 'original' is directly held.
0776 If a contained Path or Task holds 'original' it will not be replaced."""
0777 didReplace = False
0778 if original in self._tasks:
0779 self._tasks.remove(original)
0780 if replacement is not None:
0781 self._tasks.add(replacement)
0782 didReplace = True
0783 indices = []
0784 for i, e in enumerate(self):
0785 if original == e:
0786 indices.append(i)
0787 for i in reversed(indices):
0788 self.pop(i)
0789 if replacement is not None:
0790 self.insert(i, replacement)
0791 didReplace = True
0792 return didReplace
0793
0794 def moduleNames(self):
0795 result = set()
0796 visitor = NodeNameVisitor(result)
0797 for seq in self:
0798 seq.visit(visitor)
0799 for t in self._tasks:
0800 t.visit(visitor)
0801 return result
0802 def contains(self, mod) -> bool:
0803 visitor = ContainsModuleVisitor(mod)
0804 for seq in self:
0805 seq.visit(visitor)
0806 if visitor.result():
0807 return True
0808 for t in self._tasks:
0809 t.visit(visitor)
0810 if visitor.result():
0811 return True
0812 return visitor.result()
0813 def tasks(self):
0814 """Returns the list of Tasks (that may contain other Tasks) that are associated directly to the Schedule."""
0815 return self._tasks
0816 def dumpPython(self, options:PrintOptions=PrintOptions()) -> str:
0817 pathNames = ['process.'+p.label_() for p in self]
0818 if pathNames:
0819 s=', '.join(pathNames)
0820 else:
0821 s = ''
0822 associationContents = set()
0823 for task in self._tasks:
0824 if task.hasLabel_():
0825 associationContents.add(_Labelable.dumpSequencePython(task, options))
0826 else:
0827 associationContents.add(task.dumpPythonNoNewline(options))
0828 taskStrings = list()
0829 for iString in sorted(associationContents):
0830 taskStrings.append(iString)
0831 if taskStrings and s:
0832 return 'cms.Schedule(*[ ' + s + ' ], tasks=[' + ', '.join(taskStrings) + '])\n'
0833 elif s:
0834 return 'cms.Schedule(*[ ' + s + ' ])\n'
0835 elif taskStrings:
0836 return 'cms.Schedule(tasks=[' + ', '.join(taskStrings) + '])\n'
0837 else:
0838 return 'cms.Schedule()\n'
0839
0840 def __str__(self) -> str:
0841 return self.dumpPython()
0842
0843
0844
0845 class SequenceVisitor(object):
0846 def __init__(self,d):
0847 self.deps = d
0848 def enter(self,visitee):
0849 if isinstance(visitee,Sequence):
0850 self.deps.append(visitee)
0851 pass
0852 def leave(self,visitee):
0853 pass
0854
0855
0856
0857 class TaskVisitor(object):
0858 def __init__(self,d):
0859 self.deps = d
0860 def enter(self,visitee):
0861 if isinstance(visitee,Task):
0862 self.deps.append(visitee)
0863 pass
0864 def leave(self,visitee):
0865 pass
0866
0867
0868
0869 class ConditionalTaskVisitor(object):
0870 def __init__(self,d):
0871 self.deps = d
0872 def enter(self,visitee):
0873 if isinstance(visitee,ConditionalTask):
0874 self.deps.append(visitee)
0875 pass
0876 def leave(self,visitee):
0877 pass
0878
0879
0880
0881
0882
0883
0884
0885
0886
0887 class ModuleNodeVisitor(object):
0888 def __init__(self,l):
0889 self.l = l
0890 def enter(self,visitee):
0891 if visitee.isLeaf():
0892 self.l.append(visitee)
0893 pass
0894 def leave(self,visitee):
0895 pass
0896
0897
0898
0899
0900
0901
0902 class ModuleNodeOnTaskVisitor(object):
0903 def __init__(self,l):
0904 self.l = l
0905 self._levelInTasks = 0
0906 def enter(self,visitee):
0907 if isinstance(visitee, Task):
0908 self._levelInTasks += 1
0909 if self._levelInTasks == 0:
0910 return
0911 if visitee.isLeaf():
0912 self.l.append(visitee)
0913 pass
0914 def leave(self,visitee):
0915 if self._levelInTasks > 0:
0916 if isinstance(visitee, Task):
0917 self._levelInTasks -= 1
0918
0919 class ModuleNodeOnConditionalTaskVisitor(object):
0920 def __init__(self,l):
0921 self.l = l
0922 self._levelInTasks = 0
0923 def enter(self,visitee):
0924 if isinstance(visitee, ConditionalTask):
0925 self._levelInTasks += 1
0926
0927
0928
0929
0930 if hasattr(visitee, "modulesForConditionalTask_"):
0931 self.l.extend(visitee.modulesForConditionalTask_())
0932 if self._levelInTasks == 0:
0933 return
0934 if visitee.isLeaf():
0935 self.l.append(visitee)
0936 pass
0937 def leave(self,visitee):
0938 if self._levelInTasks > 0:
0939 if isinstance(visitee, ConditionalTask):
0940 self._levelInTasks -= 1
0941
0942
0943
0944
0945
0946
0947
0948 class ModuleNodeNotOnTaskVisitor(object):
0949 def __init__(self,l):
0950 self.l = l
0951 self._levelInTasks = 0
0952 def enter(self,visitee):
0953 if isinstance(visitee, Task):
0954 self._levelInTasks += 1
0955 if self._levelInTasks > 0:
0956 return
0957 if visitee.isLeaf():
0958 self.l.append(visitee)
0959 pass
0960 def leave(self,visitee):
0961 if self._levelInTasks > 0:
0962 if isinstance(visitee, Task):
0963 self._levelInTasks -= 1
0964
0965
0966
0967
0968
0969
0970 class ContainsModuleVisitor(object):
0971 def __init__(self,mod):
0972 self._mod = mod
0973 self._result = False
0974
0975 def result(self):
0976 return self._result
0977
0978 def enter(self,visitee):
0979 if self._mod is visitee:
0980 self._result = True
0981
0982 def leave(self,visitee):
0983 pass
0984
0985
0986
0987
0988
0989
0990
0991
0992
0993
0994 class NodeNameVisitor(object):
0995 """ takes a set as input"""
0996 def __init__(self,l):
0997 self.l = l
0998 def enter(self,visitee):
0999 if visitee.isLeaf():
1000 if isinstance(visitee, _Labelable):
1001 self.l.add(visitee.label_())
1002 else:
1003 if visitee._inProcess:
1004 self.l.add(visitee.type_())
1005 else:
1006 raise RuntimeError("Service not attached to process: {}".format(visitee.dumpPython()))
1007 def leave(self,visitee):
1008 pass
1009
1010
1011
1012 class ExpandVisitor(object):
1013 """ Expands the sequence into leafs and UnaryOperators """
1014 def __init__(self, type):
1015 self._type = type
1016 self.l = []
1017 self.taskLeaves = []
1018 self.taskLeavesInConditionalTasks = []
1019 self.presentTaskLeaves = self.taskLeaves
1020 self._levelInTasks = 0
1021 self.conditionaltaskLeaves = []
1022 self._levelInConditionalTasks = 0
1023
1024 def enter(self,visitee):
1025 if isinstance(visitee, Task):
1026 self._levelInTasks += 1
1027 return
1028 if isinstance(visitee, ConditionalTask):
1029 self.presentTaskLeaves = self.taskLeavesInConditionalTasks
1030 self._levelInConditionalTasks += 1
1031 return
1032 if visitee.isLeaf():
1033 if self._levelInTasks > 0:
1034 self.presentTaskLeaves.append(visitee)
1035 elif self._levelInConditionalTasks > 0:
1036 self.conditionaltaskLeaves.append(visitee)
1037 else:
1038 self.l.append(visitee)
1039 def leave(self, visitee):
1040 if self._levelInTasks > 0:
1041 if isinstance(visitee, Task):
1042 self._levelInTasks -= 1
1043 return
1044 if self._levelInConditionalTasks > 0:
1045 if isinstance(visitee, ConditionalTask):
1046 self._levelInConditionalTasks -= 1
1047 if 0 == self._levelInConditionalTasks:
1048 self.presentTaskLeaves = self.taskLeaves
1049 return
1050 if isinstance(visitee,_UnarySequenceOperator):
1051 self.l[-1] = visitee
1052 def result(self):
1053 tsks = []
1054 if self.taskLeaves:
1055 tsks.append(Task(*self.taskLeaves))
1056 if self.conditionaltaskLeaves:
1057 ct = ConditionalTask(*self.conditionaltaskLeaves)
1058 if self.taskLeavesInConditionalTasks:
1059 ct.append(*self.taskLeavesInConditionalTasks)
1060 tsks.append(ct)
1061 if len(self.l) > 0:
1062
1063 seq = self.l[0]
1064 for el in self.l[1:]:
1065 seq += el
1066 return self._type(seq, *tsks)
1067 else:
1068 return self._type(*tsks)
1069 def resultString(self):
1070 sep = ''
1071 returnValue = ''
1072 for m in self.l:
1073 if m is not None:
1074 returnValue += sep+str(m)
1075 sep = '+'
1076 if returnValue:
1077 sep = ','
1078 for n in self.taskLeaves:
1079 if n is not None:
1080 returnValue += sep+str(n)
1081 sep = ','
1082 return returnValue
1083
1084
1085
1086
1087 class DecoratedNodeNameVisitor(object):
1088 """ Adds any '!' or '-' needed. Takes a list """
1089 def __init__(self,l):
1090 self.l = l
1091 self._decoration =''
1092 self._levelInTasks = 0
1093
1094 def initialize(self):
1095 self.l[:] = []
1096 self._decoration =''
1097 self._levelInTasks = 0
1098
1099 def enter(self,visitee):
1100 if isinstance(visitee, _TaskBase):
1101 self._levelInTasks += 1
1102 if self._levelInTasks > 0:
1103 return
1104 if visitee.isLeaf():
1105 if hasattr(visitee, "_Labelable__label"):
1106 self.l.append(self._decoration+visitee.label_())
1107 else:
1108 error = "An object in a sequence was not found in the process\n"
1109 if hasattr(visitee, "_filename"):
1110 error += "From file " + visitee._filename
1111 else:
1112 error += "Dump follows\n" + repr(visitee)
1113 raise RuntimeError(error)
1114 if isinstance(visitee,_BooleanLogicExpression):
1115 self.l.append(self._decoration+visitee.operatorString())
1116 if isinstance(visitee,_UnarySequenceOperator):
1117 self._decoration=visitee.decoration()
1118 else:
1119 self._decoration=''
1120
1121 def leave(self,visitee):
1122
1123 if self._levelInTasks > 0:
1124 if isinstance(visitee, _TaskBase):
1125 self._levelInTasks -= 1
1126 return
1127 if isinstance(visitee,_BooleanLogicExpression):
1128
1129 self.l.append('@')
1130
1131
1132
1133
1134 class DecoratedNodeNamePlusVisitor(object):
1135 """ Adds any '!' or '-' needed. Takes a list """
1136 def __init__(self,l):
1137 self.l = l
1138 self._decoration =''
1139 self._levelInTasks = 0
1140 self._leavesOnTasks = []
1141
1142 def initialize(self):
1143 self.l[:] = []
1144 self._decoration =''
1145 self._levelInTasks = 0
1146 self._leavesOnTasks[:] = []
1147
1148 def enter(self,visitee):
1149 if isinstance(visitee, Task):
1150 self._levelInTasks += 1
1151 if self._levelInTasks > 0:
1152 if visitee.isLeaf():
1153 self._leavesOnTasks.append(visitee)
1154 return
1155 if visitee.isLeaf():
1156 if hasattr(visitee, "_Labelable__label"):
1157 self.l.append(self._decoration+visitee.label_())
1158 else:
1159 error = "An object in a sequence was not found in the process\n"
1160 if hasattr(visitee, "_filename"):
1161 error += "From file " + visitee._filename
1162 else:
1163 error += "Dump follows\n" + repr(visitee)
1164 raise RuntimeError(error)
1165 if isinstance(visitee,_BooleanLogicExpression):
1166 self.l.append(self._decoration+visitee.operatorString())
1167 if isinstance(visitee,_UnarySequenceOperator):
1168 self._decoration=visitee.decoration()
1169 else:
1170 self._decoration=''
1171
1172 def leave(self,visitee):
1173
1174 if self._levelInTasks > 0:
1175 if isinstance(visitee, Task):
1176 self._levelInTasks -= 1
1177 return
1178 if isinstance(visitee,_BooleanLogicExpression):
1179
1180 self.l.append('@')
1181
1182 def leavesOnTasks(self):
1183 return self._leavesOnTasks
1184
1185 class _CopyAndExcludeSequenceVisitorOld(object):
1186 """Traverses a Sequence and constructs a new sequence which does not contain modules from the specified list"""
1187 def __init__(self,modulesToRemove):
1188 self.__modulesToIgnore = modulesToRemove
1189 self.__stack = list()
1190 self.__stack.append(list())
1191 self.__result = None
1192 self.__didExclude = False
1193 def enter(self,visitee):
1194 if len(self.__stack) > 0:
1195
1196 self.__stack[-1].append([visitee,False])
1197 if visitee.isLeaf():
1198 if visitee in self.__modulesToIgnore:
1199 self.__didExclude = True
1200 self.__stack[-1][-1]=[None,True]
1201 elif isinstance(visitee, Sequence):
1202 if visitee in self.__modulesToIgnore:
1203 self.__didExclude = True
1204 self.__stack[-1][-1]=[None,True]
1205 self.__stack.append(list())
1206 else:
1207
1208 self.__stack.append(list())
1209 def leave(self,visitee):
1210 node = visitee
1211 if not visitee.isLeaf():
1212
1213 l = self.__stack[-1]
1214 changed = False
1215 countNulls = 0
1216 nonNulls = list()
1217 for c in l:
1218 if c[1] == True:
1219 changed = True
1220 if c[0] is None:
1221 countNulls +=1
1222 else:
1223 nonNulls.append(c[0])
1224 if changed:
1225 self.__didExclude = True
1226 if countNulls != 0:
1227
1228 if len(nonNulls) == 0:
1229
1230 node = None
1231 else:
1232 node = nonNulls[0]
1233 for n in nonNulls[1:]:
1234 node = node+n
1235 else:
1236
1237
1238
1239 children = [x[0] for x in l ]
1240 if not isinstance(visitee,Sequence):
1241 node = visitee.__new__(type(visitee))
1242 node.__init__(*children)
1243 else:
1244 node = nonNulls[0]
1245 if node != visitee:
1246
1247
1248 if len(self.__stack) > 1:
1249 p = self.__stack[-2]
1250
1251 for i,c in enumerate(p):
1252 if c[0]==visitee:
1253 c[0]=node
1254 c[1]=True
1255 break
1256 if not visitee.isLeaf():
1257 self.__stack = self.__stack[:-1]
1258 def result(self):
1259 result = None
1260 for n in (x[0] for x in self.__stack[0]):
1261 if n is None:
1262 continue
1263 if result is None:
1264 result = n
1265 else:
1266 result = result+n
1267 return result
1268 def didExclude(self):
1269 return self.__didExclude
1270
1271
1272
1273 class _MutatingSequenceVisitor(object):
1274 """Traverses a Sequence and constructs a new sequence by applying the operator to each element of the sequence"""
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
1316
1317
1318
1319
1320
1321
1322
1323 def __init__(self,operator):
1324 self.__operator = operator
1325
1326
1327 self.__stack = list()
1328 self.__stack.append(list())
1329 self.__didApply = False
1330 self.__levelInModifiedNonLeaf = 0
1331 def enter(self,visitee):
1332
1333
1334 if self.__levelInModifiedNonLeaf > 0:
1335 if not visitee.isLeaf():
1336 self.__levelInModifiedNonLeaf += 1
1337 return
1338
1339
1340 if not len(self.__stack) > 0:
1341 raise RuntimeError("LogicError Empty stack in MutatingSequenceVisitor.\n"
1342 "This should never happen. Contact a Framework developer.")
1343
1344
1345
1346
1347 v = self.__operator(visitee)
1348
1349 if v is visitee:
1350
1351
1352
1353
1354
1355
1356
1357
1358 self.__stack[-1].append([visitee, False, None])
1359 if not visitee.isLeaf():
1360
1361
1362 self.__stack.append(list())
1363 else:
1364
1365 self.__didApply = True
1366 self.__stack[-1].append([v, True, None])
1367 if not visitee.isLeaf():
1368
1369 self.__levelInModifiedNonLeaf = 1
1370 def leave(self,visitee):
1371
1372
1373 if visitee.isLeaf():
1374 return
1375
1376
1377
1378 if self.__levelInModifiedNonLeaf > 0:
1379 self.__levelInModifiedNonLeaf -= 1
1380 return
1381
1382
1383
1384
1385
1386
1387 contents = self.__stack[-1]
1388 changed = False
1389 allNull = True
1390 for c in contents:
1391 if c[1] == True:
1392 changed = True
1393 if c[0] is not None:
1394 allNull = False
1395 if changed:
1396 if allNull:
1397 self.__stack[-2][-1] = [None, True, None]
1398
1399 elif isinstance(visitee, _UnarySequenceOperator):
1400 node = visitee.__new__(type(visitee))
1401 node.__init__(contents[0][0])
1402 self.__stack[-2][-1] = [node, True, None]
1403
1404 elif isinstance(visitee, _TaskBase):
1405 nonNull = []
1406 for c in contents:
1407 if c[0] is not None:
1408 nonNull.append(c[0])
1409 self.__stack[-2][-1] = [visitee._makeInstance(*nonNull), True, None]
1410 elif isinstance(visitee, Sequence):
1411 seq = _SequenceCollection()
1412 tasks = list()
1413 for c in contents:
1414 if c[0] is None:
1415 continue
1416 if isinstance(c[0], _TaskBase):
1417 tasks.append(c[0])
1418 else:
1419 seq = seq + c[0]
1420 if c[2] is not None:
1421 tasks.extend(c[2])
1422
1423 self.__stack[-2][-1] = [seq, True, tasks]
1424
1425
1426
1427
1428 if not visitee.isLeaf():
1429 self.__stack = self.__stack[:-1]
1430
1431 def result(self, visitedContainer):
1432
1433 if isinstance(visitedContainer, _TaskBase):
1434 result = list()
1435 for n in (x[0] for x in self.__stack[0]):
1436 if n is not None:
1437 result.append(n)
1438 return result
1439
1440 seq = _SequenceCollection()
1441 tasks = list()
1442 for c in self.__stack[0]:
1443 if c[0] is None:
1444 continue
1445 if isinstance(c[0], _TaskBase):
1446 tasks.append(c[0])
1447 else:
1448 seq = seq + c[0]
1449 if c[2] is not None:
1450 tasks.extend(c[2])
1451 return [seq, tasks]
1452
1453 def _didApply(self) -> bool:
1454 return self.__didApply
1455
1456
1457 class _CopyAndRemoveFirstSequenceVisitor(_MutatingSequenceVisitor):
1458 """Traverses a Sequence and constructs a new sequence which does not contain modules from the specified list"""
1459 def __init__(self,moduleToRemove):
1460 class _RemoveFirstOperator(object):
1461 def __init__(self,moduleToRemove):
1462 self.__moduleToRemove = moduleToRemove
1463 self.__found = False
1464 def __call__(self,test):
1465 if not self.__found and test is self.__moduleToRemove:
1466 self.__found = True
1467 return None
1468 return test
1469 super(type(self),self).__init__(_RemoveFirstOperator(moduleToRemove))
1470 def didRemove(self) -> bool:
1471 return self._didApply()
1472
1473
1474 class _CopyAndExcludeSequenceVisitor(_MutatingSequenceVisitor):
1475 """Traverses a Sequence and constructs a new sequence which does not contain the module specified"""
1476 def __init__(self,modulesToRemove):
1477 class _ExcludeOperator(object):
1478 def __init__(self,modulesToRemove):
1479 self.__modulesToIgnore = modulesToRemove
1480 def __call__(self,test):
1481 if test in modulesToRemove:
1482 return None
1483 return test
1484 super(type(self),self).__init__(_ExcludeOperator(modulesToRemove))
1485 def didExclude(self) -> bool:
1486 return self._didApply()
1487
1488
1489 class _CopyAndReplaceSequenceVisitor(_MutatingSequenceVisitor):
1490 """Traverses a Sequence and constructs a new sequence which replaces a specified module with a different module"""
1491 def __init__(self,target,replace):
1492 class _ReplaceOperator(object):
1493 def __init__(self,target,replace):
1494 self.__target = target
1495 self.__replace = replace
1496 def __call__(self,test):
1497 if test == self.__target:
1498 return self.__replace
1499 return test
1500 super(type(self),self).__init__(_ReplaceOperator(target,replace))
1501 def didReplace(self) -> bool:
1502 return self._didApply()
1503
1504 class _TaskBase(_ConfigureComponent, _Labelable) :
1505 def __init__(self, *items):
1506 self._collection = OrderedSet()
1507 self.add(*items)
1508
1509 def __setattr__(self,name:str,value):
1510 if not name.startswith("_"):
1511 raise AttributeError("You cannot set parameters for {} objects.".format(self._taskType()))
1512 else:
1513 self.__dict__[name] = value
1514
1515 def add(self, *items):
1516 for item in items:
1517 if not self._allowedInTask(item):
1518 raise RuntimeError("Adding an entry of type '{0}' to a {1}.\n"
1519 "It is illegal to add this type to a {1}.".format(type(item).__name__, self._taskType()))
1520 self._collection.add(item)
1521
1522 def fillContents(self, taskContents, options:PrintOptions=PrintOptions()):
1523
1524 if self.hasLabel_():
1525 taskContents.add(_Labelable.dumpSequencePython(self, options))
1526 else:
1527 for i in self._collection:
1528 if isinstance(i, _TaskBase):
1529 i.fillContents(taskContents, options)
1530 else:
1531 taskContents.add(i.dumpSequencePython(options))
1532
1533 def dumpPython(self, options:PrintOptions=PrintOptions()) -> str:
1534 s = self.dumpPythonNoNewline(options)
1535 return s + "\n"
1536
1537 def dumpPythonNoNewline(self, options:PrintOptions=PrintOptions()) -> str:
1538 """Returns a string which is the python representation of the object"""
1539 taskContents = set()
1540 for i in self._collection:
1541 if isinstance(i, _TaskBase):
1542 i.fillContents(taskContents, options)
1543 else:
1544 taskContents.add(i.dumpSequencePython(options))
1545 s=''
1546 iFirst = True
1547 for item in sorted(taskContents):
1548 if not iFirst:
1549 s += ", "
1550 iFirst = False
1551 s += item
1552 if len(taskContents) > 255:
1553 s = "*[" + s + "]"
1554 return "cms.{}({})".format(self._taskType(),s)
1555
1556 def directDependencies(self,sortByType:bool=True):
1557 return findDirectDependencies(self, self._collection,sortByType=sortByType)
1558
1559 def _isTaskComponent(self) -> bool:
1560 return False
1561
1562 def isLeaf(self) -> bool:
1563 return False
1564
1565 def visit(self,visitor):
1566 for i in self._collection:
1567 visitor.enter(i)
1568 if not i.isLeaf():
1569 i.visit(visitor)
1570 visitor.leave(i)
1571
1572 def _errorstr(self) -> str:
1573 return "{}(...)".format(self.taskType_())
1574
1575 def __iter__(self):
1576 for key in self._collection:
1577 yield key
1578
1579 def __str__(self) -> str:
1580 l = []
1581 v = ModuleNodeVisitor(l)
1582 self.visit(v)
1583 s = ''
1584 for i in l:
1585 if s:
1586 s += ', '
1587 s += str (i)
1588 return s
1589
1590 def __repr__(self) -> str:
1591 s = str(self)
1592 return "cms."+type(self).__name__+'('+s+')\n'
1593
1594 def moduleNames(self):
1595 """Returns a set containing the names of all modules being used"""
1596 result = set()
1597 visitor = NodeNameVisitor(result)
1598 self.visit(visitor)
1599 return result
1600 def contains(self, mod):
1601 visitor = ContainsModuleVisitor(mod)
1602 self.visit(visitor)
1603 return visitor.result()
1604 def copy(self):
1605 return self._makeInstance(*self._collection)
1606 def copyAndExclude(self,listOfModulesToExclude):
1607 """Returns a copy of the sequence which excludes those module in 'listOfModulesToExclude'"""
1608
1609
1610
1611
1612
1613 for i in listOfModulesToExclude:
1614 if not i._isTaskComponent():
1615 raise TypeError("copyAndExclude can only exclude objects that can be placed on a Task")
1616 v = _CopyAndExcludeSequenceVisitor(listOfModulesToExclude)
1617 self.visit(v)
1618 return self._makeInstance(*v.result(self))
1619 def copyAndAdd(self, *modulesToAdd):
1620 """Returns a copy of the Task adding modules/tasks"""
1621 t = self.copy()
1622 t.add(*modulesToAdd)
1623 return t
1624 def expandAndClone(self):
1625
1626
1627
1628
1629 l = []
1630 v = ModuleNodeVisitor(l)
1631 self.visit(v)
1632 return self._makeInstance(*l)
1633 def replace(self, original, replacement):
1634 """Finds all instances of 'original' and substitutes 'replacement' for them.
1635 Returns 'True' if a replacement occurs."""
1636
1637
1638
1639
1640
1641
1642
1643 if not self._allowedInTask(original) or (not replacement is None and not self._allowedInTask(replacement)):
1644 raise TypeError("The {0} replace function only works with objects that can be placed on a {0}\n".format(self._taskType()) + \
1645 " replace was called with original type = {}\n".format(str(type(original))) + \
1646 " and replacement type = {}\n".format(str(type(replacement))))
1647 else:
1648 v = _CopyAndReplaceSequenceVisitor(original,replacement)
1649 self.visit(v)
1650 if v.didReplace():
1651 self._collection.clear()
1652 self.add(*v.result(self))
1653 return v.didReplace()
1654
1655 def remove(self, something):
1656 """Remove the first occurrence of a module
1657 Returns 'True' if the module has been removed, False if it was not found"""
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668 if not self._allowedInTask(something):
1669 raise TypeError("remove only works with objects that can be placed on a Task")
1670 v = _CopyAndRemoveFirstSequenceVisitor(something)
1671 self.visit(v)
1672 if v.didRemove():
1673 self._collection.clear()
1674 self.add(*v.result(self))
1675 return v.didRemove()
1676
1677 def resolve(self, processDict,keepIfCannotResolve:bool=False):
1678 temp = OrderedSet()
1679 for i in self._collection:
1680 if self._mustResolve(i):
1681 temp.add(i.resolve(processDict,keepIfCannotResolve))
1682 else:
1683 temp.add(i)
1684 self._collection = temp
1685 return self
1686
1687 class _TaskBasePlaceholder(object):
1688 def __init__(self, name:str):
1689 self._name = name
1690 def _isTaskComponent(self) -> bool:
1691 return False
1692 def isLeaf(self) -> bool:
1693 return False
1694 def visit(self,visitor):
1695 pass
1696 def __str__(self) -> str:
1697 return self._name
1698 def insertInto(self, parameterSet, myname):
1699 raise RuntimeError("The {} {} was never overridden".format(self._typeName(), self._name))
1700 def resolve(self, processDict,keepIfCannotResolve:bool=False):
1701 if not self._name in processDict:
1702 if keepIfCannotResolve:
1703 return self
1704 raise RuntimeError("The {} {} cannot be resolved.\n Known keys are: {}".format(self._typeName(), self._name,str(processDict.keys())))
1705 o = processDict[self._name]
1706 if not self._allowedInTask(o):
1707 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))))
1708 if isinstance(o, self._taskClass()):
1709 return o.resolve(processDict)
1710 return o
1711 def copy(self):
1712 return self._makeInstance(self._name)
1713 def dumpSequencePython(self, options:PrintOptions=PrintOptions()) -> str:
1714 return 'cms.{}("{}")'.format(self._typeName(), self._name)
1715 def dumpPython(self, options:PrintOptions=PrintOptions()) -> str:
1716 result = 'cms.{}(\"'.format(self._typeName())
1717 if options.isCfg:
1718 result += 'process.'
1719 result += self._name+'\")\n'
1720 return result
1721
1722 class Task(_TaskBase) :
1723 """Holds EDProducers, EDFilters, ESProducers, ESSources, Services, and Tasks.
1724 A Task can be associated with Sequences, Paths, EndPaths, ConditionalTasks and the Schedule.
1725 An EDProducer or EDFilter will be enabled to run unscheduled if it is on
1726 a task associated with the Schedule or any scheduled Path or EndPath (directly
1727 or indirectly through Sequences) and not be on any scheduled Path or EndPath.
1728 ESSources, ESProducers, and Services will be enabled to run if they are on
1729 a Task associated with the Schedule or a scheduled Path or EndPath. In other
1730 cases, they will be enabled to run if and only if they are not on a Task attached
1731 to the process.
1732 """
1733 @staticmethod
1734 def _taskType() -> str:
1735 return "Task"
1736 def _place(self, name:str, proc):
1737 proc._placeTask(name,self)
1738 def _isTaskComponent(self) -> bool:
1739 return True
1740 @staticmethod
1741 def _makeInstance(*items):
1742 return Task(*items)
1743 @staticmethod
1744 def _allowedInTask(item ) -> bool:
1745 return (isinstance(item, _ConfigureComponent) and item._isTaskComponent()) or isinstance(item, TaskPlaceholder)
1746 @staticmethod
1747 def _mustResolve(item) -> bool:
1748 return isinstance(item, Task) or isinstance(item, TaskPlaceholder)
1749
1750 class TaskPlaceholder(_TaskBasePlaceholder):
1751 def _isTaskComponent(self) -> bool:
1752 return True
1753 @staticmethod
1754 def _typeName() -> str:
1755 return "TaskPlaceholder"
1756 @staticmethod
1757 def _makeInstance(name):
1758 return TaskPlaceholder(name)
1759 @staticmethod
1760 def _allowedInTask(obj) -> bool:
1761 return Task._allowedInTask(obj)
1762 @staticmethod
1763 def _taskClass():
1764 return Task
1765
1766
1767 class ConditionalTask(_TaskBase) :
1768 """Holds EDProducers, EDFilters, ESProducers, ESSources, Services, Tasks and ConditionalTasks.
1769 A ConditionalTask can be associated with Sequences, Paths, and EndPaths.
1770 An EDProducer or EDFilter will be added to a Path or EndPath based on which other
1771 modules on the Path consumes its data products. If that ConditionalTask assigned module
1772 is placed after an EDFilter, the module will only run if the EDFilter passes. If no module
1773 on the Path needs the module's data products, the module will be treated as if it were on a Task.
1774 """
1775 @staticmethod
1776 def _taskType():
1777 return "ConditionalTask"
1778 def _place(self, name:str, proc):
1779 proc._placeConditionalTask(name,self)
1780 def _isTaskComponent(self) -> bool:
1781 return False
1782 @staticmethod
1783 def _makeInstance(*items):
1784 return ConditionalTask(*items)
1785 @staticmethod
1786 def _allowedInTask(item) -> bool:
1787 return isinstance(item, ConditionalTask) or isinstance(item, ConditionalTaskPlaceholder) or Task._allowedInTask(item)
1788 @staticmethod
1789 def _mustResolve(item) -> bool:
1790 return Task._mustResolve(item) or isinstance(item, ConditionalTask) or isinstance(item, ConditionalTaskPlaceholder)
1791
1792
1793 class ConditionalTaskPlaceholder(_TaskBasePlaceholder):
1794 def _isTaskComponent(self) -> bool:
1795 return False
1796 @staticmethod
1797 def _typeName() -> str:
1798 return "ConditionalTaskPlaceholder"
1799 @staticmethod
1800 def _makeInstance(name):
1801 return ConditionalTaskPlaceholder(name)
1802 @staticmethod
1803 def _allowedInTask(obj) -> bool:
1804 return Task._allowedInTask(obj) or ConditionalTask._allowedInTask(obj)
1805 @staticmethod
1806 def _taskClass():
1807 return ConditionalTask
1808
1809
1810 if __name__=="__main__":
1811 import unittest
1812 class DummyModule(_Labelable, _SequenceLeaf, _ConfigureComponent):
1813 def __init__(self,name):
1814 self.setLabel(name)
1815 def _isTaskComponent(self):
1816 return True
1817 def __repr__(self):
1818 return self.label_()
1819 class DummyBooleanModule(_Labelable, _BooleanLogicSequenceLeaf):
1820 def __init__(self,name):
1821 self.setLabel(name)
1822 class TestModuleCommand(unittest.TestCase):
1823 def setUp(self):
1824 """Nothing to do """
1825 pass
1826 def testBoolean(self):
1827 a = DummyBooleanModule("a")
1828 b = DummyBooleanModule("b")
1829 p = Path( a & b)
1830 self.assertEqual(p.dumpPython(),"cms.Path(process.a&process.b)\n")
1831 l = list()
1832 namesVisitor = DecoratedNodeNameVisitor(l)
1833 p.visit(namesVisitor)
1834 self.assertEqual(l,['&','a','b','@'])
1835 p2 = Path( a | b)
1836 self.assertEqual(p2.dumpPython(),"cms.Path(process.a|process.b)\n")
1837 l[:]=[]
1838 p2.visit(namesVisitor)
1839 self.assertEqual(l,['|','a','b','@'])
1840 c = DummyBooleanModule("c")
1841 d = DummyBooleanModule("d")
1842 p3 = Path(a & b & c & d)
1843 self.assertEqual(p3.dumpPython(),"cms.Path(process.a&process.b&process.c&process.d)\n")
1844 l[:]=[]
1845 p3.visit(namesVisitor)
1846 self.assertEqual(l,['&','a','b','c','d','@'])
1847 p3 = Path(((a & b) & c) & d)
1848 self.assertEqual(p3.dumpPython(),"cms.Path(process.a&process.b&process.c&process.d)\n")
1849 p3 = Path(a & (b & (c & d)))
1850 self.assertEqual(p3.dumpPython(),"cms.Path(process.a&process.b&process.c&process.d)\n")
1851 p3 = Path((a & b) & (c & d))
1852 self.assertEqual(p3.dumpPython(),"cms.Path(process.a&process.b&process.c&process.d)\n")
1853 p3 = Path(a & (b & c) & d)
1854 self.assertEqual(p3.dumpPython(),"cms.Path(process.a&process.b&process.c&process.d)\n")
1855 p4 = Path(a | b | c | d)
1856 self.assertEqual(p4.dumpPython(),"cms.Path(process.a|process.b|process.c|process.d)\n")
1857 p5 = Path(a | b & c & d )
1858 self.assertEqual(p5.dumpPython(),"cms.Path(process.a|(process.b&process.c&process.d))\n")
1859 l[:]=[]
1860 p5.visit(namesVisitor)
1861 self.assertEqual(l,['|','a','&','b','c','d','@','@'])
1862 p5 = Path(a & b | c & d )
1863 self.assertEqual(p5.dumpPython(),"cms.Path((process.a&process.b)|(process.c&process.d))\n")
1864 l[:]=[]
1865 p5.visit(namesVisitor)
1866 self.assertEqual(l,['|','&','a','b','@','&','c','d','@','@'])
1867 p5 = Path(a & (b | c) & d )
1868 self.assertEqual(p5.dumpPython(),"cms.Path(process.a&(process.b|process.c)&process.d)\n")
1869 l[:]=[]
1870 p5.visit(namesVisitor)
1871 self.assertEqual(l,['&','a','|','b','c','@','d','@'])
1872 p5 = Path(a & b & c | d )
1873 self.assertEqual(p5.dumpPython(),"cms.Path((process.a&process.b&process.c)|process.d)\n")
1874 l[:]=[]
1875 p5.visit(namesVisitor)
1876 self.assertEqual(l,['|','&','a','b','c','@','d','@'])
1877 p6 = Path( a & ~b)
1878 self.assertEqual(p6.dumpPython(),"cms.Path(process.a&(~process.b))\n")
1879 l[:]=[]
1880 p6.visit(namesVisitor)
1881 self.assertEqual(l,['&','a','!b','@'])
1882 p6 = Path( a & ignore(b))
1883 self.assertEqual(p6.dumpPython(),"cms.Path(process.a&(cms.ignore(process.b)))\n")
1884 l[:]=[]
1885 p6.visit(namesVisitor)
1886 self.assertEqual(l,['&','a','-b','@'])
1887 p6 = Path( a & wait(b))
1888 self.assertEqual(p6.dumpPython(),"cms.Path(process.a&(cms.wait(process.b)))\n")
1889 l[:]=[]
1890 p6.visit(namesVisitor)
1891 self.assertEqual(l,['&','a','|b','@'])
1892 p6 = Path( a & wait(ignore(b)))
1893 self.assertEqual(p6.dumpPython(),"cms.Path(process.a&(cms.wait(cms.ignore(process.b))))\n")
1894 l[:]=[]
1895 p6.visit(namesVisitor)
1896 self.assertEqual(l,['&','a','+b','@'])
1897 p6 = Path( a & ignore(wait(b)))
1898 self.assertEqual(p6.dumpPython(),"cms.Path(process.a&(cms.wait(cms.ignore(process.b))))\n")
1899 l[:]=[]
1900 p6.visit(namesVisitor)
1901 self.assertEqual(l,['&','a','+b','@'])
1902 p6 = Path(~(a&b))
1903 self.assertEqual(p6.dumpPython(),"cms.Path(~(process.a&process.b))\n")
1904 l[:]=[]
1905 p6.visit(namesVisitor)
1906 self.assertEqual(l,['!&','a','b','@'])
1907
1908 def testTaskConstructor(self):
1909 a = DummyModule("a")
1910 self.assertRaises(RuntimeError, lambda : Task(ConditionalTask(a)) )
1911
1912 def testDumpPython(self):
1913 a = DummyModule("a")
1914 b = DummyModule('b')
1915 p = Path((a*b))
1916
1917 self.assertEqual(p.dumpPython(),"cms.Path(process.a+process.b)\n")
1918 p2 = Path((b+a))
1919
1920 self.assertEqual(p2.dumpPython(),"cms.Path(process.b+process.a)\n")
1921 c = DummyModule('c')
1922 p3 = Path(c*(a+b))
1923
1924 self.assertEqual(p3.dumpPython(),"cms.Path(process.c+process.a+process.b)\n")
1925 p4 = Path(c*a+b)
1926
1927 self.assertEqual(p4.dumpPython(),"cms.Path(process.c+process.a+process.b)\n")
1928 p5 = Path(a+ignore(b))
1929
1930 self.assertEqual(p5.dumpPython(),"cms.Path(process.a+cms.ignore(process.b))\n")
1931 p5a = Path(a+wait(b))
1932 self.assertEqual(p5a.dumpPython(),"cms.Path(process.a+cms.wait(process.b))\n")
1933 p5b = Path(a+ignore(wait(b)))
1934 self.assertEqual(p5b.dumpPython(),"cms.Path(process.a+cms.wait(cms.ignore(process.b)))\n")
1935 p5c = Path(a+wait(ignore(b)))
1936 self.assertEqual(p5c.dumpPython(),"cms.Path(process.a+cms.wait(cms.ignore(process.b)))\n")
1937 p6 = Path(c+a*b)
1938
1939 self.assertEqual(p6.dumpPython(),"cms.Path(process.c+process.a+process.b)\n")
1940 p7 = Path(a+~b)
1941 self.assertEqual(p7.dumpPython(),"cms.Path(process.a+~process.b)\n")
1942 p8 = Path((a+b)*c)
1943 self.assertEqual(p8.dumpPython(),"cms.Path(process.a+process.b+process.c)\n")
1944 t1 = Task(a)
1945 t2 = Task(c, b)
1946 t3 = Task()
1947 p9 = Path((a+b)*c, t1)
1948 self.assertEqual(p9.dumpPython(),"cms.Path(process.a+process.b+process.c, cms.Task(process.a))\n")
1949 p10 = Path((a+b)*c, t2, t1)
1950 self.assertEqual(p10.dumpPython(),"cms.Path(process.a+process.b+process.c, cms.Task(process.a), cms.Task(process.b, process.c))\n")
1951 p11 = Path(t1, t2, t3)
1952 self.assertEqual(p11.dumpPython(),"cms.Path(cms.Task(), cms.Task(process.a), cms.Task(process.b, process.c))\n")
1953 d = DummyModule("d")
1954 e = DummyModule('e')
1955 f = DummyModule('f')
1956 t4 = Task(d, Task(f))
1957 s = Sequence(e, t4)
1958 p12 = Path(a+b+s+c,t1)
1959 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")
1960 ct1 = ConditionalTask(a)
1961 ct2 = ConditionalTask(c, b)
1962 ct3 = ConditionalTask()
1963 p13 = Path((a+b)*c, ct1)
1964 self.assertEqual(p13.dumpPython(),"cms.Path(process.a+process.b+process.c, cms.ConditionalTask(process.a))\n")
1965 p14 = Path((a+b)*c, ct2, ct1)
1966 self.assertEqual(p14.dumpPython(),"cms.Path(process.a+process.b+process.c, cms.ConditionalTask(process.a), cms.ConditionalTask(process.b, process.c))\n")
1967 p15 = Path(ct1, ct2, ct3)
1968 self.assertEqual(p15.dumpPython(),"cms.Path(cms.ConditionalTask(), cms.ConditionalTask(process.a), cms.ConditionalTask(process.b, process.c))\n")
1969 ct4 = ConditionalTask(d, Task(f))
1970 s = Sequence(e, ct4)
1971 p16 = Path(a+b+s+c,ct1)
1972 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")
1973
1974 n = 260
1975 mods = []
1976 labels = []
1977 for i in range(0, n):
1978 l = "a{}".format(i)
1979 labels.append("process."+l)
1980 mods.append(DummyModule(l))
1981 labels.sort()
1982 task = Task(*mods)
1983 self.assertEqual(task.dumpPython(), "cms.Task(*[" + ", ".join(labels) + "])\n")
1984 conditionalTask = ConditionalTask(*mods)
1985 self.assertEqual(conditionalTask.dumpPython(), "cms.ConditionalTask(*[" + ", ".join(labels) + "])\n")
1986
1987 l = list()
1988 namesVisitor = DecoratedNodeNameVisitor(l)
1989 p.visit(namesVisitor)
1990 self.assertEqual(l, ['a', 'b'])
1991 l[:] = []
1992 p5.visit(namesVisitor)
1993 self.assertEqual(l, ['a', '-b'])
1994 l[:] = []
1995 p5a.visit(namesVisitor)
1996 self.assertEqual(l, ['a', '|b'])
1997 l[:] = []
1998 p5b.visit(namesVisitor)
1999 self.assertEqual(l, ['a', '+b'])
2000 l[:] = []
2001 p5c.visit(namesVisitor)
2002 self.assertEqual(l, ['a', '+b'])
2003 l[:] = []
2004 p7.visit(namesVisitor)
2005 self.assertEqual(l, ['a', '!b'])
2006 l[:] = []
2007 p10.visit(namesVisitor)
2008 self.assertEqual(l, ['a', 'b', 'c'])
2009 l[:] = []
2010 p12.visit(namesVisitor)
2011 self.assertEqual(l, ['a', 'b', 'e', 'c'])
2012 l[:] = []
2013 p16.visit(namesVisitor)
2014 self.assertEqual(l, ['a', 'b', 'e', 'c'])
2015 l[:] = []
2016 moduleVisitor = ModuleNodeVisitor(l)
2017 p8.visit(moduleVisitor)
2018 names = [m.label_() for m in l]
2019 self.assertEqual(names, ['a', 'b', 'c'])
2020 tph = TaskPlaceholder('a')
2021 self.assertEqual(tph.dumpPython(), 'cms.TaskPlaceholder("process.a")\n')
2022 sph = SequencePlaceholder('a')
2023 self.assertEqual(sph.dumpPython(), 'cms.SequencePlaceholder("process.a")\n')
2024 ctph = ConditionalTaskPlaceholder('a')
2025 self.assertEqual(ctph.dumpPython(), 'cms.ConditionalTaskPlaceholder("process.a")\n')
2026
2027 def testDumpConfig(self):
2028 a = DummyModule("a")
2029 b = DummyModule('b')
2030 p = Path((a*b))
2031
2032 self.assertEqual(p.dumpConfig(None),"{a&b}\n")
2033 p2 = Path((b+a))
2034
2035 self.assertEqual(p2.dumpConfig(None),"{b&a}\n")
2036 c = DummyModule('c')
2037 p3 = Path(c*(a+b))
2038
2039 self.assertEqual(p3.dumpConfig(None),"{c&a&b}\n")
2040 p4 = Path(c*a+b)
2041
2042 self.assertEqual(p4.dumpConfig(None),"{c&a&b}\n")
2043 p5 = Path(a+ignore(b))
2044
2045 self.assertEqual(p5.dumpConfig(None),"{a&-b}\n")
2046 p6 = Path(c+a*b)
2047
2048 self.assertEqual(p6.dumpConfig(None),"{c&a&b}\n")
2049 p7 = Path(a+~b)
2050 self.assertEqual(p7.dumpConfig(None),"{a&!b}\n")
2051 p8 = Path((a+b)*c)
2052 self.assertEqual(p8.dumpConfig(None),"{a&b&c}\n")
2053 def testVisitor(self):
2054 class TestVisitor(object):
2055 def __init__(self, enters, leaves):
2056 self._enters = enters
2057 self._leaves = leaves
2058 def enter(self,visitee):
2059
2060 if self._enters[0] != visitee:
2061 raise RuntimeError("wrong node ("+str(visitee)+") on 'enter'")
2062 else:
2063 self._enters = self._enters[1:]
2064 def leave(self,visitee):
2065 if self._leaves[0] != visitee:
2066 raise RuntimeError("wrong node ("+str(visitee)+") on 'leave'\n expected ("+str(self._leaves[0])+")")
2067 else:
2068 self._leaves = self._leaves[1:]
2069 a = DummyModule("a")
2070 b = DummyModule('b')
2071 multAB = a*b
2072 p = Path(multAB)
2073 t = TestVisitor(enters=[a,b],
2074 leaves=[a,b])
2075 p.visit(t)
2076
2077 plusAB = a+b
2078 p = Path(plusAB)
2079 t = TestVisitor(enters=[a,b],
2080 leaves=[a,b])
2081 p.visit(t)
2082
2083 c=DummyModule("c")
2084 d=DummyModule("d")
2085 e=DummyModule("e")
2086 f=DummyModule("f")
2087 g=DummyModule("g")
2088 ct1 = ConditionalTask(d)
2089 ct2 = ConditionalTask(e, ct1)
2090 ct3 = ConditionalTask(f, g, ct2)
2091 s=Sequence(plusAB, ct3, ct2)
2092 multSC = s*c
2093 p=Path(multSC, ct1, ct2)
2094 l = []
2095 v = ModuleNodeVisitor(l)
2096 p.visit(v)
2097 expected = [a,b,f,g,e,d,e,d,c,d,e,d]
2098 self.assertEqual(expected,l)
2099
2100
2101 t1 = Task(d)
2102 t2 = Task(e, t1)
2103 t3 = Task(f, g, t2)
2104 s=Sequence(plusAB, t3, t2)
2105 multSC = s*c
2106 p=Path(multSC, t1, t2)
2107
2108 l = []
2109 v = ModuleNodeVisitor(l)
2110 p.visit(v)
2111 expected = [a,b,f,g,e,d,e,d,c,d,e,d]
2112 self.assertEqual(expected,l)
2113
2114 l[:] = []
2115 v = ModuleNodeOnTaskVisitor(l)
2116 p.visit(v)
2117 expected = [f,g,e,d,e,d,d,e,d]
2118 self.assertEqual(expected,l)
2119
2120 l[:] = []
2121 v = ModuleNodeNotOnTaskVisitor(l)
2122 p.visit(v)
2123 expected = [a,b,c]
2124 self.assertEqual(expected,l)
2125
2126
2127 t=TestVisitor(enters=[s,a,b,t3,f,g,t2,e,t1,d,t2,e,t1,d,c,t1,d,t2,e,t1,d],
2128 leaves=[a,b,f,g,e,d,t1,t2,t3,e,d,t1,t2,s,c,d,t1,e,d,t1,t2])
2129 p.visit(t)
2130
2131 notA= ~a
2132 p=Path(notA)
2133 t=TestVisitor(enters=[notA,a],leaves=[a,notA])
2134 p.visit(t)
2135 def testResolve(self):
2136 m1 = DummyModule("m1")
2137 m2 = DummyModule("m2")
2138 s1 = Sequence(m1)
2139 s2 = SequencePlaceholder("s3")
2140 s3 = Sequence(m2)
2141 p = Path(s1*s2)
2142 l = list()
2143
2144
2145 namesVisitor = DecoratedNodeNameVisitor(l)
2146 p.visit(namesVisitor)
2147 self.assertEqual(l, ['m1'])
2148 p.resolve(dict(s1=s1, s2=s2, s3=s3))
2149 l[:] = []
2150 p.visit(namesVisitor)
2151 self.assertEqual(l, ['m1', 'm2'])
2152 l[:]=[]
2153 s1 = Sequence(m1)
2154 s2 = SequencePlaceholder("s3")
2155 s3 = Sequence(m2)
2156 s4 = SequencePlaceholder("s2")
2157 p=Path(s1+s4)
2158 p.resolve(dict(s1=s1, s2=s2, s3=s3, s4=s4))
2159 p.visit(namesVisitor)
2160 self.assertEqual(l, ['m1', 'm2'])
2161 l[:]=[]
2162 m3 = DummyModule("m3")
2163 m4 = DummyModule("m4")
2164 s1 = Sequence(~m1)
2165 s2 = SequencePlaceholder("s3")
2166 s3 = Sequence(ignore(m2))
2167 s4 = Sequence(wait(m3) + ignore(wait(m4)))
2168 d = dict(s1=s1, s2=s2, s3=s3, s4=s4)
2169 p = Path(s1*s2*s4)
2170 p.resolve(dict(s1=s1, s2=s2, s3=s3, s4=s4))
2171 p.visit(namesVisitor)
2172 self.assertEqual(l, ['!m1', '-m2', '|m3', '+m4'])
2173 def testReplace(self):
2174 m1 = DummyModule("m1")
2175 m2 = DummyModule("m2")
2176 m3 = DummyModule("m3")
2177 m4 = DummyModule("m4")
2178 m5 = DummyModule("m5")
2179
2180 s1 = Sequence(m1*~m2*m1*m2*ignore(m2))
2181 s2 = Sequence(m1*m2)
2182 l = []
2183 namesVisitor = DecoratedNodeNameVisitor(l)
2184 s1.visit(namesVisitor)
2185 self.assertEqual(l,['m1', '!m2', 'm1', 'm2', '-m2'])
2186
2187 s3 = Sequence(~m1*s2)
2188 s3.replace(~m1, m2)
2189 l[:] = []
2190 s3.visit(namesVisitor)
2191 self.assertEqual(l, ['m2', 'm1', 'm2'])
2192 s3.replace(m2, ~m1)
2193 l[:] = []
2194 s3.visit(namesVisitor)
2195 self.assertEqual(l, ['!m1', 'm1', '!m1'])
2196
2197 s3 = Sequence(ignore(m1)*s2)
2198 s3.replace(ignore(m1), m2)
2199 l[:] = []
2200 s3.visit(namesVisitor)
2201 self.assertEqual(l, ['m2', 'm1', 'm2'])
2202 s3.replace(m2, ignore(m1))
2203 l[:] = []
2204 s3.visit(namesVisitor)
2205 self.assertEqual(l, ['-m1', 'm1', '-m1'])
2206
2207 ph = SequencePlaceholder('x')
2208 s4 = Sequence(Sequence(ph))
2209 s4.replace(ph,m2)
2210 self.assertEqual(s4.dumpPython(), "cms.Sequence(process.m2)\n")
2211
2212 s1.replace(m2,m3)
2213 l[:] = []
2214 s1.visit(namesVisitor)
2215 self.assertEqual(l,['m1', '!m3', 'm1', 'm3', '-m3'])
2216 s2 = Sequence(m1*m2)
2217 s3 = Sequence(~m1*s2)
2218 l[:] = []
2219 s3.visit(namesVisitor)
2220 self.assertEqual(l,['!m1', 'm1', 'm2'])
2221 l[:] = []
2222 s3.replace(s2,m1)
2223 s3.visit(namesVisitor)
2224 self.assertEqual(l,['!m1', 'm1'])
2225
2226 s1 = Sequence(m1+m2)
2227 s2 = Sequence(m3+m4)
2228 s3 = Sequence(s1+s2)
2229 s3.replace(m3,m5)
2230 l[:] = []
2231 s3.visit(namesVisitor)
2232 self.assertEqual(l,['m1','m2','m5','m4'])
2233
2234 m6 = DummyModule("m6")
2235 m7 = DummyModule("m7")
2236 m8 = DummyModule("m8")
2237 m9 = DummyModule("m9")
2238
2239
2240 t6 = Task(m6)
2241 t7 = Task(m7)
2242 t89 = Task(m8, m9)
2243
2244 s1 = Sequence(m1+m2, t6)
2245 s2 = Sequence(m3+m4, t7)
2246 s3 = Sequence(s1+s2, t89)
2247 s3.replace(m3,m5)
2248 l[:] = []
2249 s3.visit(namesVisitor)
2250 self.assertEqual(l,['m1','m2','m5','m4'])
2251
2252 s3.replace(m8,m1)
2253 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")
2254
2255 s3.replace(m1,m7)
2256 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")
2257 result = s3.replace(t7, t89)
2258 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")
2259 self.assertTrue(result)
2260 result = s3.replace(t7, t89)
2261 self.assertFalse(result)
2262
2263 t1 = Task()
2264 t1.replace(m1,m2)
2265 self.assertTrue(t1.dumpPython() == "cms.Task()\n")
2266
2267 t1 = Task(m1)
2268 t1.replace(m1,m2)
2269 self.assertTrue(t1.dumpPython() == "cms.Task(process.m2)\n")
2270
2271 t1 = Task(m1,m2, m2)
2272 t1.replace(m2,m3)
2273 self.assertTrue(t1.dumpPython() == "cms.Task(process.m1, process.m3)\n")
2274
2275 t1 = Task(m1,m2)
2276 t2 = Task(m1,m3,t1)
2277 t2.replace(m1,m4)
2278 self.assertTrue(t2.dumpPython() == "cms.Task(process.m2, process.m3, process.m4)\n")
2279
2280 t1 = Task(m2)
2281 t2 = Task(m1,m3,t1)
2282 t2.replace(m1,m4)
2283 self.assertTrue(t2.dumpPython() == "cms.Task(process.m2, process.m3, process.m4)\n")
2284
2285 t1 = Task(m2)
2286 t2 = Task(m1,m3,t1)
2287 t2.replace(t1,m4)
2288 self.assertTrue(t2.dumpPython() == "cms.Task(process.m1, process.m3, process.m4)\n")
2289
2290 t1 = Task(m2)
2291 t2 = Task(m1,m3,t1)
2292 t3 = Task(m5)
2293 t2.replace(m2,t3)
2294 self.assertTrue(t2.dumpPython() == "cms.Task(process.m1, process.m3, process.m5)\n")
2295
2296
2297 ct6 = ConditionalTask(m6)
2298 ct7 = ConditionalTask(m7)
2299 ct89 = ConditionalTask(m8, m9)
2300
2301 cs1 = Sequence(m1+m2, ct6)
2302 cs2 = Sequence(m3+m4, ct7)
2303 cs3 = Sequence(cs1+cs2, ct89)
2304 cs3.replace(m3,m5)
2305 l[:] = []
2306 cs3.visit(namesVisitor)
2307 self.assertEqual(l,['m1','m2','m5','m4'])
2308
2309 cs3.replace(m8,m1)
2310 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")
2311
2312 cs3.replace(m1,m7)
2313 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")
2314 result = cs3.replace(ct7, ct89)
2315 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")
2316 self.assertTrue(result)
2317 result = cs3.replace(ct7, ct89)
2318 self.assertFalse(result)
2319
2320 ct1 = ConditionalTask()
2321 ct1.replace(m1,m2)
2322 self.assertEqual(ct1.dumpPython(), "cms.ConditionalTask()\n")
2323
2324 ct1 = ConditionalTask(m1)
2325 ct1.replace(m1,m2)
2326 self.assertEqual(ct1.dumpPython(), "cms.ConditionalTask(process.m2)\n")
2327
2328 ct1 = ConditionalTask(m1,m2, m2)
2329 ct1.replace(m2,m3)
2330 self.assertEqual(ct1.dumpPython(), "cms.ConditionalTask(process.m1, process.m3)\n")
2331
2332 ct1 = ConditionalTask(m1,m2)
2333 ct2 = ConditionalTask(m1,m3,ct1)
2334 ct2.replace(m1,m4)
2335 self.assertEqual(ct2.dumpPython(), "cms.ConditionalTask(process.m2, process.m3, process.m4)\n")
2336
2337 ct1 = ConditionalTask(m2)
2338 ct2 = ConditionalTask(m1,m3,ct1)
2339 ct2.replace(m1,m4)
2340 self.assertEqual(ct2.dumpPython(), "cms.ConditionalTask(process.m2, process.m3, process.m4)\n")
2341
2342 ct1 = ConditionalTask(m2)
2343 ct2 = ConditionalTask(m1,m3,ct1)
2344 ct2.replace(ct1,m4)
2345 self.assertEqual(ct2.dumpPython(), "cms.ConditionalTask(process.m1, process.m3, process.m4)\n")
2346
2347 ct1 = ConditionalTask(m2)
2348 ct2 = ConditionalTask(m1,m3,ct1)
2349 ct3 = ConditionalTask(m5)
2350 ct2.replace(m2,ct3)
2351 self.assertEqual(ct2.dumpPython(), "cms.ConditionalTask(process.m1, process.m3, process.m5)\n")
2352
2353
2354 fp = FinalPath()
2355 fp.replace(m1,m2)
2356 self.assertEqual(fp.dumpPython(), "cms.FinalPath()\n")
2357 fp = FinalPath(m1)
2358 fp.replace(m1,m2)
2359 self.assertEqual(fp.dumpPython(), "cms.FinalPath(process.m2)\n")
2360
2361 def testReplaceIfHeldDirectly(self):
2362 m1 = DummyModule("m1")
2363 m2 = DummyModule("m2")
2364 m3 = DummyModule("m3")
2365 m4 = DummyModule("m4")
2366 m5 = DummyModule("m5")
2367
2368 s1 = Sequence(m1*~m2*m1*m2*ignore(m2))
2369 s1._replaceIfHeldDirectly(m2,m3)
2370 self.assertEqual(s1.dumpPython()[:-1],
2371 "cms.Sequence(process.m1+~process.m3+process.m1+process.m3+cms.ignore(process.m3))")
2372
2373 s2 = Sequence(m1*m2)
2374 l = []
2375 s3 = Sequence(~m1*s2)
2376 s3._replaceIfHeldDirectly(~m1, m2)
2377 self.assertEqual(s3.dumpPython()[:-1],
2378 "cms.Sequence(process.m2+(process.m1+process.m2))")
2379
2380 m6 = DummyModule("m6")
2381 m7 = DummyModule("m7")
2382 m8 = DummyModule("m8")
2383 m9 = DummyModule("m9")
2384 t6 = Task(m6)
2385 t7 = Task(m7)
2386 t89 = Task(m8, m9)
2387
2388 s1 = Sequence(m1+m2, t6)
2389 s2 = Sequence(m3+m4, t7)
2390 s3 = Sequence(s1+s2, t89)
2391 s3._replaceIfHeldDirectly(m3,m5)
2392 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))")
2393 s2._replaceIfHeldDirectly(m3,m5)
2394 self.assertEqual(s2.dumpPython()[:-1],"cms.Sequence(process.m5+process.m4, cms.Task(process.m7))")
2395 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))")
2396
2397 s1 = Sequence(t6)
2398 s1._replaceIfHeldDirectly(t6,t7)
2399 self.assertEqual(s1.dumpPython()[:-1],"cms.Sequence(cms.Task(process.m7))")
2400
2401
2402 ct6 = ConditionalTask(m6)
2403 ct7 = ConditionalTask(m7)
2404 ct89 = ConditionalTask(m8, m9)
2405
2406 s1 = Sequence(m1+m2, ct6)
2407 s2 = Sequence(m3+m4, ct7)
2408 s3 = Sequence(s1+s2, ct89)
2409 s3._replaceIfHeldDirectly(m3,m5)
2410 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))")
2411 s2._replaceIfHeldDirectly(m3,m5)
2412 self.assertEqual(s2.dumpPython()[:-1],"cms.Sequence(process.m5+process.m4, cms.ConditionalTask(process.m7))")
2413 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))")
2414
2415 s1 = Sequence(ct6)
2416 s1._replaceIfHeldDirectly(ct6,ct7)
2417 self.assertEqual(s1.dumpPython()[:-1],"cms.Sequence(cms.ConditionalTask(process.m7))")
2418 def testIndex(self):
2419 m1 = DummyModule("a")
2420 m2 = DummyModule("b")
2421 m3 = DummyModule("c")
2422
2423 s = Sequence(m1+m2+m3)
2424 self.assertEqual(s.index(m1),0)
2425 self.assertEqual(s.index(m2),1)
2426 self.assertEqual(s.index(m3),2)
2427
2428 def testInsert(self):
2429 m1 = DummyModule("a")
2430 m2 = DummyModule("b")
2431 m3 = DummyModule("c")
2432 s = Sequence(m1+m3)
2433 s.insert(1,m2)
2434 self.assertEqual(s.index(m1),0)
2435 self.assertEqual(s.index(m2),1)
2436 self.assertEqual(s.index(m3),2)
2437
2438 s = Sequence()
2439 s.insert(0, m1)
2440 self.assertEqual(s.index(m1),0)
2441
2442 p = Path()
2443 p.insert(0, m1)
2444 self.assertEqual(s.index(m1),0)
2445
2446 def testExpandAndClone(self):
2447 m1 = DummyModule("m1")
2448 m2 = DummyModule("m2")
2449 m3 = DummyModule("m3")
2450 m4 = DummyModule("m4")
2451 m5 = DummyModule("m5")
2452
2453 s1 = Sequence(m1*~m2*m1*m2*ignore(m2))
2454 s2 = Sequence(m1*m2)
2455 s3 = Sequence(~m1*s2)
2456
2457 p = Path(s1+s3)
2458 p2 = p.expandAndClone()
2459 l = []
2460 namesVisitor = DecoratedNodeNameVisitor(l)
2461 p2.visit(namesVisitor)
2462 self.assertEqual(l, ['m1', '!m2', 'm1', 'm2', '-m2', '!m1', 'm1', 'm2'])
2463
2464
2465 m6 = DummyModule("m6")
2466 m7 = DummyModule("m7")
2467 m8 = DummyModule("m8")
2468 m9 = DummyModule("m9")
2469 p = Path(s1+s3, Task(m6))
2470 p2 = p.expandAndClone()
2471 l[:] = []
2472 p2.visit(namesVisitor)
2473 self.assertEqual(l, ['m1', '!m2', 'm1', 'm2', '-m2', '!m1', 'm1', 'm2'])
2474 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")
2475
2476 s2 = Sequence(m1*m2, Task(m9))
2477 s3 = Sequence(~m1*s2)
2478 t8 = Task(m8)
2479 t8.setLabel("t8")
2480 p = Path(s1+s3, Task(m6, Task(m7, t8)))
2481 p2 = p.expandAndClone()
2482 l[:] = []
2483 p2.visit(namesVisitor)
2484 self.assertEqual(l, ['m1', '!m2', 'm1', 'm2', '-m2', '!m1', 'm1', 'm2'])
2485 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")
2486
2487 t1 = Task(m1,m2,m3)
2488 s1 = Sequence(t1)
2489 s2 = s1.expandAndClone()
2490 l[:] = []
2491 s2.visit(namesVisitor)
2492 self.assertEqual(l, [])
2493 self.assertTrue(s2.dumpPython() == "cms.Sequence(cms.Task(process.m1, process.m2, process.m3))\n")
2494
2495 t1 = Task(m1,m2)
2496 t2 = Task(m1,m3,t1)
2497 t3 = t2.expandAndClone()
2498 self.assertTrue(t3.dumpPython() == "cms.Task(process.m1, process.m2, process.m3)\n")
2499 t4 = Task()
2500 t5 = t4.expandAndClone()
2501 self.assertTrue(t5.dumpPython() == "cms.Task()\n")
2502
2503 s1 = Sequence(m1*~m2*m1*m2*ignore(m2))
2504 s2 = Sequence(m1*m2)
2505 s3 = Sequence(~m1*s2)
2506 p = Path(s1+s3, ConditionalTask(m6))
2507 p2 = p.expandAndClone()
2508 l[:] = []
2509 p2.visit(namesVisitor)
2510 self.assertEqual(l, ['m1', '!m2', 'm1', 'm2', '-m2', '!m1', 'm1', 'm2'])
2511 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")
2512
2513 s2 = Sequence(m1*m2, ConditionalTask(m9))
2514 s3 = Sequence(~m1*s2)
2515 ct8 = ConditionalTask(m8)
2516 ct8.setLabel("ct8")
2517 p = Path(s1+s3, ConditionalTask(m6, ConditionalTask(m7, ct8)))
2518 p2 = p.expandAndClone()
2519 l[:] = []
2520 p2.visit(namesVisitor)
2521 self.assertEqual(l, ['m1', '!m2', 'm1', 'm2', '-m2', '!m1', 'm1', 'm2'])
2522 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")
2523
2524 t1 = ConditionalTask(m1,m2,m3)
2525 s1 = Sequence(t1)
2526 s2 = s1.expandAndClone()
2527 l[:] = []
2528 s2.visit(namesVisitor)
2529 self.assertEqual(l, [])
2530 self.assertEqual(s2.dumpPython(), "cms.Sequence(cms.ConditionalTask(process.m1, process.m2, process.m3))\n")
2531
2532 t1 = ConditionalTask(m1,m2)
2533 t2 = ConditionalTask(m1,m3,t1)
2534 t3 = t2.expandAndClone()
2535 self.assertEqual(t3.dumpPython(), "cms.ConditionalTask(process.m1, process.m2, process.m3)\n")
2536 t4 = ConditionalTask()
2537 t5 = t4.expandAndClone()
2538 self.assertTrue(t5.dumpPython() == "cms.ConditionalTask()\n")
2539
2540 def testAdd(self):
2541 m1 = DummyModule("m1")
2542 m2 = DummyModule("m2")
2543 m3 = DummyModule("m3")
2544 m4 = DummyModule("m4")
2545 s1 = Sequence(m1)
2546 s3 = Sequence(m3+ignore(m4))
2547 p = Path(s1)
2548 p += ~m2
2549 p *= s3
2550
2551 l = []
2552 namesVisitor = DecoratedNodeNameVisitor(l)
2553 p.visit(namesVisitor)
2554 self.assertEqual(l, ['m1', '!m2', 'm3', '-m4'])
2555
2556 s4 = Sequence()
2557 s4 +=m1
2558 l[:]=[]; s1.visit(namesVisitor); self.assertEqual(l,['m1'])
2559 self.assertEqual(s4.dumpPython(),"cms.Sequence(process.m1)\n")
2560 s4 = Sequence()
2561 s4 *=m1
2562 l[:]=[]; s1.visit(namesVisitor); self.assertEqual(l,['m1'])
2563 self.assertEqual(s4.dumpPython(),"cms.Sequence(process.m1)\n")
2564
2565
2566 def testRemove(self):
2567 m1 = DummyModule("m1")
2568 m2 = DummyModule("m2")
2569 m3 = DummyModule("m3")
2570 m4 = DummyModule("m4")
2571 s1 = Sequence(m1*m2+~m3)
2572 s2 = Sequence(m1*s1)
2573 l = []
2574 namesVisitor = DecoratedNodeNameVisitor(l)
2575 d = {'m1':m1 ,'m2':m2, 'm3':m3,'s1':s1, 's2':s2}
2576 l[:] = []; s1.visit(namesVisitor); self.assertEqual(l,['m1', 'm2', '!m3'])
2577 l[:] = []; s2.visit(namesVisitor); self.assertEqual(l,['m1', 'm1', 'm2', '!m3'])
2578 s1.remove(m2)
2579 l[:] = []; s1.visit(namesVisitor); self.assertEqual(l,['m1', '!m3'])
2580 l[:] = []; s2.visit(namesVisitor); self.assertEqual(l,['m1', 'm1', '!m3'])
2581 s2.remove(m3)
2582 l[:] = []; s1.visit(namesVisitor); self.assertEqual(l,['m1', '!m3'])
2583 l[:] = []; s2.visit(namesVisitor); self.assertEqual(l,['m1', 'm1'])
2584 s1 = Sequence( m1 + m2 + m1 + m2 )
2585 l[:] = []; s1.visit(namesVisitor); self.assertEqual(l,['m1', 'm2', 'm1', 'm2'])
2586 s1.remove(m2)
2587 l[:] = []; s1.visit(namesVisitor); self.assertEqual(l,['m1', 'm1', 'm2'])
2588 s1 = Sequence( m1 + m3 )
2589 s2 = Sequence( m2 + ignore(m3) + s1 + m3 )
2590 l[:] = []; s2.visit(namesVisitor); self.assertEqual(l,['m2', '-m3', 'm1', 'm3', 'm3'])
2591 s2.remove(s1)
2592 l[:] = []; s2.visit(namesVisitor); self.assertEqual(l,['m2', '-m3', 'm3'])
2593 s2.remove(m3)
2594 l[:] = []; s2.visit(namesVisitor); self.assertEqual(l,['m2','m3'])
2595 s1 = Sequence(m1*m2*m3)
2596 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2+process.m3)\n")
2597 s1.remove(m2)
2598 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m3)\n")
2599 s1 = Sequence(m1+m2+m3)
2600 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2+process.m3)\n")
2601 s1.remove(m2)
2602 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m3)\n")
2603 s1 = Sequence(m1*m2+m3)
2604 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2+process.m3)\n")
2605 s1.remove(m2)
2606 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m3)\n")
2607 s1 = Sequence(m1+m2*m3)
2608 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2+process.m3)\n")
2609 s1.remove(m2)
2610 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m3)\n")
2611 s1.remove(m1)
2612 s1.remove(m3)
2613 l[:]=[]; s1.visit(namesVisitor); self.assertEqual(l,[])
2614 self.assertEqual(s1.dumpPython(), "cms.Sequence()\n")
2615 s3 = Sequence(m1)
2616 s3.remove(m1)
2617 l[:]=[]; s3.visit(namesVisitor); self.assertEqual(l,[])
2618 self.assertEqual(s3.dumpPython(), "cms.Sequence()\n")
2619 s3 = Sequence(m1)
2620 s4 = Sequence(s3)
2621 s4.remove(m1)
2622 l[:]=[]; s4.visit(namesVisitor); self.assertEqual(l,[])
2623 self.assertEqual(s4.dumpPython(), "cms.Sequence()\n")
2624
2625 s1 = Sequence(m1+m2, Task(m3), Task(m4))
2626 s1.remove(m4)
2627 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2, cms.Task(process.m3))\n")
2628 s1 = Sequence(m1+m2+Sequence(Task(m3,m4), Task(m3), Task(m4)))
2629 s1.remove(m4)
2630 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2, cms.Task(process.m3), cms.Task(process.m4))\n")
2631 t1 = Task(m1)
2632 t1.setLabel("t1")
2633 t2 = Task(m2,t1)
2634 t2.setLabel("t2")
2635 t3 = Task(t1,t2,m1)
2636 t3.remove(m1)
2637 self.assertTrue(t3.dumpPython() == "cms.Task(process.m1, process.t2)\n")
2638 t3.remove(m1)
2639 self.assertTrue(t3.dumpPython() == "cms.Task(process.m1, process.m2)\n")
2640 t3.remove(m1)
2641 self.assertTrue(t3.dumpPython() == "cms.Task(process.m2)\n")
2642 t3.remove(m2)
2643 self.assertTrue(t3.dumpPython() == "cms.Task()\n")
2644
2645 s1 = Sequence(m1+m2, ConditionalTask(m3), ConditionalTask(m4))
2646 s1.remove(m4)
2647 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2, cms.ConditionalTask(process.m3))\n")
2648 s1 = Sequence(m1+m2+Sequence(ConditionalTask(m3,m4), ConditionalTask(m3), ConditionalTask(m4)))
2649 s1.remove(m4)
2650 self.assertEqual(s1.dumpPython(), "cms.Sequence(process.m1+process.m2, cms.ConditionalTask(process.m3), cms.ConditionalTask(process.m4))\n")
2651 t1 = ConditionalTask(m1)
2652 t1.setLabel("t1")
2653 t2 = ConditionalTask(m2,t1)
2654 t2.setLabel("t2")
2655 t3 = ConditionalTask(t1,t2,m1)
2656 t3.remove(m1)
2657 self.assertEqual(t3.dumpPython(), "cms.ConditionalTask(process.m1, process.t2)\n")
2658 t3.remove(m1)
2659 self.assertEqual(t3.dumpPython(), "cms.ConditionalTask(process.m1, process.m2)\n")
2660 t3.remove(m1)
2661 self.assertEqual(t3.dumpPython(), "cms.ConditionalTask(process.m2)\n")
2662 t3.remove(m2)
2663 self.assertEqual(t3.dumpPython(), "cms.ConditionalTask()\n")
2664
2665 fp = FinalPath(m1+m2)
2666 fp.remove(m1)
2667 self.assertEqual(fp.dumpPython(), "cms.FinalPath(process.m2)\n")
2668 fp = FinalPath(m1)
2669 fp.remove(m1)
2670 self.assertEqual(fp.dumpPython(), "cms.FinalPath()\n")
2671
2672 def testCopyAndExclude(self):
2673 a = DummyModule("a")
2674 b = DummyModule("b")
2675 c = DummyModule("c")
2676 d = DummyModule("d")
2677 s = Sequence(a+b+c)
2678 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+process.b+process.c)\n")
2679 s = Sequence(a+b+c+d)
2680 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2681 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2682 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+process.b+process.d)\n")
2683 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+process.b+process.c)\n")
2684 s=Sequence(a*b+c+d)
2685 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2686 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2687 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+process.b+process.d)\n")
2688 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+process.b+process.c)\n")
2689 s = Sequence(a+b*c+d)
2690 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2691 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2692 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+process.b+process.d)\n")
2693 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+process.b+process.c)\n")
2694 s2 = Sequence(a+b)
2695 s = Sequence(c+s2+d)
2696 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.c+process.b+process.d)\n")
2697 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.c+process.a+process.d)\n")
2698 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence((process.a+process.b)+process.d)\n")
2699 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.c+(process.a+process.b))\n")
2700 self.assertEqual(s.copyAndExclude([a,b]).dumpPython(),"cms.Sequence(process.c+process.d)\n")
2701 s3 = s.copyAndExclude([c])
2702 s2.remove(a)
2703 self.assertEqual(s3.dumpPython(),"cms.Sequence((process.b)+process.d)\n")
2704 s4 = s.copyAndExclude([a,b])
2705 seqs = []
2706 sequenceVisitor = SequenceVisitor(seqs)
2707 s.visit(sequenceVisitor)
2708 self.assertEqual(len(seqs),1)
2709 seqs[:] = []
2710 s4.visit(sequenceVisitor)
2711 self.assertEqual(len(seqs),0)
2712 self.assertEqual(s4.dumpPython(),"cms.Sequence(process.c+process.d)\n")
2713 holder = SequencePlaceholder("x")
2714 s3 = Sequence(b+d,Task(a))
2715 s2 = Sequence(a+b+holder+s3)
2716 s = Sequence(c+s2+d)
2717 seqs[:] = []
2718 s.visit(sequenceVisitor)
2719 self.assertTrue(seqs == [s2,s3])
2720 s2 = Sequence(a+b+holder)
2721 s = Sequence(c+s2+d)
2722 self.assertEqual(s.copyAndExclude([holder]).dumpPython(),"cms.Sequence(process.c+process.a+process.b+process.d)\n")
2723 s2 = Sequence(a+b+c)
2724 s = Sequence(s2+d)
2725 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2726 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2727 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+process.b+process.d)\n")
2728 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence((process.a+process.b+process.c))\n")
2729 self.assertEqual(s.copyAndExclude([s2]).dumpPython(),"cms.Sequence(process.d)\n")
2730 s2 = Sequence(a+b+c)
2731 s = Sequence(s2*d)
2732 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2733 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2734 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+process.b+process.d)\n")
2735 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence((process.a+process.b+process.c))\n")
2736 self.assertEqual(s.copyAndExclude([a,b,c]).dumpPython(),"cms.Sequence(process.d)\n")
2737 s = Sequence(ignore(a)+b+c+d)
2738 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2739 self.assertEqual(s.copyAndExclude([ignore(a)]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2740 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(cms.ignore(process.a)+process.c+process.d)\n")
2741 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(cms.ignore(process.a)+process.b+process.d)\n")
2742 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(cms.ignore(process.a)+process.b+process.c)\n")
2743 s = Sequence(a+ignore(b)+c+d)
2744 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(cms.ignore(process.b)+process.c+process.d)\n")
2745 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2746 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+cms.ignore(process.b)+process.d)\n")
2747 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+cms.ignore(process.b)+process.c)\n")
2748 s = Sequence(a+b+c+ignore(d))
2749 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+cms.ignore(process.d))\n")
2750 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+cms.ignore(process.d))\n")
2751 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+process.b+cms.ignore(process.d))\n")
2752 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+process.b+process.c)\n")
2753 s = Sequence(~a+b+c+d)
2754 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+process.d)\n")
2755 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(~process.a+process.c+process.d)\n")
2756 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(~process.a+process.b+process.d)\n")
2757 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(~process.a+process.b+process.c)\n")
2758 s = Sequence(a+~b+c+d)
2759 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(~process.b+process.c+process.d)\n")
2760 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2761 self.assertEqual(s.copyAndExclude([~b]).dumpPython(),"cms.Sequence(process.a+process.c+process.d)\n")
2762 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+~process.b+process.d)\n")
2763 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+~process.b+process.c)\n")
2764 s = Sequence(a+b+c+~d)
2765 self.assertEqual(s.copyAndExclude([a]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d)\n")
2766 self.assertEqual(s.copyAndExclude([b]).dumpPython(),"cms.Sequence(process.a+process.c+~process.d)\n")
2767 self.assertEqual(s.copyAndExclude([c]).dumpPython(),"cms.Sequence(process.a+process.b+~process.d)\n")
2768 self.assertEqual(s.copyAndExclude([d]).dumpPython(),"cms.Sequence(process.a+process.b+process.c)\n")
2769 self.assertEqual(s.copyAndExclude([a,b,c,d]).dumpPython(),"cms.Sequence()\n")
2770
2771
2772 e = DummyModule("e")
2773 f = DummyModule("f")
2774 g = DummyModule("g")
2775 h = DummyModule("h")
2776 t1 = Task(h)
2777 s = Sequence(a+b+c+~d, Task(e,f,Task(g,t1)))
2778 self.assertEqual(s.copyAndExclude([a,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.Task(process.e, process.f, process.g))\n")
2779 self.assertEqual(s.copyAndExclude([a,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.Task(process.e, process.f, process.g))\n")
2780 self.assertEqual(s.copyAndExclude([a,e,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.Task(process.f, process.g))\n")
2781 self.assertEqual(s.copyAndExclude([a,e,f,g,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d)\n")
2782 self.assertEqual(s.copyAndExclude([a,b,c,d]).dumpPython(),"cms.Sequence(cms.Task(process.e, process.f, process.g, process.h))\n")
2783 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")
2784 taskList = []
2785 taskVisitor = TaskVisitor(taskList)
2786 s.visit(taskVisitor)
2787 self.assertEqual(len(taskList),3)
2788 s2 = s.copyAndExclude([g,h])
2789 taskList[:] = []
2790 s2.visit(taskVisitor)
2791 self.assertEqual(len(taskList),1)
2792 t2 = Task(t1)
2793 taskList[:] = []
2794 t2.visit(taskVisitor)
2795 self.assertEqual(taskList[0],t1)
2796 s3 = Sequence(s)
2797 self.assertEqual(s3.copyAndExclude([a,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.Task(process.e, process.f, process.g))\n")
2798 s4 = Sequence(s)
2799 self.assertEqual(s4.copyAndExclude([a,b,c,d,e,f,g,h]).dumpPython(),"cms.Sequence()\n")
2800 t1 = Task(e,f)
2801 t11 = Task(a)
2802 t11.setLabel("t11")
2803 t2 = Task(g,t1,h,t11)
2804 t3 = t2.copyAndExclude([e,h])
2805 self.assertTrue(t3.dumpPython() == "cms.Task(process.f, process.g, process.t11)\n")
2806 t4 = t2.copyAndExclude([e,f,g,h,a])
2807 self.assertTrue(t4.dumpPython() == "cms.Task()\n")
2808
2809 t1 = ConditionalTask(h)
2810 s = Sequence(a+b+c+~d, ConditionalTask(e,f,ConditionalTask(g,t1)))
2811 self.assertEqual(s.copyAndExclude([a,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.ConditionalTask(process.e, process.f, process.g))\n")
2812 self.assertEqual(s.copyAndExclude([a,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.ConditionalTask(process.e, process.f, process.g))\n")
2813 self.assertEqual(s.copyAndExclude([a,e,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.ConditionalTask(process.f, process.g))\n")
2814 self.assertEqual(s.copyAndExclude([a,e,f,g,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d)\n")
2815 self.assertEqual(s.copyAndExclude([a,b,c,d]).dumpPython(),"cms.Sequence(cms.ConditionalTask(process.e, process.f, process.g, process.h))\n")
2816 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")
2817 taskList = []
2818 taskVisitor = ConditionalTaskVisitor(taskList)
2819 s.visit(taskVisitor)
2820 self.assertEqual(len(taskList),3)
2821 s2 = s.copyAndExclude([g,h])
2822 taskList[:] = []
2823 s2.visit(taskVisitor)
2824 self.assertEqual(len(taskList),1)
2825 t2 = ConditionalTask(t1)
2826 taskList[:] = []
2827 t2.visit(taskVisitor)
2828 self.assertEqual(taskList[0],t1)
2829 s3 = Sequence(s)
2830 self.assertEqual(s3.copyAndExclude([a,h]).dumpPython(),"cms.Sequence(process.b+process.c+~process.d, cms.ConditionalTask(process.e, process.f, process.g))\n")
2831 s4 = Sequence(s)
2832 self.assertEqual(s4.copyAndExclude([a,b,c,d,e,f,g,h]).dumpPython(),"cms.Sequence()\n")
2833 t1 = ConditionalTask(e,f)
2834 t11 = ConditionalTask(a)
2835 t11.setLabel("t11")
2836 t2 = ConditionalTask(g,t1,h,t11)
2837 t3 = t2.copyAndExclude([e,h])
2838 self.assertEqual(t3.dumpPython(), "cms.ConditionalTask(process.f, process.g, process.t11)\n")
2839 t4 = t2.copyAndExclude([e,f,g,h,a])
2840 self.assertEqual(t4.dumpPython(), "cms.ConditionalTask()\n")
2841
2842 def testSequenceTypeChecks(self):
2843 m1 = DummyModule("m1")
2844 m2 = DummyModule("m2")
2845 s1 = Sequence(m1*m2)
2846 def testRaise():
2847 s1.something = 1
2848 self.assertRaises(AttributeError,testRaise)
2849 def testRaise2():
2850 s2 = Sequence(m1*None)
2851 self.assertRaises(TypeError,testRaise2)
2852 def testCopy(self):
2853 a = DummyModule("a")
2854 b = DummyModule("b")
2855 c = DummyModule("c")
2856 p1 = Path(a+b+c)
2857 p2 = p1.copy()
2858 e = DummyModule("e")
2859 p2.replace(b,e)
2860 self.assertEqual(p1.dumpPython(),"cms.Path(process.a+process.b+process.c)\n")
2861 self.assertEqual(p2.dumpPython(),"cms.Path(process.a+process.e+process.c)\n")
2862 p1 = Path(a+b+c)
2863 p2 = p1.copy()
2864 p1 += e
2865 self.assertEqual(p1.dumpPython(),"cms.Path(process.a+process.b+process.c+process.e)\n")
2866 self.assertEqual(p2.dumpPython(),"cms.Path(process.a+process.b+process.c)\n")
2867
2868 t1 = Task(a, b)
2869 t2 = t1.copy()
2870 self.assertTrue(t1.dumpPython() == t2.dumpPython())
2871 t1Contents = list(t1._collection)
2872 t2Contents = list(t2._collection)
2873 self.assertTrue(id(t1Contents[0]) == id(t2Contents[0]))
2874 self.assertTrue(id(t1Contents[1]) == id(t2Contents[1]))
2875 self.assertTrue(id(t1._collection) != id(t2._collection))
2876
2877 t1 = ConditionalTask(a, b)
2878 t2 = t1.copy()
2879 self.assertTrue(t1.dumpPython() == t2.dumpPython())
2880 t1Contents = list(t1._collection)
2881 t2Contents = list(t2._collection)
2882 self.assertTrue(id(t1Contents[0]) == id(t2Contents[0]))
2883 self.assertTrue(id(t1Contents[1]) == id(t2Contents[1]))
2884 self.assertTrue(id(t1._collection) != id(t2._collection))
2885
2886 def testCopyAndAdd(self):
2887 a = DummyModule("a")
2888 b = DummyModule("b")
2889 c = DummyModule("c")
2890 d = DummyModule("d")
2891 e = DummyModule("e")
2892
2893 t1 = Task(a, b, c)
2894 self.assertEqual(t1.dumpPython(), "cms.Task(process.a, process.b, process.c)\n")
2895 t2 = t1.copyAndAdd(d, e)
2896 self.assertEqual(t1.dumpPython(), "cms.Task(process.a, process.b, process.c)\n")
2897 self.assertEqual(t2.dumpPython(), "cms.Task(process.a, process.b, process.c, process.d, process.e)\n")
2898 t3 = t2.copyAndExclude([b])
2899 self.assertEqual(t1.dumpPython(), "cms.Task(process.a, process.b, process.c)\n")
2900 self.assertEqual(t2.dumpPython(), "cms.Task(process.a, process.b, process.c, process.d, process.e)\n")
2901 self.assertEqual(t3.dumpPython(), "cms.Task(process.a, process.c, process.d, process.e)\n")
2902 t4 = t1.copyAndExclude([b]).copyAndAdd(d)
2903 self.assertEqual(t4.dumpPython(), "cms.Task(process.a, process.c, process.d)\n")
2904 t5 = t2.copyAndExclude([b]).copyAndAdd(d)
2905 self.assertEqual(t5.dumpPython(), "cms.Task(process.a, process.c, process.d, process.e)\n")
2906 t6 = t4.copyAndAdd(Task(b))
2907 self.assertEqual(t6.dumpPython(), "cms.Task(process.a, process.b, process.c, process.d)\n")
2908
2909 t1 = ConditionalTask(a, b, c)
2910 self.assertEqual(t1.dumpPython(), "cms.ConditionalTask(process.a, process.b, process.c)\n")
2911 t2 = t1.copyAndAdd(d, e)
2912 self.assertEqual(t1.dumpPython(), "cms.ConditionalTask(process.a, process.b, process.c)\n")
2913 self.assertEqual(t2.dumpPython(), "cms.ConditionalTask(process.a, process.b, process.c, process.d, process.e)\n")
2914 t3 = t2.copyAndExclude([b])
2915 self.assertEqual(t1.dumpPython(), "cms.ConditionalTask(process.a, process.b, process.c)\n")
2916 self.assertEqual(t2.dumpPython(), "cms.ConditionalTask(process.a, process.b, process.c, process.d, process.e)\n")
2917 self.assertEqual(t3.dumpPython(), "cms.ConditionalTask(process.a, process.c, process.d, process.e)\n")
2918 t4 = t1.copyAndExclude([b]).copyAndAdd(d)
2919 self.assertEqual(t4.dumpPython(), "cms.ConditionalTask(process.a, process.c, process.d)\n")
2920 t5 = t2.copyAndExclude([b]).copyAndAdd(d)
2921 self.assertEqual(t5.dumpPython(), "cms.ConditionalTask(process.a, process.c, process.d, process.e)\n")
2922 t6 = t4.copyAndAdd(Task(b))
2923 self.assertEqual(t6.dumpPython(), "cms.ConditionalTask(process.a, process.b, process.c, process.d)\n")
2924
2925 def testInsertInto(self):
2926 from FWCore.ParameterSet.Types import vstring
2927 class TestPSet(object):
2928 def __init__(self):
2929 self._dict = dict()
2930 def addVString(self,isTracked,label,value):
2931 self._dict[label]=value
2932 a = DummyModule("a")
2933 b = DummyModule("b")
2934 c = DummyModule("c")
2935 d = DummyModule("d")
2936 p = Path(a+b+c+d)
2937 decoratedList = []
2938 lister = DecoratedNodeNameVisitor(decoratedList)
2939 p.visit(lister)
2940 ps = TestPSet()
2941 p.insertInto(ps,"p",decoratedList)
2942 self.assertEqual(ps._dict, {"p":vstring("a","b","c","d")})
2943 s = Sequence(b+c)
2944 p = Path(a+s+d)
2945 decoratedList[:] = []
2946 p.visit(lister)
2947 ps = TestPSet()
2948 p.insertInto(ps,"p",decoratedList)
2949 self.assertEqual(ps._dict, {"p":vstring("a","b","c","d")})
2950
2951 unittest.main()