Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:33:01

0001 import copy
0002 import inspect
0003 import FWCore.ParameterSet.Config as cms
0004 from FWCore.ParameterSet.Mixins import *
0005 from os import path
0006 
0007 #### patches needed for deepcopy of sorted dicts ####
0008 
0009 import FWCore.ParameterSet.DictTypes as dicttypes
0010 
0011 def new_SortedKeysDict__copy__(self):
0012     return self.__class__(self)
0013 dicttypes.SortedKeysDict.__copy__ = new_SortedKeysDict__copy__
0014 
0015 def new_SortedKeysDict__deepcopy__(self, memo=None):
0016     from copy import deepcopy
0017     if memo is None:
0018         memo = {}
0019     d = memo.get(id(self), None)
0020     if d is not None:
0021         return d
0022     memo[id(self)] = d = self.__class__()
0023     d.__init__(deepcopy(self.items(), memo))
0024     return d
0025 dicttypes.SortedKeysDict.__deepcopy__ = new_SortedKeysDict__deepcopy__
0026 
0027 
0028 class parameter:
0029     pass
0030 
0031 ### Base class for object oriented designed tools
0032 
0033 class ConfigToolBase(object) :
0034 
0035     """ Base class for PAT tools
0036     """
0037     _label="ConfigToolBase"
0038     _defaultValue="No default value. Set parameter value."
0039     _path = ""
0040     def __init__(self):
0041         self._parameters=dicttypes.SortedKeysDict()
0042         self._description=self.__doc__
0043         self._comment = ''
0044         self.parAccepted=True
0045         saveOrigin(self,1)
0046         self._path = path.realpath(self._filename)        
0047         self._path = self._path.split("/src/")
0048         self._path = self._path[1].replace("/python","")
0049         #self._path = "".join(self._path)
0050         self._path = self._path.replace("/",".")
0051         self._path = self._path.replace(".py","")
0052 
0053 
0054     def __call__(self,process):
0055         """ Call the instance 
0056         """
0057         raise NotImplementedError
0058 
0059     def apply(self,process):
0060 
0061         if hasattr(process, "addAction"):
0062             process.disableRecording()
0063 
0064         try:
0065             comment=inspect.stack(2)[2][4][0].rstrip("\n")
0066             if comment.startswith("#"):
0067                 self.setComment(comment.lstrip("#"))
0068         except:
0069             pass
0070 
0071         self.toolCode(process)
0072 
0073         if hasattr(process, "addAction"):
0074             process.enableRecording()
0075             action=self.__copy__()
0076             process.addAction(action)
0077 
0078     def toolCode(self, process):
0079         raise NotImplementedError
0080 
0081 
0082     ### __copy__(self) returns a copy of the tool
0083     def __copy__(self):
0084         c=type(self)()
0085         c.setParameters(copy.deepcopy(self._parameters))
0086         c.setComment(self._comment)
0087         return c
0088     def reset(self):
0089         self._parameters=copy.deepcopy(self._defaultParameters)
0090     def getvalue(self,name):
0091         """ Return the value of parameter 'name'
0092         """
0093         return self._parameters[name].value
0094     def description(self):
0095         """ Return a string with a detailed description of the action.
0096         """
0097         return self._description
0098 
0099     ### use addParameter method in the redefinition of tool constructor in order to add parameters to the tools
0100     ### each tool is defined by its label, default value, description, type and allowedValues (the last two attribute can be ignored
0101     ### if the user gives a valid default values and if there is not a list of allowed values)
0102     def addParameter(self,dict,parname, parvalue, description,Type=None, allowedValues=None, acceptNoneValue=False):
0103         """ Add a parameter with its label, value, description and type to self._parameters
0104         """
0105         par=parameter()
0106         par.name=parname
0107         par.value=parvalue
0108         par.description=description
0109         if Type==None:
0110             par.type=type(parvalue)
0111         else: par.type=Type
0112         par.allowedValues=allowedValues
0113         par.acceptNoneValue=acceptNoneValue
0114         dict[par.name]=par        
0115     def getParameters(self):
0116         """ Return a copy of the dict of the parameters.
0117         """
0118         return copy.deepcopy(self._parameters)
0119     def setParameter(self, name, value, typeNone=False):
0120         """ Change parameter 'name' to a new value
0121         """
0122         self._parameters[name].value=value
0123         ### check about input value type 
0124         self.typeError(name)
0125         ### check about input value (it works if allowedValues for the specific parameter is set)
0126         if self._defaultParameters[name].allowedValues is not None: self.isAllowed(name,value )
0127     def setParameters(self, parameters):
0128         self._parameters=copy.deepcopy(parameters)
0129     #def dumpPython(self):
0130      #   """ Return the python code to perform the action
0131      #   """
0132      #   raise NotImplementedError
0133 
0134     def dumpPython(self):
0135         """ Return the python code to perform the action
0136         """ 
0137         dumpPythonImport = "\nfrom "+self._path+" import *\n"
0138         dumpPython=''
0139         if self._comment!="":
0140             dumpPython = '#'+self._comment
0141         dumpPython += "\n"+self._label+"(process "
0142         for key in self._parameters.keys():
0143             if repr(self._parameters[key].value)!=repr(self._defaultParameters[key].value):
0144                 dumpPython+= ", "+str(key)+" = "
0145                 if self._parameters[key].type is str:
0146                     string = "'"+str(self.getvalue(key))+"'"
0147                 else:
0148                     string = str(self.getvalue(key))
0149                 dumpPython+= string
0150         dumpPython+=")"+'\n'
0151         return (dumpPythonImport,dumpPython)
0152 
0153     def setComment(self, comment):
0154         """ Write a comment in the configuration file
0155         """
0156         self._comment = str(comment)
0157     def comment(self):
0158         """ Return the comment set for this tool
0159         """
0160         return self._comment
0161     def errorMessage(self,value,type):
0162         return "The type for parameter "+'"'+str(value)+'"'+" is not "+'"'+str(type)+'"'
0163     ### method isAllowed is called by setParameter to check input values for a specific parameter
0164     def isAllowed(self,name,value):
0165         self.parAccepted=True
0166         if value==[]:
0167             self.parAccepted=False
0168         elif (isinstance(value,dict)) and (isinstance(self._parameters[name].allowedValues,list)):
0169             for key in value.keys():
0170                 if (key not in self._parameters[name].allowedValues):
0171                     raise ValueError("The input key value "+'"'+str(key)+'"'+" for parameter "+'"'+name+'"'+" is not supported. Supported ones are: "+str(self._parameters[name].allowedValues)[1:-1])
0172         elif (isinstance(value,list)) and (isinstance(self._parameters[name].allowedValues,list )):
0173             for val in value:
0174                 if (val not in self._parameters[name].allowedValues) :
0175                     raise ValueError("The input value "+'"'+str(val)+'"'+" for parameter "+'"'+name+'"'+" is not supported. Supported ones are: "+str(self._parameters[name].allowedValues)[1:-1])
0176         elif (not isinstance(value,list))and (isinstance(self._parameters[name].allowedValues,list)) :
0177             if (value not in self._parameters[name].allowedValues and value == None) and (not self._parameters[name].acceptNoneValue) :
0178                 self.parAccepted=False
0179         elif not isinstance(self._parameters[name].allowedValues,list):
0180             if (value!=self._parameters[name].allowedValues and value == None) and (not self._parameters[name].acceptNoneValue) :
0181                 self.parAccepted=False  
0182         if self.parAccepted==False:
0183             raise ValueError("The input value "+'"'+str(value)+'"'+" for parameter "+'"'+name+'"'+" is not supported. Supported ones are: "+str(self._parameters[name].allowedValues)[1:-1])
0184     ### check about input value type        
0185     def typeError(self,name):
0186         if self._parameters[name].acceptNoneValue is False:
0187             if not isinstance(self._parameters[name].value,self._parameters[name].type):
0188                 raise TypeError(self.errorMessage(self._parameters[name].value,self._parameters[name].type))
0189         else:
0190             if not (isinstance(self._parameters[name].value,self._parameters[name].type) or self._parameters[name].value is  None):
0191                 raise TypeError(self.errorMessage(self._parameters[name].value,self._parameters[name].type))
0192     def getAllowedValues(self,name):
0193         return self._defaultParameters[name].allowedValues