Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-03-03 23:53:00

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