File indexing completed on 2024-04-06 12:12:53
0001 from __future__ import print_function
0002 from builtins import range, object
0003 import inspect
0004 from typing import Union
0005
0006 class _ConfigureComponent(object):
0007 """Denotes a class that can be used by the Processes class"""
0008 def _isTaskComponent(self) -> bool:
0009 return False
0010
0011 class PrintOptions(object):
0012 def __init__(self, indent:int = 0, deltaIndent:int = 4, process:bool = True, targetDirectory: Union[str, None] = None, useSubdirectories:bool = False):
0013 self.indent_= indent
0014 self.deltaIndent_ = deltaIndent
0015 self.isCfg = process
0016 self.targetDirectory = targetDirectory
0017 self.useSubdirectories = useSubdirectories
0018 def indentation(self) -> str:
0019 return ' '*self.indent_
0020 def indent(self):
0021 self.indent_ += self.deltaIndent_
0022 def unindent(self):
0023 self.indent_ -= self.deltaIndent_
0024
0025 class _SpecialImportRegistry(object):
0026 """This class collects special import statements of configuration types"""
0027 def __init__(self):
0028 self._registry = {}
0029
0030 def _reset(self):
0031 for lst in self._registry.values():
0032 lst[1] = False
0033
0034 def registerSpecialImportForType(self, cls, impStatement):
0035 className = cls.__name__
0036 if className in self._registry:
0037 raise RuntimeError("Error: the configuration type '%s' already has an import statement registered '%s'" % (className, self._registry[className][0]))
0038 self._registry[className] = [impStatement, False]
0039
0040 def registerUse(self, obj):
0041 className = obj.__class__.__name__
0042 try:
0043 self._registry[className][1] = True
0044 except KeyError:
0045 pass
0046
0047 def getSpecialImports(self):
0048 coll = set()
0049 for (imp, used) in self._registry.values():
0050 if used:
0051 coll.add(imp)
0052 return sorted(coll)
0053
0054 specialImportRegistry = _SpecialImportRegistry()
0055
0056 class _ParameterTypeBase(object):
0057 """base class for classes which are used as the 'parameters' for a ParameterSet"""
0058 def __init__(self):
0059 self.__dict__["_isFrozen"] = False
0060 self.__isTracked = True
0061 self._isModified = False
0062 def isModified(self) -> bool:
0063 return self._isModified
0064 def resetModified(self):
0065 self._isModified=False
0066 def configTypeName(self) -> str:
0067 if self.isTracked():
0068 return type(self).__name__
0069 return 'untracked '+type(self).__name__
0070 def pythonTypeName(self) -> str:
0071 if self.isTracked():
0072 return 'cms.'+type(self).__name__
0073 return 'cms.untracked.'+type(self).__name__
0074 def dumpPython(self, options:PrintOptions=PrintOptions()) -> str:
0075 specialImportRegistry.registerUse(self)
0076 return self.pythonTypeName()+"("+self.pythonValue(options)+")"
0077 def __repr__(self) -> str:
0078 return self.dumpPython()
0079 def isTracked(self) -> bool:
0080 return self.__isTracked
0081 def setIsTracked(self,trackness:bool):
0082 self.__isTracked = trackness
0083 def isFrozen(self) -> bool:
0084 return self._isFrozen
0085 def setIsFrozen(self):
0086 self._isFrozen = True
0087 def isCompatibleCMSType(self,aType) -> bool:
0088 return isinstance(self,aType)
0089 def _checkAndReturnValueWithType(self, valueWithType):
0090 if isinstance(valueWithType, type(self)):
0091 return valueWithType
0092 raise TypeError("Attempted to assign type {from_} to type {to}".format(from_ = str(type(valueWithType)), to = str(type(self))) )
0093
0094
0095 class _SimpleParameterTypeBase(_ParameterTypeBase):
0096 """base class for parameter classes which only hold a single value"""
0097 def __init__(self,value):
0098 super(_SimpleParameterTypeBase,self).__init__()
0099 self._value = value
0100 if not self._isValid(value):
0101 raise ValueError(str(value)+" is not a valid "+str(type(self)))
0102 def value(self):
0103 return self._value
0104 def setValue(self,value):
0105 if not self._isValid(value):
0106 raise ValueError(str(value)+" is not a valid "+str(type(self)))
0107 if value!=self._value:
0108 self._isModified=True
0109 self._value=value
0110 def configValue(self, options:PrintOptions=PrintOptions()) -> str:
0111 return str(self._value)
0112 def pythonValue(self, options:PrintOptions=PrintOptions()) -> str:
0113 return self.configValue(options)
0114 def __eq__(self,other) -> bool:
0115 if isinstance(other,_SimpleParameterTypeBase):
0116 return self._value == other._value
0117 return self._value == other
0118 def __ne__(self,other) -> bool:
0119 if isinstance(other,_SimpleParameterTypeBase):
0120 return self._value != other._value
0121 return self._value != other
0122 def __lt__(self,other) -> bool:
0123 if isinstance(other,_SimpleParameterTypeBase):
0124 return self._value < other._value
0125 return self._value < other
0126 def __le__(self,other) -> bool:
0127 if isinstance(other,_SimpleParameterTypeBase):
0128 return self._value <= other._value
0129 return self._value <= other
0130 def __gt__(self,other) -> bool:
0131 if isinstance(other,_SimpleParameterTypeBase):
0132 return self._value > other._value
0133 return self._value > other
0134 def __ge__(self,other) -> bool:
0135 if isinstance(other,_SimpleParameterTypeBase):
0136 return self._value >= other._value
0137 return self._value >= other
0138
0139
0140 class UsingBlock(_SimpleParameterTypeBase):
0141 """For injection purposes, pretend this is a new parameter type
0142 then have a post process step which strips these out
0143 """
0144 def __init__(self,value, s:str='', loc:int=0, file:str=''):
0145 super(UsingBlock,self).__init__(value)
0146 self.s = s
0147 self.loc = loc
0148 self.file = file
0149 self.isResolved = False
0150 @staticmethod
0151 def _isValid(value) -> bool:
0152 return isinstance(value,str)
0153 def _valueFromString(value) -> str:
0154 """only used for cfg-parsing"""
0155 return str(value)
0156 def insertInto(self, parameterSet, myname:str):
0157 value = self.value()
0158
0159
0160
0161 parameterSet.addString(self.isTracked(), myname, value)
0162 def dumpPython(self, options:PrintOptions=PrintOptions()) -> str:
0163 if options.isCfg:
0164 return "process."+self.value()
0165 else:
0166 return self.value()
0167
0168
0169 class _Parameterizable(object):
0170 """Base class for classes which allow addition of _ParameterTypeBase data"""
0171 def __init__(self,*arg,**kargs):
0172 self.__dict__['_Parameterizable__parameterNames'] = []
0173 self.__dict__["_isFrozen"] = False
0174 self.__dict__['_Parameterizable__validator'] = None
0175 """The named arguments are the 'parameters' which are added as 'python attributes' to the object"""
0176 if len(arg) != 0:
0177
0178 for block in arg:
0179
0180 if type(block).__name__ not in ["PSet", "__PSet", "dict"]:
0181 raise ValueError("Only PSets can be passed as unnamed argument blocks. This is a "+type(block).__name__)
0182 if isinstance(block,dict):
0183 kargs = block
0184 else:
0185 self.__setParameters(block.parameters_())
0186 self.__setParameters(kargs)
0187 self._isModified = False
0188
0189 def parameterNames_(self):
0190 """Returns the name of the parameters"""
0191 return self.__parameterNames[:]
0192 def isModified(self) -> bool:
0193 if self._isModified:
0194 return True
0195 for name in self.parameterNames_():
0196 param = self.__dict__[name]
0197 if isinstance(param, _Parameterizable) and param.isModified():
0198 self._isModified = True
0199 return True
0200 return False
0201
0202 def hasParameter(self, params) -> bool:
0203 """
0204 _hasParameter_
0205
0206 check that pset provided has the attribute chain
0207 specified.
0208
0209 Eg, if params is [ 'attr1', 'attr2', 'attr3' ]
0210 check for pset.attr1.attr2.attr3
0211
0212 returns True if parameter exists, False if not
0213 """
0214 return (self.getParameter(params) != None)
0215
0216 def getParameter(self, params):
0217 """
0218 _getParameter_
0219
0220 Retrieve the specified parameter from the PSet Provided
0221 given the attribute chain
0222
0223 returns None if not found
0224 """
0225 lastParam = self
0226
0227 if type(params).__name__ == 'str':
0228 return getattr(self, params, None)
0229 for param in params:
0230 lastParam = getattr(lastParam, param, None)
0231 if lastParam == None:
0232 return None
0233 return lastParam
0234
0235 def parameters_(self):
0236 """Returns a dictionary of copies of the user-set parameters"""
0237 import copy
0238 result = dict()
0239 for name in self.parameterNames_():
0240 result[name]=copy.deepcopy(self.__dict__[name])
0241 return result
0242
0243 def __addParameter(self, name:str, value):
0244 if name == 'allowAnyLabel_':
0245 self.__validator = value
0246 self._isModified = True
0247 return
0248 if not isinstance(value,_ParameterTypeBase):
0249 if self.__validator is not None:
0250 value = self.__validator.convert_(value)
0251 else:
0252 self.__raiseBadSetAttr(name)
0253 if name in self.__dict__:
0254 message = "Duplicate insert of member " + name
0255 message += "\nThe original parameters are:\n"
0256 message += self.dumpPython() + '\n'
0257 raise ValueError(message)
0258 self.__dict__[name]=value
0259 self.__parameterNames.append(name)
0260 self._isModified = True
0261
0262 def __setParameters(self,parameters):
0263 v = None
0264 for name,value in parameters.items():
0265 if name == 'allowAnyLabel_':
0266 v = value
0267 continue
0268 self.__addParameter(name, value)
0269 if v is not None:
0270 self.__validator=v
0271 def __setattr__(self,name:str,value):
0272
0273
0274 if self.isFrozen() and not (name in ["_Labelable__label","_isFrozen"] or name.startswith('_')):
0275 message = "Object already added to a process. It is read only now\n"
0276 message += " %s = %s" %(name, value)
0277 message += "\nThe original parameters are:\n"
0278 message += self.dumpPython() + '\n'
0279 raise ValueError(message)
0280
0281 if name[0]=='_':
0282 super(_Parameterizable,self).__setattr__(name,value)
0283 elif not name in self.__dict__:
0284 self.__addParameter(name, value)
0285 self._isModified = True
0286 else:
0287
0288 if isinstance(value,_ParameterTypeBase):
0289 self.__dict__[name] = self.__dict__[name]._checkAndReturnValueWithType(value)
0290 else:
0291 self.__dict__[name].setValue(value)
0292 self._isModified = True
0293
0294 def isFrozen(self) -> bool:
0295 return self._isFrozen
0296 def setIsFrozen(self):
0297 self._isFrozen = True
0298 for name in self.parameterNames_():
0299 self.__dict__[name].setIsFrozen()
0300 def __delattr__(self,name:str):
0301 if self.isFrozen():
0302 raise ValueError("Object already added to a process. It is read only now")
0303 super(_Parameterizable,self).__delattr__(name)
0304 self.__parameterNames.remove(name)
0305 @staticmethod
0306 def __raiseBadSetAttr(name:str):
0307 raise TypeError(name+" does not already exist, so it can only be set to a CMS python configuration type")
0308 def dumpPython(self, options:PrintOptions=PrintOptions()) -> str:
0309 specialImportRegistry.registerUse(self)
0310 sortedNames = sorted(self.parameterNames_())
0311 if len(sortedNames) > 200:
0312
0313
0314
0315
0316
0317
0318 others = []
0319 usings = []
0320 for name in sortedNames:
0321 param = self.__dict__[name]
0322
0323 name2 = name.replace('-','_')
0324 options.indent()
0325
0326 if name.startswith("using_"):
0327 usings.append(options.indentation()+param.dumpPython(options))
0328 else:
0329 others.append((name2, param.dumpPython(options)))
0330 options.unindent()
0331
0332 resultList = ',\n'.join(usings)
0333 longOthers = options.indentation()+"**dict(\n"
0334 options.indent()
0335 longOthers += options.indentation()+"[\n"
0336 entriesInList = 0
0337 options.indent()
0338 for n,v in others:
0339 entriesInList +=1
0340 if entriesInList > 200:
0341
0342 options.unindent()
0343 longOthers += options.indentation()+"] +\n"+options.indentation()+"[\n"
0344 entriesInList = 0
0345 options.indent()
0346 longOthers += options.indentation()+'("'+n+'" , '+v+' ),\n'
0347
0348 longOthers += options.indentation()+"]\n"
0349 options.unindent()
0350 longOthers +=options.indentation()+")\n"
0351 options.unindent()
0352 ret = []
0353 if resultList:
0354 ret.append(resultList)
0355 if longOthers:
0356 ret.append(longOthers)
0357 return ",\n".join(ret)
0358
0359 others = []
0360 usings = []
0361 for name in sortedNames:
0362 param = self.__dict__[name]
0363
0364 name2 = name.replace('-','_')
0365 options.indent()
0366
0367 if name.startswith("using_"):
0368 usings.append(options.indentation()+param.dumpPython(options))
0369 else:
0370 others.append(options.indentation()+name2+' = '+param.dumpPython(options))
0371 options.unindent()
0372
0373 resultList = usings
0374 resultList.extend(others)
0375 if self.__validator is not None:
0376 options.indent()
0377 resultList.append(options.indentation()+"allowAnyLabel_="+self.__validator.dumpPython(options))
0378 options.unindent()
0379 return ',\n'.join(resultList)+'\n'
0380 def __repr__(self) -> str:
0381 return self.dumpPython()
0382 def insertContentsInto(self, parameterSet):
0383 for name in self.parameterNames_():
0384 param = getattr(self,name)
0385 param.insertInto(parameterSet, name)
0386
0387
0388 class _TypedParameterizable(_Parameterizable):
0389 """Base class for classes which are Parameterizable and have a 'type' assigned"""
0390 def __init__(self,type_,*arg,**kargs):
0391 self.__dict__['_TypedParameterizable__type'] = type_
0392
0393
0394
0395
0396
0397 super(_TypedParameterizable,self).__init__(*arg,**kargs)
0398 saveOrigin(self, 1)
0399 def _place(self,name:str,proc):
0400 self._placeImpl(name,proc)
0401 def type_(self):
0402 """returns the type of the object, e.g. 'FooProducer'"""
0403 return self.__type
0404 def copy(self):
0405 returnValue =_TypedParameterizable.__new__(type(self))
0406 params = self.parameters_()
0407 returnValue.__init__(self.__type,**params)
0408 returnValue._isModified = self._isModified
0409 return returnValue
0410 def clone(self, *args, **params):
0411 """Copies the object and allows one to modify the parameters of the clone.
0412 New parameters may be added by specify the exact type
0413 Modifying existing parameters can be done by just specifying the new
0414 value without having to specify the type.
0415 A parameter may be removed from the clone using the value None.
0416 #remove the parameter foo.fred
0417 mod.toModify(foo, fred = None)
0418 A parameter embedded within a PSet may be changed via a dictionary
0419 #change foo.fred.pebbles to 3 and foo.fred.friend to "barney"
0420 mod.toModify(foo, fred = dict(pebbles = 3, friend = "barney)) )
0421 """
0422 returnValue =_TypedParameterizable.__new__(type(self))
0423 myparams = self.parameters_()
0424
0425
0426 for block in args:
0427
0428 if type(block).__name__ not in ["PSet", "__PSet"]:
0429 raise ValueError("Only PSets can be passed as unnamed argument blocks. This is a "+type(block).__name__)
0430 for name in block.parameterNames_():
0431 try:
0432 del myparams[name]
0433 except KeyError:
0434 pass
0435
0436 _modifyParametersFromDict(myparams, params, self._Parameterizable__raiseBadSetAttr)
0437 if self._Parameterizable__validator is not None:
0438 myparams["allowAnyLabel_"] = self._Parameterizable__validator
0439
0440 returnValue.__init__(self.__type,*args,
0441 **myparams)
0442 returnValue._isModified = False
0443 returnValue._isFrozen = False
0444 saveOrigin(returnValue, 1)
0445 return returnValue
0446
0447 @staticmethod
0448 def __findDefaultsFor(label:str,type):
0449
0450 import sys
0451 import glob
0452 choices = list()
0453 for d in sys.path:
0454 choices.extend(glob.glob(d+'/*/*/'+label+'.py'))
0455 if not choices:
0456 return None
0457
0458
0459
0460 for c in choices:
0461
0462 name='.'.join(c[:-3].split('/')[-3:])
0463
0464 mod = __import__(name)
0465 components = name.split('.')
0466 for comp in components[1:]:
0467 mod = getattr(mod,comp)
0468 if hasattr(mod,label):
0469 default = getattr(mod,label)
0470 if isinstance(default,_TypedParameterizable):
0471 if(default.type_() == type):
0472 params = dict()
0473 for name in default.parameterNames_():
0474 params[name] = getattr(default,name)
0475 return params
0476 return None
0477
0478 def directDependencies(self):
0479 return []
0480
0481 def dumpConfig(self, options:PrintOptions=PrintOptions()) -> str:
0482 config = self.__type +' { \n'
0483 for name in self.parameterNames_():
0484 param = self.__dict__[name]
0485 options.indent()
0486 config+=options.indentation()+param.configTypeName()+' '+name+' = '+param.configValue(options)+'\n'
0487 options.unindent()
0488 config += options.indentation()+'}\n'
0489 return config
0490
0491 def dumpPython(self, options:PrintOptions=PrintOptions()) -> str:
0492 specialImportRegistry.registerUse(self)
0493 result = "cms."+str(type(self).__name__)+'("'+self.type_()+'"'
0494 nparam = len(self.parameterNames_())
0495 if nparam == 0:
0496 result += ")\n"
0497 else:
0498 result += ",\n"+_Parameterizable.dumpPython(self,options)+options.indentation() + ")\n"
0499 return result
0500
0501 def dumpPythonAttributes(self, myname:str, options:PrintOptions) -> str:
0502 """ dumps the object with all attributes declared after the constructor"""
0503 result = ""
0504 for name in sorted(self.parameterNames_()):
0505 param = self.__dict__[name]
0506 result += options.indentation() + myname + "." + name + " = " + param.dumpPython(options) + "\n"
0507 return result
0508
0509 def nameInProcessDesc_(self, myname:str):
0510 return myname;
0511 def moduleLabel_(self, myname:str):
0512 return myname
0513 def appendToProcessDescList_(self, lst, myname:str):
0514 lst.append(self.nameInProcessDesc_(myname))
0515 def insertInto(self, parameterSet, myname:str):
0516 newpset = parameterSet.newPSet()
0517 newpset.addString(True, "@module_label", self.moduleLabel_(myname))
0518 newpset.addString(True, "@module_type", self.type_())
0519 newpset.addString(True, "@module_edm_type", type(self).__name__)
0520 self.insertContentsInto(newpset)
0521 parameterSet.addPSet(True, self.nameInProcessDesc_(myname), newpset)
0522
0523
0524
0525 class _Labelable(object):
0526 """A 'mixin' used to denote that the class can be paired with a label (e.g. an EDProducer)"""
0527 def label_(self) -> str:
0528 if not hasattr(self, "_Labelable__label"):
0529 raise RuntimeError("module has no label. Perhaps it wasn't inserted into the process?")
0530 return self.__label
0531 def hasLabel_(self) -> bool:
0532 return hasattr(self, "_Labelable__label") and self.__label is not None
0533 def setLabel(self,label:str):
0534 if self.hasLabel_() :
0535 if self.label_() != label and label is not None :
0536 msg100 = "Attempting to change the label of a Labelable object, possibly an attribute of the Process\n"
0537 msg101 = "Old label = "+self.label_()+" New label = "+label+"\n"
0538 msg102 = "Type = "+str(type(self))+"\n"
0539 msg103 = "Some possible solutions:\n"
0540 msg104 = " 1. Clone modules instead of using simple assignment. Cloning is\n"
0541 msg105 = " also preferred for other types when possible.\n"
0542 msg106 = " 2. Declare new names starting with an underscore if they are\n"
0543 msg107 = " for temporaries you do not want propagated into the Process. The\n"
0544 msg108 = " underscore tells \"from x import *\" and process.load not to import\n"
0545 msg109 = " the name.\n"
0546 msg110 = " 3. Reorganize so the assigment is not necessary. Giving a second\n"
0547 msg111 = " name to the same object usually causes confusion and problems.\n"
0548 msg112 = " 4. Compose Sequences: newName = cms.Sequence(oldName)\n"
0549 raise ValueError(msg100+msg101+msg102+msg103+msg104+msg105+msg106+msg107+msg108+msg109+msg110+msg111+msg112)
0550 self.__label = label
0551 def label(self) -> str:
0552
0553 return self.__label
0554 def __str__(self):
0555
0556
0557
0558 return str(self.__label)
0559 def dumpSequenceConfig(self):
0560 return str(self.__label)
0561 def dumpSequencePython(self, options:PrintOptions=PrintOptions()):
0562 if options.isCfg:
0563 return 'process.'+str(self.__label)
0564 else:
0565 return str(self.__label)
0566 def _findDependencies(self,knownDeps,presentDeps):
0567
0568 myDeps=knownDeps.get(self.label_(),None)
0569 if myDeps!=None:
0570 if presentDeps != myDeps:
0571 raise RuntimeError("the module "+self.label_()+" has two dependencies \n"
0572 +str(presentDeps)+"\n"
0573 +str(myDeps)+"\n"
0574 +"Please modify sequences to rectify this inconsistency")
0575 else:
0576 myDeps=set(presentDeps)
0577 knownDeps[self.label_()]=myDeps
0578 presentDeps.add(self.label_())
0579
0580
0581 class _Unlabelable(object):
0582 """A 'mixin' used to denote that the class can be used without a label (e.g. a Service)"""
0583 pass
0584
0585 class _ValidatingListBase(list):
0586 """Base class for a list which enforces that its entries pass a 'validity' test"""
0587 def __init__(self,*arg,**args):
0588 super(_ValidatingListBase,self).__init__(arg)
0589 if 0 != len(args):
0590 raise SyntaxError("named arguments ("+','.join([x for x in args])+") passsed to "+str(type(self)))
0591 if not type(self)._isValid(iter(self)):
0592 raise TypeError("wrong types ("+','.join([str(type(value)) for value in iter(self)])+
0593 ") added to "+str(type(self)))
0594 def __setitem__(self,key,value):
0595 if isinstance(key,slice):
0596 if not self._isValid(value):
0597 raise TypeError("wrong type being inserted into this container "+self._labelIfAny())
0598 else:
0599 if not self._itemIsValid(value):
0600 raise TypeError("can not insert the type "+str(type(value))+" in container "+self._labelIfAny())
0601 super(_ValidatingListBase,self).__setitem__(key,value)
0602 @classmethod
0603 def _isValid(cls,seq) -> bool:
0604
0605 if isinstance(seq, str):
0606 return False
0607 for item in seq:
0608 if not cls._itemIsValid(item):
0609 return False
0610 return True
0611 def _itemFromArgument(self, x):
0612 return x
0613 def _convertArguments(self, seq):
0614 if isinstance(seq, str):
0615 yield seq
0616 for x in seq:
0617 yield self._itemFromArgument(x)
0618 def append(self,x):
0619 if not self._itemIsValid(x):
0620 raise TypeError("wrong type being appended to container "+self._labelIfAny())
0621 super(_ValidatingListBase,self).append(self._itemFromArgument(x))
0622 def extend(self,x):
0623 if not self._isValid(x):
0624 raise TypeError("wrong type being extended to container "+self._labelIfAny())
0625 super(_ValidatingListBase,self).extend(self._convertArguments(x))
0626 def __add__(self,rhs):
0627 if not self._isValid(rhs):
0628 raise TypeError("wrong type being added to container "+self._labelIfAny())
0629 import copy
0630 value = copy.copy(self)
0631 value.extend(rhs)
0632 return value
0633 def insert(self,i,x):
0634 if not self._itemIsValid(x):
0635 raise TypeError("wrong type being inserted to container "+self._labelIfAny())
0636 super(_ValidatingListBase,self).insert(i,self._itemFromArgument(x))
0637 def _labelIfAny(self) -> str:
0638 result = type(self).__name__
0639 if hasattr(self, '__label'):
0640 result += ' ' + self.__label
0641 return result
0642
0643 class _ValidatingParameterListBase(_ValidatingListBase,_ParameterTypeBase):
0644 def __init__(self,*arg,**args):
0645 _ParameterTypeBase.__init__(self)
0646 if len (arg) == 1 and not isinstance(arg[0],str):
0647 try:
0648 arg = iter(arg[0])
0649 except TypeError:
0650 pass
0651 super(_ValidatingParameterListBase,self).__init__(*arg,**args)
0652 def value(self):
0653 return list(self)
0654 def setValue(self,v):
0655 self[:] = []
0656 self.extend(v)
0657 self._isModified=True
0658 def configValue(self, options:PrintOptions=PrintOptions()) -> str:
0659 config = '{\n'
0660 first = True
0661 for value in iter(self):
0662 options.indent()
0663 config += options.indentation()
0664 if not first:
0665 config+=', '
0666 config+= self.configValueForItem(value, options)+'\n'
0667 first = False
0668 options.unindent()
0669 config += options.indentation()+'}\n'
0670 return config
0671 def configValueForItem(self,item, options:PrintOptions) -> str:
0672 return str(item)
0673 def pythonValueForItem(self,item, options:PrintOptions) -> str:
0674 return self.configValueForItem(item, options)
0675 def __repr__(self):
0676 return self.dumpPython()
0677 def dumpPython(self, options:PrintOptions=PrintOptions()) -> str:
0678 specialImportRegistry.registerUse(self)
0679 result = self.pythonTypeName()+"("
0680 n = len(self)
0681 if hasattr(self, "_nPerLine"):
0682 nPerLine = self._nPerLine
0683 else:
0684 nPerLine = 5
0685 if n>nPerLine: options.indent()
0686 if n>=256:
0687
0688 result+=" ("
0689 for i, v in enumerate(self):
0690 if i == 0:
0691 if n>nPerLine: result += '\n'+options.indentation()
0692 else:
0693 if i % nPerLine == 0:
0694 result += ',\n'+options.indentation()
0695 else:
0696 result += ', '
0697 result += self.pythonValueForItem(v,options)
0698 if n>nPerLine:
0699 options.unindent()
0700 result += '\n'+options.indentation()
0701 if n>=256:
0702 result +=' ) '
0703 result += ')'
0704 return result
0705 def directDependencies(self):
0706 return []
0707 @staticmethod
0708 def _itemsFromStrings(strings,converter):
0709 return (converter(x).value() for x in strings)
0710
0711 def saveOrigin(obj, level):
0712 import sys
0713 fInfo = inspect.getframeinfo(sys._getframe(level+1))
0714 obj._filename = fInfo.filename
0715 obj._lineNumber =fInfo.lineno
0716
0717 def _modifyParametersFromDict(params, newParams, errorRaiser, keyDepth=""):
0718 if len(newParams):
0719
0720 for key,value in newParams.items():
0721 if key in params:
0722 if value is None:
0723 del params[key]
0724 elif isinstance(value, dict):
0725 if isinstance(params[key],_Parameterizable):
0726 pset = params[key]
0727 p =pset.parameters_()
0728 oldkeys = set(p.keys())
0729 _modifyParametersFromDict(p,
0730 value,errorRaiser,
0731 ("%s.%s" if isinstance(key, str) else "%s[%s]")%(keyDepth,key))
0732 for k,v in p.items():
0733 setattr(pset,k,v)
0734 oldkeys.discard(k)
0735 for k in oldkeys:
0736 delattr(pset,k)
0737 elif isinstance(params[key],_ValidatingParameterListBase):
0738 if any(not isinstance(k, int) for k in value.keys()):
0739 raise TypeError("Attempted to change a list using a dict whose keys are not integers")
0740 plist = params[key]
0741 if any((k < 0 or k >= len(plist)) for k in value.keys()):
0742 raise IndexError("Attempted to set an index which is not in the list")
0743 p = dict(enumerate(plist))
0744 _modifyParametersFromDict(p,
0745 value,errorRaiser,
0746 ("%s.%s" if isinstance(key, str) else "%s[%s]")%(keyDepth,key))
0747 for k,v in p.items():
0748 plist[k] = v
0749 else:
0750 raise ValueError("Attempted to change non PSet value "+keyDepth+" using a dictionary")
0751 elif isinstance(value,_ParameterTypeBase) or (isinstance(key, int)) or isinstance(value, _Parameterizable):
0752 params[key] = value
0753 else:
0754 params[key].setValue(value)
0755 else:
0756 if isinstance(value,_ParameterTypeBase) or isinstance(value, _Parameterizable):
0757 params[key]=value
0758 else:
0759 errorRaiser(key)
0760
0761
0762 if __name__ == "__main__":
0763
0764 import unittest
0765 class TestList(_ValidatingParameterListBase):
0766 @classmethod
0767 def _itemIsValid(cls,item):
0768 return True
0769 class testMixins(unittest.TestCase):
0770 def testListConstruction(self):
0771 t = TestList(1)
0772 self.assertEqual(t,[1])
0773 t = TestList((1,))
0774 self.assertEqual(t,[1])
0775 t = TestList("one")
0776 self.assertEqual(t,["one"])
0777 t = TestList( [1,])
0778 self.assertEqual(t,[1])
0779 t = TestList( (x for x in [1]) )
0780 self.assertEqual(t,[1])
0781
0782 t = TestList(1,2)
0783 self.assertEqual(t,[1,2])
0784 t = TestList((1,2))
0785 self.assertEqual(t,[1,2])
0786 t = TestList("one","two")
0787 self.assertEqual(t,["one","two"])
0788 t = TestList(("one","two"))
0789 self.assertEqual(t,["one","two"])
0790 t = TestList( [1,2])
0791 self.assertEqual(t,[1,2])
0792 t = TestList( (x for x in [1,2]) )
0793 self.assertEqual(t,[1,2])
0794 t = TestList( iter((1,2)) )
0795 self.assertEqual(t,[1,2])
0796
0797
0798 def testLargeList(self):
0799
0800
0801 args = [i for i in range(0,300)]
0802
0803 t = TestList(*args)
0804 pdump= t.dumpPython()
0805 class cms(object):
0806 def __init__(self):
0807 self.TestList = TestList
0808 pythonized = eval( pdump, globals(),{'cms':cms()} )
0809 self.assertEqual(t,pythonized)
0810 def testUsingBlock(self):
0811 a = UsingBlock("a")
0812 self.assertTrue(isinstance(a, _ParameterTypeBase))
0813 def testConstruction(self):
0814 class __Test(_TypedParameterizable):
0815 pass
0816 class __TestType(_SimpleParameterTypeBase):
0817 def _isValid(self,value):
0818 return True
0819 class __PSet(_ParameterTypeBase,_Parameterizable):
0820 def __init__(self,*arg,**args):
0821
0822 _ParameterTypeBase.__init__(self)
0823 _Parameterizable.__init__(self,*arg,**args)
0824
0825 a = __Test("MyType", __PSet(a=__TestType(1)))
0826 self.assertEqual(a.a.value(), 1)
0827 b = __Test("MyType", __PSet(a=__TestType(1)), __PSet(b=__TestType(2)))
0828 self.assertEqual(b.a.value(), 1)
0829 self.assertEqual(b.b.value(), 2)
0830 self.assertRaises(ValueError, lambda: __Test("MyType", __PSet(a=__TestType(1)), __PSet(a=__TestType(2))))
0831
0832 def testCopy(self):
0833 class __Test(_TypedParameterizable):
0834 pass
0835 class __TestType(_SimpleParameterTypeBase):
0836 def _isValid(self,value):
0837 return True
0838 a = __Test("MyType",t=__TestType(1), u=__TestType(2))
0839 b = a.copy()
0840 self.assertEqual(b.t.value(),1)
0841 self.assertEqual(b.u.value(),2)
0842
0843 c = __Test("MyType")
0844 self.assertEqual(len(c.parameterNames_()), 0)
0845 d = c.copy()
0846 self.assertEqual(len(d.parameterNames_()), 0)
0847 def testClone(self):
0848 class __Test(_TypedParameterizable):
0849 pass
0850 class __TestType(_SimpleParameterTypeBase):
0851 def _isValid(self,value):
0852 return True
0853 class __PSet(_ParameterTypeBase,_Parameterizable):
0854 def __init__(self,*arg,**args):
0855
0856 _ParameterTypeBase.__init__(self)
0857 _Parameterizable.__init__(self,*arg,**args)
0858 def dumpPython(self,options=PrintOptions()):
0859 return "__PSet(\n"+_Parameterizable.dumpPython(self, options)+options.indentation()+")"
0860
0861 a = __Test("MyType",
0862 t=__TestType(1),
0863 u=__TestType(2),
0864 w = __TestType(3),
0865 x = __PSet(a = __TestType(4),
0866 b = __TestType(6),
0867 c = __PSet(gamma = __TestType(5))))
0868 b = a.clone(t=3,
0869 v=__TestType(4),
0870 w= None,
0871 x = dict(a = 7,
0872 c = dict(gamma = 8),
0873 d = __TestType(9)))
0874 c = a.clone(x = dict(a=None, c=None))
0875 self.assertEqual(a.t.value(),1)
0876 self.assertEqual(a.u.value(),2)
0877 self.assertEqual(b.t.value(),3)
0878 self.assertEqual(b.u.value(),2)
0879 self.assertEqual(b.v.value(),4)
0880 self.assertEqual(b.x.a.value(),7)
0881 self.assertEqual(b.x.b.value(),6)
0882 self.assertEqual(b.x.c.gamma.value(),8)
0883 self.assertEqual(b.x.d.value(),9)
0884 self.assertEqual(hasattr(b,"w"), False)
0885 self.assertEqual(hasattr(c.x,"a"), False)
0886 self.assertEqual(hasattr(c.x,"c"), False)
0887 self.assertRaises(TypeError,a.clone,**{"v":1})
0888 d = a.clone(__PSet(k=__TestType(42)))
0889 self.assertEqual(d.t.value(), 1)
0890 self.assertEqual(d.k.value(), 42)
0891 d2 = a.clone(__PSet(t=__TestType(42)))
0892 self.assertEqual(d2.t.value(), 42)
0893 d3 = a.clone(__PSet(t=__TestType(42)),
0894 __PSet(u=__TestType(56)))
0895 self.assertEqual(d3.t.value(), 42)
0896 self.assertEqual(d3.u.value(), 56)
0897 self.assertRaises(ValueError,a.clone,
0898 __PSet(t=__TestType(42)),
0899 __PSet(t=__TestType(56)))
0900 d4 = a.clone(__PSet(t=__TestType(43)), u = 57)
0901 self.assertEqual(d4.t.value(), 43)
0902 self.assertEqual(d4.u.value(), 57)
0903 self.assertRaises(TypeError,a.clone,t=__TestType(43),**{"doesNotExist":57})
0904
0905 e = __Test("MyType")
0906 self.assertEqual(len(e.parameterNames_()), 0)
0907 f = e.clone(__PSet(a = __TestType(1)), b = __TestType(2))
0908 self.assertEqual(f.a.value(), 1)
0909 self.assertEqual(f.b.value(), 2)
0910 g = e.clone()
0911 self.assertEqual(len(g.parameterNames_()), 0)
0912
0913 def testModified(self):
0914 class __TestType(_SimpleParameterTypeBase):
0915 def _isValid(self,value):
0916 return True
0917 a = __TestType(1)
0918 self.assertEqual(a.isModified(),False)
0919 a.setValue(1)
0920 self.assertEqual(a.isModified(),False)
0921 a.setValue(2)
0922 self.assertEqual(a.isModified(),True)
0923 a.resetModified()
0924 self.assertEqual(a.isModified(),False)
0925 def testLargeParameterizable(self):
0926 class tLPTest(_TypedParameterizable):
0927 pass
0928 class tLPTestType(_SimpleParameterTypeBase):
0929 def _isValid(self,value):
0930 return True
0931 class __DummyModule(object):
0932 def __init__(self):
0933 self.tLPTest = tLPTest
0934 self.tLPTestType = tLPTestType
0935 p = tLPTest("MyType",** dict( [ ("a"+str(x), tLPTestType(x)) for x in range(0,300) ] ) )
0936
0937 self.assertEqual(p.dumpPython(), eval(p.dumpPython(),{"cms": __DummyModule()}).dumpPython())
0938 def testSpecialImportRegistry(self):
0939 reg = _SpecialImportRegistry()
0940 reg.registerSpecialImportForType(int, "import foo")
0941 self.assertRaises(RuntimeError, lambda: reg.registerSpecialImportForType(int, "import bar"))
0942 reg.registerSpecialImportForType(str, "import bar")
0943 self.assertEqual(reg.getSpecialImports(), [])
0944 reg.registerUse([1])
0945 self.assertEqual(reg.getSpecialImports(), [])
0946 reg.registerUse(1)
0947 self.assertEqual(reg.getSpecialImports(), ["import foo"])
0948 reg.registerUse(1)
0949 self.assertEqual(reg.getSpecialImports(), ["import foo"])
0950 reg.registerUse("a")
0951 self.assertEqual(reg.getSpecialImports(), ["import bar", "import foo"])
0952 def testInvalidTypeChange(self):
0953 class __Test(_TypedParameterizable):
0954 pass
0955 class __TestTypeA(_SimpleParameterTypeBase):
0956 def _isValid(self,value):
0957 return True
0958 class __TestTypeB(_SimpleParameterTypeBase):
0959 def _isValid(self,value):
0960 return True
0961 pass
0962 a = __Test("MyType",
0963 t=__TestTypeA(1))
0964 self.assertRaises(TypeError, lambda : setattr(a,'t',__TestTypeB(2)))
0965
0966
0967 unittest.main()