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