CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Mixins.py
Go to the documentation of this file.
1 import inspect
2 
4  """Denotes a class that can be used by the Processes class"""
5  pass
6 
8  def __init__(self):
9  self.indent_= 0
10  self.deltaIndent_ = 4
11  self.isCfg = True
12  def indentation(self):
13  return ' '*self.indent_
14  def indent(self):
15  self.indent_ += self.deltaIndent_
16  def unindent(self):
17  self.indent_ -= self.deltaIndent_
18 
20  """base class for classes which are used as the 'parameters' for a ParameterSet"""
21  def __init__(self):
22  self.__dict__["_isFrozen"] = False
23  self.__isTracked = True
24  self._isModified = False
25  def isModified(self):
26  return self._isModified
27  def resetModified(self):
28  self._isModified=False
29  def configTypeName(self):
30  if self.isTracked():
31  return type(self).__name__
32  return 'untracked '+type(self).__name__
33  def pythonTypeName(self):
34  if self.isTracked():
35  return 'cms.'+type(self).__name__
36  return 'cms.untracked.'+type(self).__name__
37  def dumpPython(self, options=PrintOptions()):
38  return self.pythonTypeName()+"("+self.pythonValue(options)+")"
39  def __repr__(self):
40  return self.dumpPython()
41  def isTracked(self):
42  return self.__isTracked
43  def setIsTracked(self,trackness):
44  self.__isTracked = trackness
45  def isFrozen(self):
46  return self._isFrozen
47  def setIsFrozen(self):
48  self._isFrozen = True
49 
51  """base class for parameter classes which only hold a single value"""
52  def __init__(self,value):
53  super(_SimpleParameterTypeBase,self).__init__()
54  self._value = value
55  if not self._isValid(value):
56  raise ValueError(str(value)+" is not a valid "+str(type(self)))
57  def value(self):
58  return self._value
59  def setValue(self,value):
60  if not self._isValid(value):
61  raise ValueError(str(value)+" is not a valid "+str(type(self)))
62  if value!=self._value:
63  self._isModified=True
64  self._value=value
65  def configValue(self, options=PrintOptions()):
66  return str(self._value)
67  def pythonValue(self, options=PrintOptions()):
68  return self.configValue(options)
69  def __eq__(self,other):
70  if isinstance(other,_SimpleParameterTypeBase):
71  return self._value == other._value
72  return self._value == other
73  def __ne__(self,other):
74  if isinstance(other,_SimpleParameterTypeBase):
75  return self._value != other._value
76  return self._value != other
77 
78 
80  """For injection purposes, pretend this is a new parameter type
81  then have a post process step which strips these out
82  """
83  def __init__(self,value, s='', loc=0, file=''):
84  super(UsingBlock,self).__init__(value)
85  self.s = s
86  self.loc = loc
87  self.file = file
88  self.isResolved = False
89  @staticmethod
90  def _isValid(value):
91  return isinstance(value,str)
92  def _valueFromString(value):
93  """only used for cfg-parsing"""
94  return string(value)
95  def insertInto(self, parameterSet, myname):
96  value = self.value()
97  # doesn't seem to handle \0 correctly
98  #if value == '\0':
99  # value = ''
100  parameterSet.addString(self.isTracked(), myname, value)
101  def dumpPython(self, options):
102  if options.isCfg:
103  return "process."+self.value()
104  else:
105  return self.value()
106 
107 
109  """Base class for classes which allow addition of _ParameterTypeBase data"""
110  def __init__(self,*arg,**kargs):
111  self.__dict__['_Parameterizable__parameterNames'] = []
112  self.__dict__["_isFrozen"] = False
113  """The named arguments are the 'parameters' which are added as 'python attributes' to the object"""
114  if len(arg) != 0:
115  #raise ValueError("unnamed arguments are not allowed. Please use the syntax 'name = value' when assigning arguments.")
116  for block in arg:
117  if type(block).__name__ != "PSet":
118  raise ValueError("Only PSets can be passed as unnamed argument blocks. This is a "+type(block).__name__)
119  self.__setParameters(block.parameters_())
120  self.__setParameters(kargs)
121  self._isModified = False
122 
123  def parameterNames_(self):
124  """Returns the name of the parameters"""
125  return self.__parameterNames[:]
126  def isModified(self):
127  if self._isModified:
128  return True
129  for name in self.parameterNames_():
130  param = self.__dict__[name]
131  if isinstance(param, _Parameterizable) and param.isModified():
132  self._isModified = True
133  return True
134  return False
135 
136  def hasParameter(self, params):
137  """
138  _hasParameter_
139 
140  check that pset provided has the attribute chain
141  specified.
142 
143  Eg, if params is [ 'attr1', 'attr2', 'attr3' ]
144  check for pset.attr1.attr2.attr3
145 
146  returns True if parameter exists, False if not
147  """
148  return (self.getParameter(params) != None)
149 
150  def getParameter(self, params):
151  """
152  _getParameter_
153 
154  Retrieve the specified parameter from the PSet Provided
155  given the attribute chain
156 
157  returns None if not found
158  """
159  lastParam = self
160  # Don't accidentally iterate over letters in a string
161  if type(params).__name__ == 'str':
162  return getattr(self, params, None)
163  for param in params:
164  lastParam = getattr(lastParam, param, None)
165  print str(lastParam)
166  if lastParam == None:
167  return None
168  return lastParam
169 
170  def parameters_(self):
171  """Returns a dictionary of copies of the user-set parameters"""
172  import copy
173  result = dict()
174  for name in self.parameterNames_():
175  result[name]=copy.deepcopy(self.__dict__[name])
176  return result
177 
178  def __addParameter(self, name, value):
179  if not isinstance(value,_ParameterTypeBase):
180  self.__raiseBadSetAttr(name)
181  if name in self.__dict__:
182  message = "Duplicate insert of member " + name
183  message += "\nThe original parameters are:\n"
184  message += self.dumpPython() + '\n'
185  raise ValueError(message)
186  self.__dict__[name]=value
187  self.__parameterNames.append(name)
188  self._isModified = True
189 
190  def __setParameters(self,parameters):
191  for name,value in parameters.iteritems():
192  self.__addParameter(name, value)
193 
194  def __setattr__(self,name,value):
195  #since labels are not supposed to have underscores at the beginning
196  # I will assume that if we have such then we are setting an internal variable
197  if self.isFrozen() and not (name in ["_Labelable__label","_isFrozen"] or name.startswith('_')):
198  message = "Object already added to a process. It is read only now\n"
199  message += " %s = %s" %(name, value)
200  message += "\nThe original parameters are:\n"
201  message += self.dumpPython() + '\n'
202  raise ValueError(message)
203  # underscored names bypass checking for _ParameterTypeBase
204  if name[0]=='_':
205  super(_Parameterizable,self).__setattr__(name,value)
206  elif not name in self.__dict__:
207  self.__addParameter(name, value)
208  self._isModified = True
209  else:
210  # handle the case where users just replace with a value, a = 12, rather than a = cms.int32(12)
211  if isinstance(value,_ParameterTypeBase):
212  self.__dict__[name] = value
213  else:
214  self.__dict__[name].setValue(value)
215  self._isModified = True
216 
217  def isFrozen(self):
218  return self._isFrozen
219  def setIsFrozen(self):
220  self._isFrozen = True
221  for name in self.parameterNames_():
222  self.__dict__[name].setIsFrozen()
223  def __delattr__(self,name):
224  if self.isFrozen():
225  raise ValueError("Object already added to a process. It is read only now")
226  super(_Parameterizable,self).__delattr__(name)
227  self.__parameterNames.remove(name)
228  @staticmethod
229  def __raiseBadSetAttr(name):
230  raise TypeError(name+" does not already exist, so it can only be set to a CMS python configuration type")
231  def dumpPython(self, options=PrintOptions()):
232  others = []
233  usings = []
234  for name in self.parameterNames_():
235  param = self.__dict__[name]
236  # we don't want minuses in names
237  name2 = name.replace('-','_')
238  options.indent()
239  #_UsingNodes don't get assigned variables
240  if name.startswith("using_"):
241  usings.append(options.indentation()+param.dumpPython(options))
242  else:
243  others.append(options.indentation()+name2+' = '+param.dumpPython(options))
244  options.unindent()
245  # usings need to go first
246  resultList = usings
247  resultList.extend(others)
248  return ',\n'.join(resultList)+'\n'
249  def __repr__(self):
250  return self.dumpPython()
251  def insertContentsInto(self, parameterSet):
252  for name in self.parameterNames_():
253  param = getattr(self,name)
254  param.insertInto(parameterSet, name)
255 
256 
258  """Base class for classes which are Parameterizable and have a 'type' assigned"""
259  def __init__(self,type_,*arg,**kargs):
260  self.__dict__['_TypedParameterizable__type'] = type_
261  #the 'type' is also placed in the 'arg' list and we need to remove it
262  #if 'type_' not in kargs:
263  # arg = arg[1:]
264  #else:
265  # del args['type_']
266  arg = tuple([x for x in arg if x != None])
267  super(_TypedParameterizable,self).__init__(*arg,**kargs)
268  saveOrigin(self, 1)
269  def _place(self,name,proc):
270  self._placeImpl(name,proc)
271  def type_(self):
272  """returns the type of the object, e.g. 'FooProducer'"""
273  return self.__type
274  def copy(self):
275  returnValue =_TypedParameterizable.__new__(type(self))
276  params = self.parameters_()
277  args = list()
278  if len(params) == 0:
279  args.append(None)
280  returnValue.__init__(self.__type,*args,
281  **params)
282  returnValue._isModified = self._isModified
283  return returnValue
284  def clone(self, *args, **params):
285  """Copies the object and allows one to modify the parameters of the clone.
286  New parameters may be added by specify the exact type
287  Modifying existing parameters can be done by just specifying the new
288  value without having to specify the type.
289  """
290  returnValue =_TypedParameterizable.__new__(type(self))
291  myparams = self.parameters_()
292  if len(myparams) == 0 and len(params) and len(args):
293  args.append(None)
294  if len(params):
295  #need to treat items both in params and myparams specially
296  for key,value in params.iteritems():
297  if key in myparams:
298  if isinstance(value,_ParameterTypeBase):
299  myparams[key] =value
300  else:
301  myparams[key].setValue(value)
302  else:
303  if isinstance(value,_ParameterTypeBase):
304  myparams[key]=value
305  else:
306  self._Parameterizable__raiseBadSetAttr(key)
307 
308  returnValue.__init__(self.__type,*args,
309  **myparams)
310  returnValue._isModified = False
311  returnValue._isFrozen = False
312  saveOrigin(returnValue, 1)
313  return returnValue
314 
315  @staticmethod
316  def __findDefaultsFor(label,type):
317  #This routine is no longer used, but I might revive it in the future
318  import sys
319  import glob
320  choices = list()
321  for d in sys.path:
322  choices.extend(glob.glob(d+'/*/*/'+label+'.py'))
323  if not choices:
324  return None
325  #now see if any of them have what we want
326  #the use of __import__ is taken from an example
327  # from the www.python.org documentation on __import__
328  for c in choices:
329  #print " found file "+c
330  name='.'.join(c[:-3].split('/')[-3:])
331  #name = c[:-3].replace('/','.')
332  mod = __import__(name)
333  components = name.split('.')
334  for comp in components[1:]:
335  mod = getattr(mod,comp)
336  if hasattr(mod,label):
337  default = getattr(mod,label)
338  if isinstance(default,_TypedParameterizable):
339  if(default.type_() == type):
340  params = dict()
341  for name in default.parameterNames_():
342  params[name] = getattr(default,name)
343  return params
344  return None
345 
346  def dumpConfig(self, options=PrintOptions()):
347  config = self.__type +' { \n'
348  for name in self.parameterNames_():
349  param = self.__dict__[name]
350  options.indent()
351  config+=options.indentation()+param.configTypeName()+' '+name+' = '+param.configValue(options)+'\n'
352  options.unindent()
353  config += options.indentation()+'}\n'
354  return config
355 
356  def dumpPython(self, options=PrintOptions()):
357  result = "cms."+str(type(self).__name__)+'("'+self.type_()+'"'
358  nparam = len(self.parameterNames_())
359  if nparam == 0:
360  result += ")\n"
361  elif nparam < 256:
362  result += ",\n"+_Parameterizable.dumpPython(self,options)+options.indentation() + ")\n"
363  else:
364  # too big. Need to dump externally
365  #NOTE: in future should explore just creating a dict
366  # {'foo':cms.uint32(1), .... }
367  # and pass it to the constructor using the **{...} notation
368  label = ""
369  try:
370  label = "process."+self.label_()
371  except:
372  label = "FIX-THIS"
373  result += ")\n" + self.dumpPythonAttributes(label, options)
374  return result
375 
376  def dumpPythonAttributes(self, myname, options):
377  """ dumps the object with all attributes declared after the constructor"""
378  result = ""
379  for name in self.parameterNames_():
380  param = self.__dict__[name]
381  result += options.indentation() + myname + "." + name + " = " + param.dumpPython(options) + "\n"
382  return result
383 
384  def nameInProcessDesc_(self, myname):
385  return myname;
386  def moduleLabel_(self, myname):
387  return myname
388  def insertInto(self, parameterSet, myname):
389  newpset = parameterSet.newPSet()
390  newpset.addString(True, "@module_label", self.moduleLabel_(myname))
391  newpset.addString(True, "@module_type", self.type_())
392  newpset.addString(True, "@module_edm_type", type(self).__name__)
393  self.insertContentsInto(newpset)
394  parameterSet.addPSet(True, self.nameInProcessDesc_(myname), newpset)
395 
396 
397 
399  """A 'mixin' used to denote that the class can be paired with a label (e.g. an EDProducer)"""
400  def setLabel(self,label):
401  self.__label = label
402  def label_(self):
403  if not hasattr(self, "_Labelable__label"):
404  raise RuntimeError("module has no label. Perhaps it wasn't inserted into the process?")
405  return self.__label
406  def hasLabel_(self):
407  return hasattr(self, "_Labelable__label") and self.__label is not None
408  def label(self):
409  #print "WARNING: _Labelable::label() needs to be changed to label_()"
410  return self.__label
411  def __str__(self):
412  #this is probably a bad idea
413  # I added this so that when we ask a path to print
414  # we will see the label that has been assigned
415  return str(self.__label)
417  return str(self.__label)
419  return 'process.'+str(self.__label)
420  def _findDependencies(self,knownDeps,presentDeps):
421  #print 'in labelled'
422  myDeps=knownDeps.get(self.label_(),None)
423  if myDeps!=None:
424  if presentDeps != myDeps:
425  raise RuntimeError("the module "+self.label_()+" has two dependencies \n"
426  +str(presentDeps)+"\n"
427  +str(myDeps)+"\n"
428  +"Please modify sequences to rectify this inconsistency")
429  else:
430  myDeps=set(presentDeps)
431  knownDeps[self.label_()]=myDeps
432  presentDeps.add(self.label_())
433 
434 
436  """A 'mixin' used to denote that the class can be used without a label (e.g. a Service)"""
437  pass
438 
439 class _ValidatingListBase(list):
440  """Base class for a list which enforces that its entries pass a 'validity' test"""
441  def __init__(self,*arg,**args):
442  super(_ValidatingListBase,self).__init__(arg)
443  if 0 != len(args):
444  raise SyntaxError("named arguments ("+','.join([x for x in args])+") passsed to "+str(type(self)))
445  if not self._isValid(iter(self)):
446  raise TypeError("wrong types ("+','.join([str(type(value)) for value in iter(self)])+
447  ") added to "+str(type(self)))
448  def __setitem__(self,key,value):
449  if isinstance(key,slice):
450  if not self._isValid(value):
451  raise TypeError("wrong type being inserted into this container "+self._labelIfAny())
452  else:
453  if not self._itemIsValid(value):
454  raise TypeError("can not insert the type "+str(type(value))+" in container "+self._labelIfAny())
455  super(_ValidatingListBase,self).__setitem__(key,value)
456  def _isValid(self,seq):
457  # see if strings get reinterpreted as lists
458  if isinstance(seq, str):
459  return False
460  for item in seq:
461  if not self._itemIsValid(item):
462  return False
463  return True
464  def append(self,x):
465  if not self._itemIsValid(x):
466  raise TypeError("wrong type being appended to container "+self._labelIfAny())
467  super(_ValidatingListBase,self).append(x)
468  def extend(self,x):
469  if not self._isValid(x):
470  raise TypeError("wrong type being extended to container "+self._labelIfAny())
471  super(_ValidatingListBase,self).extend(x)
472  def __add__(self,rhs):
473  if not self._isValid(rhs):
474  raise TypeError("wrong type being added to container "+self._labelIfAny())
475  import copy
476  value = copy.copy(self)
477  value.extend(rhs)
478  return value
479  def insert(self,i,x):
480  if not self._itemIsValid(x):
481  raise TypeError("wrong type being inserted to container "+self._labelIfAny())
482  super(_ValidatingListBase,self).insert(i,x)
483  def _labelIfAny(self):
484  result = type(self).__name__
485  if hasattr(self, '__label'):
486  result += ' ' + self.__label
487  return result
488 
490  def __init__(self,*arg,**args):
491  _ParameterTypeBase.__init__(self)
492  if len (arg) == 1 and not isinstance(arg[0],str):
493  try:
494  arg = iter(arg[0])
495  except TypeError:
496  pass
497  super(_ValidatingParameterListBase,self).__init__(*arg,**args)
498  def value(self):
499  return list(self)
500  def setValue(self,v):
501  self[:] = []
502  self.extend(v)
503  self._isModified=True
504  def configValue(self, options=PrintOptions()):
505  config = '{\n'
506  first = True
507  for value in iter(self):
508  options.indent()
509  config += options.indentation()
510  if not first:
511  config+=', '
512  config+= self.configValueForItem(value, options)+'\n'
513  first = False
514  options.unindent()
515  config += options.indentation()+'}\n'
516  return config
517  def configValueForItem(self,item, options):
518  return str(item)
519  def pythonValueForItem(self,item, options):
520  return self.configValueForItem(item, options)
521  def __repr__(self):
522  return self.dumpPython()
523  def dumpPython(self, options=PrintOptions()):
524  result = self.pythonTypeName()+"("
525  n = len(self)
526  if n<255:
527  indented = False
528  for i, v in enumerate(self):
529  if i == 0:
530  if hasattr(self, "_nPerLine"):
531  nPerLine = self._nPerLine
532  else:
533  nPerLine = 5
534  else:
535  if not indented:
536  indented = True
537  options.indent()
538 
539  result += ', '
540  if i % nPerLine == 0:
541  result += '\n'+options.indentation()
542  result += self.pythonValueForItem(v,options)
543  if indented:
544  options.unindent()
545  #result+=', '.join((self.pythonValueForItem(v,options) for v in iter(self)))
546  else:
547  result = '('
548  start = 0
549  l=list()
550  while(start < len(self)):
551  v=self.pythonTypeName()+'('
552  v+=', '.join((self.pythonValueForItem(v,options) for v in self[start:start+255]))
553  v+=')'
554  l.append(v)
555  start+=255
556  result+='+'.join(l)
557  pass
558  result += ')'
559  return result
560  @staticmethod
561  def _itemsFromStrings(strings,converter):
562  return (converter(x).value() for x in strings)
563 
564 def saveOrigin(obj, level):
565  #frame = inspect.stack()[level+1]
566  frame = inspect.getframeinfo(inspect.currentframe(level+1))
567  # not safe under old python versions
568  #obj._filename = frame.filename
569  #obj._lineNumber = frame.lineno
570  obj._filename = frame[0]
571  obj._lineNumber = frame[1]
572 
573 if __name__ == "__main__":
574 
575  import unittest
577  def _itemIsValid(self,item):
578  return True
579  class testMixins(unittest.TestCase):
581  t = TestList(1)
582  self.assertEqual(t,[1])
583  t = TestList((1,))
584  self.assertEqual(t,[1])
585  t = TestList("one")
586  self.assertEqual(t,["one"])
587  t = TestList( [1,])
588  self.assertEqual(t,[1])
589  t = TestList( (x for x in [1]) )
590  self.assertEqual(t,[1])
591 
592  t = TestList(1,2)
593  self.assertEqual(t,[1,2])
594  t = TestList((1,2))
595  self.assertEqual(t,[1,2])
596  t = TestList("one","two")
597  self.assertEqual(t,["one","two"])
598  t = TestList(("one","two"))
599  self.assertEqual(t,["one","two"])
600  t = TestList( [1,2])
601  self.assertEqual(t,[1,2])
602  t = TestList( (x for x in [1,2]) )
603  self.assertEqual(t,[1,2])
604  t = TestList( iter((1,2)) )
605  self.assertEqual(t,[1,2])
606 
607 
608  def testLargeList(self):
609  #lists larger than 255 entries can not be initialized
610  #using the constructor
611  args = [i for i in xrange(0,300)]
612 
613  t = TestList(*args)
614  pdump= t.dumpPython()
615  class cms(object):
616  def __init__(self):
617  self.TestList = TestList
618  pythonized = eval( pdump, globals(),{'cms':cms()} )
619  self.assertEqual(t,pythonized)
620  def testUsingBlock(self):
621  a = UsingBlock("a")
622  self.assert_(isinstance(a, _ParameterTypeBase))
623  def testCopy(self):
624  class __Test(_TypedParameterizable):
625  pass
626  class __TestType(_SimpleParameterTypeBase):
627  def _isValid(self,value):
628  return True
629  a = __Test("MyType",t=__TestType(1), u=__TestType(2))
630  b = a.copy()
631  self.assertEqual(b.t.value(),1)
632  self.assertEqual(b.u.value(),2)
633  def testClone(self):
634  class __Test(_TypedParameterizable):
635  pass
636  class __TestType(_SimpleParameterTypeBase):
637  def _isValid(self,value):
638  return True
639  a = __Test("MyType",t=__TestType(1), u=__TestType(2))
640  b = a.clone(t=3, v=__TestType(4))
641  self.assertEqual(a.t.value(),1)
642  self.assertEqual(a.u.value(),2)
643  self.assertEqual(b.t.value(),3)
644  self.assertEqual(b.u.value(),2)
645  self.assertEqual(b.v.value(),4)
646  self.assertRaises(TypeError,a.clone,None,**{"v":1})
647  def testModified(self):
648  class __TestType(_SimpleParameterTypeBase):
649  def _isValid(self,value):
650  return True
651  a = __TestType(1)
652  self.assertEqual(a.isModified(),False)
653  a.setValue(1)
654  self.assertEqual(a.isModified(),False)
655  a.setValue(2)
656  self.assertEqual(a.isModified(),True)
657  a.resetModified()
658  self.assertEqual(a.isModified(),False)
659  unittest.main()
def _valueFromString
Definition: Mixins.py:92
def testUsingBlock
Definition: Mixins.py:620
bool setValue(Container &, const reco::JetBaseRef &, const JetExtendedData &)
associate jet with value. Returns false and associate nothing if jet is already associated ...
def dumpSequenceConfig
Definition: Mixins.py:416
def saveOrigin
Definition: Mixins.py:564
def testListConstruction
Definition: Mixins.py:580
def dumpSequencePython
Definition: Mixins.py:418
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
def _itemIsValid
Definition: Mixins.py:577
list object
Definition: dbtoconf.py:77
perl if(1 lt scalar(@::datatypes))
Definition: edlooper.cc:31
def _findDependencies
Definition: Mixins.py:420
double split
Definition: MVATrainer.cc:139
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger list("!*","!HLTx*"if it matches 2 triggers or more) will accept the event if all the matching triggers are FAIL.It will reject the event if any of the triggers are PASS or EXCEPTION(this matches the behavior of"!*"before the partial wildcard feature was incorporated).Triggers which are in the READY state are completely ignored.(READY should never be returned since the trigger paths have been run