CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ConfigDataAccessor.py
Go to the documentation of this file.
1 import sys
2 import os.path
3 import logging
4 import re
5 
6 from Vispa.Share.BasicDataAccessor import BasicDataAccessor
7 from Vispa.Share.RelativeDataAccessor import RelativeDataAccessor
8 from Vispa.Main.Exceptions import PluginIgnoredException,exception_traceback
9 
10 import FWCore.ParameterSet.SequenceTypes as sqt
11 import FWCore.ParameterSet.Config as cms
12 import FWCore.ParameterSet.Modules as mod
13 import FWCore.ParameterSet.Types as typ
14 
15 imported_configs = {}
16 file_dict = {}
17 
19  def __init__(self, label, parent=None, parameters=None):
20  self._label = label
21  self._configChildren = []
22  self._parameters = {}
23  if parent != None:
24  parent._configChildren += [self]
25  if parameters != None:
26  self._parameters = parameters
27  def label_(self):
28  return self._label
29  def parameters_(self):
30  return self._parameters
31  def _configChildren(self):
32  return self._configChildren
33 
34 class ConfigDataAccessor(BasicDataAccessor, RelativeDataAccessor):
35  def __init__(self):
36  logging.debug(__name__ + ": __init__")
37 
38  self._file = None
39  self._filename=""
40  self._isReplaceConfig = False
41  self._history=None
42  self._cancelOperationsFlag = False
43  self._initLists()
44 
45  def _initLists(self):
46  self._allObjects = []
47  self._connections = {}
48  self._topLevelObjects = []
49  self._inputTagsDict = {}
50  self._foundInDict = {}
51  self._usesDict = {}
52  self._usedByDict = {}
55 
56  def cancelOperations(self):
57  self._cancelOperationsFlag = True
58 
59  def isReplaceConfig(self):
60  return self._isReplaceConfig
61 
62  def setIsReplaceConfig(self):
63  self._isReplaceConfig = True
64 
65  def topLevelObjects(self):
66  return self._topLevelObjects
67 
68  def _readRecursive(self, mother, pth):
69  """ Read cms objects recursively from path """
70  entry = None
71  if isinstance(pth, (cms.Path, cms.EndPath, cms.Sequence, cms.SequencePlaceholder, cms.Source, mod._Module, cms.Service, cms.ESSource, cms.ESProducer, cms.ESPrefer, cms.PSet, cms.VPSet)):
72  entry = pth
73  entry._configChildren=[]
74  self._allObjects += [pth]
75  if mother != None:
76  if not pth in mother._configChildren:
77  mother._configChildren += [pth]
78  else:
79  self._topLevelObjects += [pth]
80  next_mother = entry
81  if entry == None:
82  next_mother = mother
83  if isinstance(pth, list):
84  for i in pth:
85  self._readRecursive(next_mother, i)
86  if hasattr(sqt,"_SequenceCollection"):
87  # since CMSSW_3_11_X
88  if isinstance(pth, (sqt._ModuleSequenceType)):
89  if isinstance(pth._seq, (sqt._SequenceCollection)):
90  for o in pth._seq._collection:
91  self._readRecursive(next_mother, o)
92  else:
93  self._readRecursive(next_mother, pth._seq)
94  elif isinstance(pth, sqt._UnarySequenceOperator):
95  self._readRecursive(next_mother, pth._operand)
96  else:
97  # for backwards-compatibility with CMSSW_3_10_X
98  for i in dir(pth):
99  o = getattr(pth, i)
100  if isinstance(o, sqt._Sequenceable):
101  self._readRecursive(next_mother, o)
102 
103  def readConnections(self, objects,toNeighbors=False):
104  """ Read connection between objects """
105  connections={}
106  self._motherRelationsDict={}
107  self._daughterRelationsDict={}
108  if toNeighbors:
109  compareObjectList=[]
110  for obj in objects:
111  compareObjectList+=[(obj,o) for o in self._allObjects]
112  compareObjectList+=[(o,obj) for o in self._allObjects]
113  else:
114  compareObjectList=[(o1,o2) for o1 in objects for o2 in objects]
115  for connection in compareObjectList:
116  if self._cancelOperationsFlag:
117  break
118  if not connection in self._connections.keys():
119  for key, value in self.inputTags(connection[1]):
120  module = str(value).split(":")[0]
121  if module == self.label(connection[0]):
122  product = ".".join(str(value).split(":")[1:])
123  try:
124  self._connections[connection]=(product, key)
125  except TypeError:
126  return []
127  if connection in self._connections.keys():
128  connections[connection]=self._connections[connection]
129  if not connection[1] in self._motherRelationsDict.keys():
130  self._motherRelationsDict[connection[1]]=[]
131  self._motherRelationsDict[connection[1]]+=[connection[0]]
132  if not connection[0] in self._daughterRelationsDict.keys():
133  self._daughterRelationsDict[connection[0]]=[]
134  self._daughterRelationsDict[connection[0]]+=[connection[1]]
135  return connections
136 
137  def connections(self):
138  return self._connections
139 
140  def _sort_list(self, l):
141  result = l[:]
142  result.sort(lambda x, y: cmp(self.label(x).lower(), self.label(y).lower()))
143  return result
144 
145  def open(self, filename=None):
146  """ Open config file and read it.
147  """
148  logging.debug(__name__ + ": open")
149  if filename != None:
150  self._filename = str(filename)
151  global imported_configs
152  self._isReplaceConfig = False
153  self._history=None
154 
155 # import input-config and make list of all imported configs
156  for i in imported_configs.iterkeys():
157  if i in sys.modules.keys():
158  del sys.modules[i]
159  sys.path.insert(0, os.path.dirname(self._filename))
160  common_imports = sys.modules.copy()
161 
162  import imp
163  theFile = open(self._filename)
164  self._file = imp.load_module(os.path.splitext(os.path.basename(self._filename))[0].replace(".", "_"), theFile, self._filename, ("py", "r", 1))
165  theFile.close()
166 
167  imported_configs = sys.modules.copy()
168  for i in common_imports.iterkeys():
169  del imported_configs[i]
170 
171 # make dictionary that connects every cms-object with the file in which it is defined
172  for j in imported_configs.itervalues():
173  setj = set(dir(j))
174  for entry in setj:
175  if entry[0] != "_" and entry != "cms":
176  source = 1
177  for k in imported_configs.itervalues():
178  if hasattr(k, entry):
179  setk = set(dir(k))
180  if len(setk) < len(setj) and setk < setj:
181  source = 0
182  if source == 1:
183  filen = self._filename
184  if hasattr(j, "__file__"):
185  filen = j.__file__
186  file_dict[entry] = filen
187 
188 # collect all path/sequences/modules of the input-config in a list
189  if self.process():
190  self.setProcess(self.process())
191  self._readHeaderInfo()
192  self._history=self.process().dumpHistory()
193  if not self._isReplaceConfig and hasattr(self.process(),"resetHistory"):
194  self.process().resetHistory()
195  else:
196  self._initLists()
197  for entry in dir(self._file):
198  o=getattr(self._file, entry)
199  if entry[0] != "_" and entry != "cms" and hasattr(o, "label_"):
200  getattr(self._file, entry).setLabel(entry)
201  text = os.path.splitext(os.path.basename(file_dict[o.label_()]))[0]
202  if text == os.path.splitext(os.path.basename(self._filename))[0] and not o in self._allObjects:
203  self._readRecursive(None, o)
204  return True
205 
206  def setProcess(self,process):
207  self._file.process=process
208  self._initLists()
209  parameters = {"name": self.process().process}
210  process_folder = ConfigFolder("process", None, parameters)
211 
212  self._allObjects += [process_folder]
213  self._topLevelObjects += [process_folder]
214 
215  folder_list = []
216  folder_list += [("source", [self.process().source])]
217  if self.process().schedule != None:
218  folder_list += [("paths", self.process().schedule)]
219  else:
220  folder_list += [("paths", self.process().paths.itervalues())]
221  folder_list += [("endpaths", self.process().endpaths.itervalues())]
222  folder_list += [("services", self._sort_list(self.process().services.values()))]
223  folder_list += [("psets", self._sort_list(self.process().psets.values()))]
224  folder_list += [("vpsets", self._sort_list(self.process().vpsets.values()))]
225  folder_list += [("essources", self._sort_list(self.process().es_sources.values()))]
226  folder_list += [("esproducers", self._sort_list(self.process().es_producers.values()))]
227  folder_list += [("esprefers", self._sort_list(self.process().es_prefers.values()))]
228  for foldername, entry in folder_list:
229  folder = ConfigFolder(foldername, process_folder)
230  self._allObjects += [folder]
231  for path in entry:
232  self._readRecursive(folder, path)
233 
234  def process(self):
235  if hasattr(self._file, "process"):
236  return self._file.process
237  return None
238 
239  def _readHeaderInfo(self):
240  theFile = open(self._filename)
241  foundHeaderPart1 = False
242  foundHeaderPart2 = False
243  lines = 10
244  search_paths=[os.path.abspath(os.path.dirname(self._filename))]
245  while theFile and not (foundHeaderPart1 and foundHeaderPart2) and lines > 0:
246  line = theFile.readline()
247  lines -= 1
248  if "Generated by ConfigEditor" in line:
249  foundHeaderPart1 = True
250  splitline = line.split("'")
251  if foundHeaderPart1 and len(splitline) == 5 and splitline[0] == "sys.path.append(os.path.abspath(os.path.expandvars(os.path.join(" and splitline[4] == "))))\n":
252  search_paths+=[os.path.abspath(os.path.expandvars(os.path.join(splitline[1],splitline[3])))]
253  splitline = line.split()
254  if foundHeaderPart1 and len(splitline) == 4 and splitline[0] == "from" and splitline[2] == "import":
255  for search_path in search_paths:
256  if os.path.exists(os.path.join(search_path,splitline[1]+".py")):
257  self._filename = os.path.join(search_path,splitline[1]+".py")
258  break
259  self._isReplaceConfig = True
260  foundHeaderPart2 = True
261  theFile.close()
262 
263  def dumpPython(self):
264  """ dump python configuration """
265  logging.debug(__name__ + ": dumpPython")
266  text = None
267  if self.process():
268  text = self.process().dumpPython()
269  return text
270 
271  def history(self):
272  """ configuration history """
273  logging.debug(__name__ + ": history")
274  return self._history
275 
276  def configFile(self):
277  return self._filename
278 
279  def label(self, object):
280  """ Get label of an object """
281  text = ""
282  if hasattr(object, "label_") and (not hasattr(object,"hasLabel_") or object.hasLabel_()):
283  text = str(object.label_())
284  if text == "":
285  if hasattr(object, "type_"):
286  text = str(object.type_())
287  if text == "":
288  text = "NoLabel"
289  return text
290 
291  def children(self, object):
292  """ Get children of an object """
293  if hasattr(object, "_configChildren"):
294  return tuple(object._configChildren)
295  else:
296  return ()
297 
298  def isContainer(self, object):
299  return isinstance(object, (ConfigFolder, list, cms.Path, cms.EndPath, cms.Sequence, cms.SequencePlaceholder))
300 
301  def nonSequenceChildren(self, object):
302  objects=[]
303  if self.isContainer(object):
304  for o in self.allChildren(object):
305  if not self.isContainer(o) and len(self.children(o)) == 0 and not o in objects:
306  objects += [o]
307  else:
308  for o in self.motherRelations(object)+[object]+self.daughterRelations(object):
309  if not o in objects:
310  objects += [o]
311  return objects
312 
313  def motherRelations(self, object):
314  """ Get motherRelations of an object """
315  if object in self._motherRelationsDict.keys():
316  try:
317  return self._motherRelationsDict[object]
318  except TypeError:
319  return []
320  else:
321  return []
322 
323  def daughterRelations(self, object):
324  """ Get daughterRelations of an object """
325  if object in self._daughterRelationsDict.keys():
326  try:
327  return self._daughterRelationsDict[object]
328  except TypeError:
329  return []
330  else:
331  return []
332 
333  def type(self, object):
334  """ Get type of an object """
335  return object.__class__.__name__
336 
337  def classname(self, object):
338  """ Get classname of an object """
339  text = ""
340  if hasattr(object, "type_"):
341  text = object.type_()
342  return text
343 
344  def fullFilename(self, object):
345  """ Get full filename """
346  text = ""
347 # if hasattr(object,"_filename"):
348 # text=object._filename
349  if text == "" or text.find("FWCore/ParameterSet") >= 0 or text.find("/build/") >= 0:
350  if self.label(object) in file_dict:
351  text = file_dict[self.label(object)]
352  else:
353  text = self._filename
354  root = os.path.splitext(text)[0]
355  if root != "":
356  text = root + ".py"
357  return text
358 
359  def lineNumber(self, object):
360  """ Get linenumber """
361  text = ""
362  if hasattr(object, "_filename"):
363  if object._filename.find("FWCore/ParameterSet") < 0 and object._filename.find("ConfigEditor") < 0:
364  if hasattr(object, "_lineNumber"):
365  text = str(object._lineNumber)
366  return text
367 
368  def filename(self, object):
369  """ Get filename """
370  text = os.path.splitext(os.path.basename(self.fullFilename(object)))[0]
371  return text
372 
373  def pypackage(self,object):
374  match_compiled = re.match(r'(?:^|.*?/)CMSSW[0-9_]*/python/((?:\w*/)*\w*)\.py$',self.fullFilename(object))
375  if match_compiled:
376  return match_compiled.group(1).replace('/','.')
377 
378  match_norm = re.match(r'(?:^|.*?/)(\w*)/(\w*)/(?:test|python)/((?:\w*/)*)(\w*)\.py$',self.fullFilename(object))
379  if match_norm:
380  return '%s.%s.%s%s' % (match_norm.group(1),match_norm.group(2),match_norm.group(3).replace('/','.'),match_norm.group(4))
381  return ''
382 
383  def pypath(self,object):
384  match_compiled = re.match(r'(?:^|.*?/)CMSSW[0-9_]*/python/((?:\w*/){2})((?:\w*/)*)(\w*\.py)$',self.fullFilename(object))
385  if match_compiled:
386  return '%spython/%s%s' % (match_compiled.group(1),match_compiled.group(2),match_compiled.group(3))
387  match_norm = re.match(r'(?:^|.*?/)(\w*/\w*/(?:test|python)/(?:\w*/)*\w*\.py)$',self.fullFilename(object))
388  if match_norm:
389  return match_norm.group(1)
390  return ''
391 
392  def package(self, object):
393  """ Get Package of an object file """
394  shortdirname = os.path.dirname(self.fullFilename(object)).split('python/')
395  text = ""
396  if len(shortdirname) > 1:
397  text = shortdirname[1]
398  return text
399 
400  def parameters(self, object):
401  """ Get parameters of an object """
402  this_parameters = []
403  if hasattr(object, "parameters_"):
404  this_parameters = object.parameters_().items()
405  elif hasattr(object, "_seq"):
406  if hasattr(object._seq,"dumpSequencePython"):
407  this_parameters = [('sequence', object._seq.dumpSequencePython())]
408  else:
409  this_parameters = [('sequence', 'WARNING: object was removed from a sequence.')]
410  if hasattr(object, "tarlabel_"):
411  this_parameters += [('tarlabel', object.tarlabel_())]
412  return this_parameters
413 
414  def _addInputTag(self, value, this_key, this_inputtags):
415  """ Add alls inputtags of value to a list """
416  if isinstance(value, cms.VInputTag):
417  for i in range(len(value)):
418  if type(value[i])==str:
419  self._addInputTag(cms.InputTag(value[i]), this_key+"["+str(i)+"]", this_inputtags)
420  else:
421  self._addInputTag(value[i], this_key+"["+str(i)+"]", this_inputtags)
422  elif isinstance(value, list):
423  for i in value:
424  self._addInputTag(i, this_key, this_inputtags)
425  if hasattr(value, "parameters_"):
426  this_inputtags += self._readInputTagsRecursive(value.parameters_().items(), this_key)
427  if isinstance(value, cms.InputTag):
428  pythonValue = value.value()
429  this_inputtags += [(str(this_key), value.value())]
430 
431  def _readInputTagsRecursive(self, this_parameters, start_key=""):
432  """ Make list of inputtags from parameter dict """
433  this_inputtags = []
434  for key, value in this_parameters:
435  this_key = start_key
436  if this_key != "":
437  this_key += "."
438  this_key += key
439  self._addInputTag(value, this_key, this_inputtags)
440  return this_inputtags
441 
442  def inputTags(self, object):
443  """ Make list of inputtags from parameter dict """
444  if not object in self._inputTagsDict.keys():
445  try:
446  self._inputTagsDict[object]=self._readInputTagsRecursive(self.parameters(object))
447  except TypeError:
448  return []
449  return self._inputTagsDict[object]
450 
451  def uses(self, object):
452  """ Get list of all config objects that are used as input """
453  if not object in self._usesDict.keys():
454  uses = []
455  for key, value in self.inputTags(object):
456  module = str(value).split(":")[0]
457  product = ".".join(str(value).split(":")[1:])
458  if module not in uses:
459  uses += [module]
460  try:
461  self._usesDict[object]=uses
462  except TypeError:
463  return []
464  return self._usesDict[object]
465 
466  def foundIn(self, object):
467  """ Make list of all mother sequences """
468  if not object in self._foundInDict.keys():
469  foundin = []
470  for entry in self._allObjects:
471  for daughter in self.children(entry):
472  if self.label(object) == self.label(daughter) and len(self.children(entry)) > 0 and not self.label(entry) in foundin:
473  foundin += [self.label(entry)]
474  try:
475  self._foundInDict[object]=foundin
476  except TypeError:
477  return []
478  return self._foundInDict[object]
479 
480  def usedBy(self, object):
481  """ Find config objects that use this as input """
482  if not object in self._usedByDict.keys():
483  usedby = []
484  for entry in self._allObjects:
485  for uses in self.uses(entry):
486  if self.label(object) == uses and not self.label(entry) in usedby:
487  usedby += [self.label(entry)]
488  try:
489  self._usedByDict[object]=usedby
490  except TypeError:
491  return []
492  return self._usedByDict[object]
493 
494  def recursePSetProperties(self, name, object, readonly=None):
495  #logging.debug(__name__ + ": recursePSetProperties: " + name)
496  properties = []
497  if name != "" and not isinstance(object, typ.PSet):
498  try:
499  partyp=str(type(object)).split("'")[1].replace("FWCore.ParameterSet.Types","cms")
500  if isinstance(object, cms.InputTag):
501  inputtagValue=object.pythonValue()
502  for i in range(3-len(inputtagValue.split(","))):
503  inputtagValue+=', ""'
504  properties += [("String", name, "cms.InputTag("+inputtagValue+")", partyp, readonly)]
505  elif isinstance(object, cms.bool):
506  properties += [("Boolean", name, object.value(), partyp, readonly)]
507  elif isinstance(object, (cms.int32, cms.uint32, cms.int64, cms.uint64)):
508  properties += [("Integer", name, object.value(), partyp, readonly)]
509  elif isinstance(object, cms.double):
510  properties += [("Double", name, object.value(), partyp, readonly)]
511  elif hasattr(object, "pythonValue"):
512  properties += [("String", name, str(object.pythonValue()).strip("\"'"), partyp, readonly)]
513  elif hasattr(object, "value"):
514  properties += [("MultilineString", name, str(object.value()), partyp, readonly)]
515  else:
516  properties += [("MultilineString", name, str(object), partyp, readonly)]
517  except Exception:
518  logging.error(__name__ + ": " + exception_traceback())
519 
520  if isinstance(object, ConfigFolder):
521  readonly = True
522 
523  params = self.parameters(object)[:]
524  params.sort(lambda x, y: cmp(x[0].lower(), y[0].lower()))
525  for key, value in params:
526  keyname = name
527  if name != "":
528  keyname += "."
529  keyname += key
530  properties += self.recursePSetProperties(keyname, value, readonly)
531  return properties
532 
533  def properties(self, object):
534  """ Make list of all properties """
535  #logging.debug(__name__ + ": properties")
536  properties = []
537  properties += [("Category", "Object info", "")]
538  if self.label(object) != "":
539  properties += [("String", "label", self.label(object), None, True)]
540  if self.type(object) != "":
541  text = self.type(object)
542  if self.classname(object) != "":
543  text += " <" + self.classname(object) + ">"
544  properties += [("String", "type", text, None, True)]
545  if self.filename(object) != "":
546  text = self.filename(object)
547  if self.lineNumber(object) != "":
548  text += " : " + self.lineNumber(object)
549  properties += [("String", "file", text, None, True)]
550  if self.package(object) != "":
551  properties += [("String", "package", self.package(object), None, True)]
552  if self.fullFilename(object) != "":
553  properties += [("String", "full filename", self.fullFilename(object), None, True)]
554  foundIn=self.foundIn(object)
555  if len(foundIn) > 0:
556  text = ""
557  for entry in foundIn:
558  if text != "":
559  text += ", "
560  text += entry
561  properties += [("String", "in sequence", text, "This module/sequence is used the listed sequences", True)]
562  uses=self.uses(object)
563  usedBy=self.usedBy(object)
564  if len(uses) + len(usedBy) > 0:
565  properties += [("Category", "Connections", "")]
566  if len(uses) > 0:
567  text = ""
568  for label in uses:
569  if text != "":
570  text += ", "
571  text += label
572  properties += [("MultilineString", "uses", text, "This module/sequence depends on the output of the listes modules/seuquences", True)]
573  if len(usedBy) > 0:
574  text = ""
575  usedby = []
576  for entry in usedBy:
577  if text != "":
578  text += ", "
579  text += entry
580  properties += [("MultilineString", "used by", text, "The listed modules/sequences depend on the output of this module/sequence", True)]
581  if len(self.parameters(object)) > 0:
582  properties += [("Category", "Parameters", "")]
583  properties += self.recursePSetProperties("", object)
584  return tuple(properties)
585 
586  def setProperty(self, object, name, value, categoryName):
587  """ Sets a property with given name to value.
588  """
589  if hasattr(object, "_seq") and name=="sequence":
590  return "Modification of sequences not supported yet."
591  else:
592  process=self.process()
593  try:
594  if isinstance(value,str) and\
595  not value[0]=="[" and\
596  not value[0:4]=="cms.":
597  exec "object." + name + "='''" + value + "'''"
598  else:
599  exec "object." + name + "=" + str(value)
600  except Exception,e:
601  error="Cannot set parameter "+name+" (see logfile for details):\n"+str(e)
602  logging.warning(__name__ + ": setProperty: Cannot set parameter "+name+": "+exception_traceback())
603  return error
604  return True
605 
606  def inputEventContent(self):
607  content = []
608  allLabels = [self.label(object) for object in self._allObjects]
609  content_objects = {}
610  for object in self._allObjects:
611  for key, value in self.inputTags(object):
612  elements=str(value).split(":")
613  module = elements[0]
614  if len(elements)>1:
615  product = elements[1]
616  else:
617  product = ""
618  if len(elements)>2:
619  process = elements[2]
620  else:
621  process = "*"
622  if not module in allLabels:
623  if not ("*",module,product,process) in content:
624  content += [("*",module,product,process)]
625  if "*_"+module+"_"+product+"_"+process in content_objects.keys():
626  content_objects["*_"+module+"_"+product+"_"+process]+=","+self.label(object)
627  else:
628  content_objects["*_"+module+"_"+product+"_"+process]=self.label(object)
629  return (content,content_objects)
630 
632  content = [("*",self.label(object),"*",self.process().process) for object in self._allObjects\
633  if self.type(object) in ["EDProducer", "EDFilter", "EDAnalyzer"]]
634  return content
635 
636  def inputCommands(self):
637  inputModules = [object for object in self._allObjects\
638  if self.type(object) == "Source"]
639  if len(inputModules) > 0 and hasattr(inputModules[0], "inputCommands"):
640  return inputModules[0].inputCommands
641  else:
642  return []
643 
644  def outputCommands(self):
645  outputModules = [object for object in self._allObjects\
646  if self.type(object) == "OutputModule"]
647  if len(outputModules) > 0 and hasattr(outputModules[0], "outputCommands"):
648  return outputModules[0].outputCommands
649  else:
650  return []
void strip(std::string &input, const std::string &blanks=" \n\t")
Definition: stringTools.cc:16
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
list object
Definition: dbtoconf.py:77
dbl *** dir
Definition: mlp_gen.cc:35
double split
Definition: MVATrainer.cc:139