CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ConfigToolBase.py
Go to the documentation of this file.
1 import copy
2 import inspect
3 import FWCore.ParameterSet.Config as cms
4 from FWCore.ParameterSet.Mixins import *
5 from os import path
6 
7 #### patches needed for deepcopy of sorted dicts ####
8 
9 import FWCore.ParameterSet.DictTypes as dicttypes
10 
12  return self.__class__(self)
13 dicttypes.SortedKeysDict.__copy__ = new_SortedKeysDict__copy__
14 
15 def new_SortedKeysDict__deepcopy__(self, memo=None):
16  from copy import deepcopy
17  if memo is None:
18  memo = {}
19  d = memo.get(id(self), None)
20  if d is not None:
21  return d
22  memo[id(self)] = d = self.__class__()
23  d.__init__(deepcopy(self.items(), memo))
24  return d
25 dicttypes.SortedKeysDict.__deepcopy__ = new_SortedKeysDict__deepcopy__
26 
27 
28 class parameter:
29  pass
30 
31 ### Base class for object oriented designed tools
32 
33 class ConfigToolBase(object) :
34 
35  """ Base class for PAT tools
36  """
37  _label="ConfigToolBase"
38  _defaultValue="No default value. Set parameter value."
39  _path = ""
40  def __init__(self):
41  self._parameters=dicttypes.SortedKeysDict()
42  self._description=self.__doc__
43  self._comment = ''
44  self.parAccepted=True
45  saveOrigin(self,1)
46  self._path = path.realpath(self._filename)
47  self._path = self._path.split("/src/")
48  self._path = self._path[1].replace("/python","")
49  #self._path = "".join(self._path)
50  self._path = self._path.replace("/",".")
51  self._path = self._path.replace(".py","")
52 
53 
54  def __call__(self,process):
55  """ Call the instance
56  """
57  raise NotImplementedError
58 
59  def apply(self,process):
60 
61  if hasattr(process, "addAction"):
62  process.disableRecording()
63 
64  try:
65  comment=inspect.stack(2)[2][4][0].rstrip("\n")
66  if comment.startswith("#"):
67  self.setComment(comment.lstrip("#"))
68  except:
69  pass
70 
71  self.toolCode(process)
72 
73  if hasattr(process, "addAction"):
74  process.enableRecording()
75  action=self.__copy__()
76  process.addAction(action)
77 
78  def toolCode(self, process):
79  raise NotImplementedError
80 
81 
82  ### __copy__(self) returns a copy of the tool
83  def __copy__(self):
84  c=type(self)()
85  c.setParameters(copy.deepcopy(self._parameters))
86  c.setComment(self._comment)
87  return c
88  def reset(self):
89  self._parameters=copy.deepcopy(self._defaultParameters)
90  def getvalue(self,name):
91  """ Return the value of parameter 'name'
92  """
93  return self._parameters[name].value
94  def description(self):
95  """ Return a string with a detailed description of the action.
96  """
97  return self._description
98 
99  ### use addParameter method in the redefinition of tool constructor in order to add parameters to the tools
100  ### each tool is defined by its label, default value, description, type and allowedValues (the last two attribute can be ignored
101  ### if the user gives a valid default values and if there is not a list of allowed values)
102  def addParameter(self,dict,parname, parvalue, description,Type=None, allowedValues=None, acceptNoneValue=False):
103  """ Add a parameter with its label, value, description and type to self._parameters
104  """
105  par=parameter()
106  par.name=parname
107  par.value=parvalue
108  par.description=description
109  if Type==None:
110  par.type=type(parvalue)
111  else: par.type=Type
112  par.allowedValues=allowedValues
113  par.acceptNoneValue=acceptNoneValue
114  dict[par.name]=par
115  def getParameters(self):
116  """ Return a copy of the dict of the parameters.
117  """
118  return copy.deepcopy(self._parameters)
119  def setParameter(self, name, value, typeNone=False):
120  """ Change parameter 'name' to a new value
121  """
122  self._parameters[name].value=value
123  ### check about input value type
124  self.typeError(name)
125  ### check about input value (it works if allowedValues for the specific parameter is set)
126  if self._defaultParameters[name].allowedValues is not None: self.isAllowed(name,value )
127  def setParameters(self, parameters):
128  self._parameters=copy.deepcopy(parameters)
129  #def dumpPython(self):
130  # """ Return the python code to perform the action
131  # """
132  # raise NotImplementedError
133 
134  def dumpPython(self):
135  """ Return the python code to perform the action
136  """
137  dumpPythonImport = "\nfrom "+self._path+" import *\n"
138  dumpPython=''
139  if self._comment!="":
140  dumpPython = '#'+self._comment
141  dumpPython += "\n"+self._label+"(process "
142  for key in self._parameters.keys():
143  if repr(self._parameters[key].value)!=repr(self._defaultParameters[key].value):
144  dumpPython+= ", "+str(key)+" = "
145  if self._parameters[key].type is str:
146  string = "'"+str(self.getvalue(key))+"'"
147  else:
148  string = str(self.getvalue(key))
149  dumpPython+= string
150  dumpPython+=")"+'\n'
151  return (dumpPythonImport,dumpPython)
152 
153  def setComment(self, comment):
154  """ Write a comment in the configuration file
155  """
156  self._comment = str(comment)
157  def comment(self):
158  """ Return the comment set for this tool
159  """
160  return self._comment
161  def errorMessage(self,value,type):
162  return "The type for parameter "+'"'+str(value)+'"'+" is not "+'"'+str(type)+'"'
163  ### method isAllowed is called by setParameter to check input values for a specific parameter
164  def isAllowed(self,name,value):
165  self.parAccepted=True
166  if value==[]:
167  self.parAccepted=False
168  elif (isinstance(value,dict)) and (isinstance(self._parameters[name].allowedValues,list)):
169  for key in value.keys():
170  if (key not in self._parameters[name].allowedValues):
171  raise ValueError("The input key value "+'"'+str(key)+'"'+" for parameter "+'"'+name+'"'+" is not supported. Supported ones are: "+str(self._parameters[name].allowedValues)[1:-1])
172  elif (isinstance(value,list)) and (isinstance(self._parameters[name].allowedValues,list )):
173  for val in value:
174  if (val not in self._parameters[name].allowedValues) :
175  raise ValueError("The input value "+'"'+str(val)+'"'+" for parameter "+'"'+name+'"'+" is not supported. Supported ones are: "+str(self._parameters[name].allowedValues)[1:-1])
176  elif (not isinstance(value,list))and (isinstance(self._parameters[name].allowedValues,list)) :
177  if (value not in self._parameters[name].allowedValues and value == None) and (not self._parameters[name].acceptNoneValue) :
178  self.parAccepted=False
179  elif not isinstance(self._parameters[name].allowedValues,list):
180  if (value!=self._parameters[name].allowedValues and value == None) and (not self._parameters[name].acceptNoneValue) :
181  self.parAccepted=False
182  if self.parAccepted==False:
183  raise ValueError("The input value "+'"'+str(value)+'"'+" for parameter "+'"'+name+'"'+" is not supported. Supported ones are: "+str(self._parameters[name].allowedValues)[1:-1])
184  ### check about input value type
185  def typeError(self,name):
186  if self._parameters[name].acceptNoneValue is False:
187  if not isinstance(self._parameters[name].value,self._parameters[name].type):
188  raise TypeError(self.errorMessage(self._parameters[name].value,self._parameters[name].type))
189  else:
190  if not (isinstance(self._parameters[name].value,self._parameters[name].type) or self._parameters[name].value is None):
191  raise TypeError(self.errorMessage(self._parameters[name].value,self._parameters[name].type))
192  def getAllowedValues(self,name):
193  return self._defaultParameters[name].allowedValues
def isAllowed
method isAllowed is called by setParameter to check input values for a specific parameter ...
def saveOrigin
Definition: Mixins.py:620
def typeError
check about input value type
def addParameter
use addParameter method in the redefinition of tool constructor in order to add parameters to the too...
def new_SortedKeysDict__deepcopy__
def __copy__
copy(self) returns a copy of the tool
def new_SortedKeysDict__copy__