CMS 3D CMS Logo

cfg-viewer.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # -*- coding: latin-1 -*-
3 from __future__ import print_function
4 import re
5 import collections
6 import FWCore.ParameterSet.Config as cms
8 import six
9 
11  def __init__(self,cfgFile,html,quiet,helperDir,fullDir):
12  self._html = html
13  #self._serverName = os.path.join(os.path.split(html)[0],"EditingServer.py")
14  self._quiet = quiet
15  self._theDir= fullDir
16  self._helperDir = helperDir
17  self._mother,self._daughter ={},{}
18  self._reg = re.compile("['>]")
19  self._data,self._types,self._genericTypes={},{},{}
20  self._dictP ="DictParent"
21  self._modSeqP = "ModuleSeqParent"
22  self._prodConsP= "ProdConsumParent"
23  self._parents = {
24  "DictParent":{"creator":"dictCreate","simple": True},
25  "ModuleSeqParent":{"creator":"modSeqCreate","simple": False},
26  "ProdConsumParent":{"creator":"prodConCreate","simple": False}
27  }
28  for name,x in six.iteritems(self._parents):
29  x["pfile"] = self._filenames(name)
30  x["cfile"] = self._filenames(x["creator"])
31  self._type = "%stypes.js"%(fullDir)
32  self._allJSFiles =["types.js"]
33  self._config = ConfigDataAccessor.ConfigDataAccessor()
34  self._config.open(cfgFile)
35  self._computed = self._proceed(cfgFile)
36 
37  def _proceed(self, fileName):
38  #self._filename= ""
39  topObjs = self._config.topLevelObjects()
40  if(len(topObjs)):
41  self._getData(topObjs)
42  ty = "genericTypes"
43  with open(self._type, 'w') as f:
44  f.write("var %s=%s"%(ty,genericTypes))
45  self._createObjects()
46  self._writeDictParent(ty)
47  self._writeModSeqParent()
48  self._writeProdConsum()
49  fN = fileName.split("./")[-1].split(".")[0]
50  JS = ["%s%s"%(self._helperDir,x)for x in self._allJSFiles]
51  html(self._html,JS,self._data, self._theDir, self._helperDir,
52  self._config.process().name_(), fN)
53 
54  return True
55  else:
56  print("---Nothing found for file %s."\
57  " No computation done.---"%(fileName))
58  return False
59 
60  def _getData(self,objs):
61  # i will loop around objs and keep adding things which are configFolders
62  calc =[]
63  for each in objs:
64  name = self._config.label(each)
65  kids = self._config.children(each)
66  if(not kids):
67  if(not self._quiet):print(name, "is empty.")
68  continue
69  # Taking liberty of assuming all are of same type.
70  ty = type(kids[0])
71  if(ty is ConfigDataAccessor.ConfigFolder):
72  objs.extend(kids)
73  else:
74  if(not self._quiet):print("computing %s.."%(name))
75  if(isinstance(kids[0], seq._ModuleSequenceType)):
76  # e.g.it's a path, sequence or endpath
77  self._doSequenceTypes(kids,name)
78  else:
79  # e.g. it's a pset etc.
80  self._doNonSequenceType(kids,name)
81  calc.append(name)
82  # now i will print out producers/consumers.
83  if(self._quiet):print("calculated: %s."%(", ".join(calc)))
84  self._producersConsumers()
85 
86  # Get the data for items which are SequenceTypes
87  def _doSequenceTypes(self,paths,namep):
88  theDataFile,fullDataFile = self._calcFilenames(namep)
89  topLevel,fullTopLevel = self._calcFilenames("top-"+namep)
90  json = [topLevel,theDataFile]
91  cap = namep.capitalize()
92  bl={}
93  types = False
94  with open(fullDataFile,'w') as data:
95  data.write("{")
96  v = visitor(data, self._config)
97  for item in paths:
98  if(not types):
99  spec = self._checkType(item)
100  self._saveData(spec,self._parents[self._modSeqP]["creator"],json)
101  types = True
102  name = self._config.label(item)
103  # Dont think we need to check for this here.
104  self._mothersDaughters(name,item)
105  key = self._config.label(item)
106  item.visit(v)
107  bl[key]= getParamSeqDict(v._finalExit(),
108  self._config.fullFilename(item), self._config.type(item), "")
109  data.write("}")
110  with open(fullTopLevel, 'w') as other:
111  other.write(JSONFormat(bl))
112 
113  # Check type of item and return the specofic type
114  def _checkType(self,item):
115  gen, spec = re.sub(self._reg, "",
116  str(item.__class__)).split(".")[-2:]
117  doTypes(spec,gen)
118  return spec
119 
120  # find the mothers and daughters, storing them
121  def _mothersDaughters(self,name, item):
122  mo =self._config.motherRelations(item)
123  dau = self._config.daughterRelations(item)
124  if(mo):
125  self._mother[name] = [self._config.label(i) for i in mo]
126  if(dau):
127  self._daughter[name] = [self._config.label(i) for i in dau]
128 
129  # Find data for objs which are not SequenceTypes
130  def _doNonSequenceType(self,objs, globalType):
131  everything={}
132  always= types = False
133  theDataFile, fullDataFile = self._calcFilenames(globalType)
134  # For modules types can be diff
135  # so we always want to call the doTypes method
136  if(globalType =="modules"):
137  self._saveData(globalType.capitalize(),
138  self._parents[self._dictP]["creator"],
139  [theDataFile])
140  always = types = True
141  for item in objs:
142  if(always or not types):
143  spec = self._checkType(item)
144  if(not types):
145  self._saveData(spec,self._parents[self._dictP]["creator"],
146  [theDataFile])
147  types = True
148  name = self._config.label(item)
149  self._mothersDaughters(name, item)
150  if(isinstance(item,cms._Parameterizable)):
151  out = getParameters(item.parameters_())
152  elif(isinstance(item,cms._ValidatingListBase)):
153  out = listBase(item)
154  if(isinstance(item,cms._TypedParameterizable)):
155  oType = item.type_()
156  else:
157  oType =""
158  everything[name] = getParamSeqDict(out,
159  self._config.fullFilename(item),
160  self._config.type(item), oType)
161  with open(fullDataFile,'w') as dataFile:
162  dataFile.write(JSONFormat(everything))
163 
164  # Return json data file names
165  def _calcFilenames(self,name):
166  return self._filenames(name,"data-%s.json")
167 
168  # Return filenames
169  def _filenames(self,name,option=""):
170  if(option): basicName = option%(name)
171  else: basicName = "%s.js"%(name)
172  return (basicName, "%s%s"%(self._theDir,basicName))
173 
174  # write out mothers and daughters (producers/consumers).
176  if(not self._mother and not self._daughter):
177  return
178  for name,theDict in six.iteritems({"producer":self._mother,
179  "consumer":self._daughter}):
180  thedataFile , fulldataFile = self._calcFilenames(name)
181  self._saveData(name.capitalize(),
182  self._parents[self._prodConsP]["creator"],
183  [thedataFile,self._calcFilenames("modules")[0]])
184  with open(fulldataFile,'w') as moth:
185  moth.write(JSONFormat(theDict))
186  def _saveData(self,name,base,jsonfiles):
187  jsonfiles = " ".join(["%s%s"%(self._helperDir,x)for x in jsonfiles])
188  temp={}
189  temp["data-base"] = base
190  temp["data-files"] = jsonfiles
191  self._data[name] = temp
192 
193  # Create objs and print out .js files for
194  # each type of items we have.
195  def _createObjects(self):
196  base = "obj= Object.create(new %s(%s));"
197  format="""
198  function %s(%s){
199  var obj;
200  %s
201  return obj;
202  }
203  """
204  name = "data"
205  for pname,x in six.iteritems(self._parents):
206  simple = base%(pname,name)
207  filename,fullfilename= x["cfile"]
208  self._allJSFiles.append(filename)
209  if(x["simple"]):
210  paramName="modules"
211  with open(fullfilename, 'w') as setUp:
212  setUp.write(format%(x["creator"],paramName,self._load(
213  name,paramName,simple)))
214  continue
215  secName = "topL"
216  paramName=["modules","topLevel"]
217  complexOne = base%(pname,"%s,%s"%(name, secName))
218  with open(fullfilename, 'w') as setUp:
219  setUp.write(format%(x["creator"],", ".join(paramName),
220  self._load(name,paramName[0],
221  self._load(secName, paramName[1],complexOne))))
222 
223  # return the .js code for loading json files in a string
224  def _load(self,name,param,inner):
225  return"""
226  loadJSON(%s).done(function(%s){\n%s\n});
227  """%(param,name,inner)
228 
229  # The parent class for non SequenceTypes
230  def _writeDictParent(self, typeName):
231  exVar ='this.%(key)sKey= "%(key)s";'
232  exFunc ="""
233 /**
234  * Gives the %(key)s
235  * @param {String} the key to the dictionary.
236  * @returns {String || Integer} result from dictionary if found else 0.
237  */
238 %(name)s.prototype.get%(key)s = function(key){
239  return this.getFeature(key,this.%(key)sKey);
240 }
241  """
242  search = """%(name)s.prototype.search%(key)s = function(reg,term,replce){
243  return this.generalSearch(reg,term,replce,this.%(key)sKey);
244 } """
245  extra= """
246  /**
247  /**
248 * Uses the list of parents names to go further into
249 * the lists in the dictionry, and give the last parents children.
250 * @param {Array} the names of parents to look through.
251 * First parent should be a key to the dictionary.
252 * @param {Integer} the index where the elusive parameter is. Needed incase
253 * we have a list with muultiple parameters of the same name.
254 *
255 * @returns {Array} the resulting children from the last parent.
256 */
257 DictParent.prototype.getInnerParams = function(parents, index){
258  var currentList = this.data[parents[0]][this.%(key)sKey];
259  var targetList=[]
260  var siblingsOfTarget=[]
261  for(var i=1; i < parents.length;i++){
262  for(var p=0; p < currentList.length;p++){
263  if(currentList[p][0]==parents[i]){
264  targetList = currentList[p]
265  siblingsOfTarget=currentList
266  var found = targetList[1];
267  break;
268  }
269  }
270  currentList = found;
271  }
272  if(p != index)targetList=siblingsOfTarget[index]
273  return targetList;
274 }
275  """
276  functs=""
277  variables =""
278  name = self._dictP
279  data = self._parents[name]
280  fileName, fullfileName= data["pfile"]
281  for feature in dictFeatures:
282  d = {"key": feature, "name": name}
283  variables +=exVar%d
284  functs +=exFunc%d
285  if(feature == "Parameters"):
286  functs +=extra%d
287  else:
288  functs += search%d
289  self._allJSFiles.append(fileName)
290  with open(fullfileName, 'w') as parent:
291  parent.write("""
292 /*
293  Base Object for dictionaries.
294  To use, create a dictParent obj,
295  then use Object.create to create a new obj
296  then you can change some variables/add functions
297  and have the inherited functions.
298 */
299 function %(name)s(data){
300  this.data=data;
301  %(theVars)s
302 }
303 /**
304  * Finds the desired feature from a dictionary.
305 * @param {String} the key to the dictionary.
306 * @param {String} the feature we want from the dictionary.
307 * @returns {String || Integer} result from dictionary if found else 0.
308 */
309 %(name)s.prototype.getFeature = function(key, feature){
310  var temp = this.data[key];
311  if(temp) return temp[feature];
312  else return 0;
313 }
314 DictParent.prototype.getData = function(){
315  return [this.data];
316 }
317 %(getterFunctions)s
318 
319 /**
320  * Gives the keys from desired dictionary.
321 * @returns {Array} all keys from the dictionary.
322 */
323 %(name)s.prototype.getKeys = function(){
324  return Object.keys(this.data);
325 }
326 %(name)s.prototype.generalSearch = function(reg,term,repl,feature, d){
327  d = d || this.data;
328  var matches ={}
329  for (var key in d){
330  var x= d[key][feature]
331  if(x.indexOf(term)>-1){
332  matches[key] = x.replace(reg,repl)
333  }
334  }
335  return matches;
336 }
337 
338 /**
339  * Gives the generic type for a given type.
340  * @param {String} type
341  * @returns {String} the generic type
342  */
343 function getGenericType(type){
344  return %(gen)s[type];
345 }
346  """%{"theVars":variables,"getterFunctions":functs,
347  "gen": typeName, "name":name})
348 
349  # Write out the class for SequenceTypes
351  f = """
352 /**
353  * Gives the direct children
354  * @param {String} a path name
355  * @returns {Array} list of names of the the children.
356  */
357 %(name)s.prototype.getModules = function(name){
358  return this.topLevelData[name][this.ParametersKey];
359 }
360 %(name)s.prototype.getTopFile = function(key){
361  return this.topLevelData[key][this.FileKey];
362 }
363 %(name)s.prototype.getData = function(){
364  return [this.topLevelData, this.data];
365 }
366 %(name)s.prototype.searchType = function(reg,term,replce){
367  return this.generalSearch(reg,term,replce,this.TypeKey, this.topLevelData);
368 }
369 %(name)s.prototype.searchFile = function(reg,term,replce){
370  return this.generalSearch(reg,term,replce,this.FileKey, this.topLevelData);
371 }
372 """
373  self._complexBase(self._modSeqP, f)
374 
375  # Write out the class for producers and consumers.
376  def _writeProdConsum(self):
377  f= """
378 /**
379  * Gives the direct children
380  * @param {String} a path name
381  * @returns {Array} list of names of the the children.
382  */
383 %(name)s.prototype.getModules = function(name){
384  return this.topLevelData[name];
385 }
386 %(name)s.prototype.getTopFile = function(key){
387  return this.getFile(key);
388 }
389 %(name)s.prototype.getData = function(){
390  return [this.topLevelData, this.data];
391 }
392 // Producer and consumer have different structure to rest.
393 // Dont have file and type with them..
394 // to get file and type we need to take each name,
395 //look up the moduledata and find matches.
396 %(name)s.prototype.generalSearch = function(reg,term,repl, feature){
397  var matches ={}
398  for (var key in this.topLevelData){
399  var x = this.data[key][feature]
400  if(x.indexOf(term)>-1){
401  matches[key] = x.replace(reg,repl)
402  }
403  }
404  return matches;
405 }
406 %(name)s.prototype.typeSearch = function(reg,term,replce){
407  return this.generalSearch(reg,term,replce,this.TypeKey);
408 }
409 %(name)s.prototype.fileSearch = function(reg,term,replce){
410  return this.generalSearch(reg,term,replce,this.FileKey);
411 }
412  """
413  self._complexBase(self._prodConsP, f)
414 
415  def _complexBase(self,parentName, extra):
416  name = parentName
417  data = self._parents[name]
418  fileName, fullfilename= data["pfile"]
419  self._allJSFiles.append(fileName)
420  all = """
421 /*
422  Base object for thing of the type:
423  It also inherits from DictParent.
424 */
425 function %(name)s(data,topLevel, nameList,indexList){
426  this.data = data;
427  this.topLevelData=topLevel;// e.g. pathNames to module names
428  this.fixedNameList = nameList; // e.g.names of paths
429 }
430 %(name)s.prototype = new %(dict)s(this.data);
431 
432 %(name)s.prototype.getKeys = function(){
433  return Object.keys(this.topLevelData)
434 }
435  """+ extra
436  with open(fullfilename, 'w') as parent:
437  parent.write(all%{"name": name, "dict": self._dictP})
438 
439 # Helper function which gets parameter details.
440 def getParameters(parameters):
441  all =[]
442  if(not parameters):
443  return []
444  for (name,valType) in six.iteritems(parameters):
445  theT= (valType.configTypeName() if(
446  hasattr(valType,"configTypeName")) else "").split(" ",1)[-1]
447  temp = re.sub("<|>|'", "", str(type(valType)))
448  generic, spec = temp.split(".")[-2:]
449  doTypes(spec,generic)
450  theList=[name]
451  if(isinstance(valType,cms._Parameterizable)):
452  theList.append(getParameters(valType.parameters_()))
453  elif(isinstance(valType,cms._ValidatingListBase)):
454  theList.append(listBase(valType))
455  else:
456  if(isinstance(valType,cms._SimpleParameterTypeBase)):
457  value = valType.configValue()
458  else:
459  try:
460  value = valType.pythonValue()
461  except:
462  value = valType
463  theList.append(value)
464  if(theT != "double" and theT !="int" and not isinstance(valType, str)):
465  if(not valType.isTracked()):
466  theList.append("untracked")
467  theList.append(theT)
468  all.append(theList)
469  return all
470 
471 def listBase(VList):
472  # we have a list of things..
473  #loop around the list get parameters of inners.
474  #Since ValidatingListBases "*usually* have the same types
475  #throughout, just test first --is this a rule?
476  # Find out and if needed move these ifs to the loop.
477  if(not VList):return ""
478  first = VList[0]
479  if(isinstance(first,cms._Parameterizable)or
480  isinstance(first,cms._ValidatingListBase)):
481  anotherVList=False
482  if(isinstance(first,cms._ValidatingListBase)):
483  anotherVList=True
484  outerList=[]
485  for member in VList:
486  if(member.hasLabel_()):
487  name = member.label()
488  else:
489  name = member.configTypeName()
490  innerList=[name]
491  if(not anotherVList):
492  innerList.append(getParameters(member.parameters_()))
493  else:
494  innerList.append(listBase(member))
495  temp = re.sub("<|>|'", "", str(type(member)))
496  generic, spec = temp.split(".")[-2:]
497  doTypes(spec,generic)
498  innerList.append(spec)
499  outerList.append(innerList)
500  return outerList
501  elif(isinstance(first,cms._SimpleParameterTypeBase)):
502  return ",".join(i.configValue() for i in VList)
503  elif(isinstance(first,cms._ParameterTypeBase)):
504  return ",".join(i.pythonValue() for i in VList)
505  else:
506  #Most things should at least be _ParameterTypeBase, adding this jic
507  try:
508  outcome = ",".join(str(i) for i in VList)
509  return outcome
510  except:
511  return "Unknown types"
512 
513 
514 dictFeatures=["Parameters", "Type", "File", "oType"]
515 # Used to enforce dictionary in datafiles.
516 def getParamSeqDict(params, fil, typ, oType):
517  d={}
518  d[dictFeatures[0]] = params
519  d[dictFeatures[1]] = typ
520  d[dictFeatures[2]] = fil
521  d[dictFeatures[3]] = oType
522  return d
523 
524 class visitor:
525  def __init__(self, df, cfg):
526  self._df = df
527  self._underPath = [] # direct children of paths
528  #(includes children of modules)
529  self._modulesToPaths={} # map from modules to index of path -
530  self._seq = 0
531  self._pathLength=0
532  self._currentName =""
533  self._oldNames =[]
534  self._done =[]
535  self._seqs={}
536  self._typeNumbers = {}
537  self._innerSeq = False
538  self._reg= re.compile("<|>|'")
539  self.config = cfg
540 
541  def _finalExit(self):
542  self._pathLength+=1
543  temp = self._underPath
544  self._underPath =[]
545  return temp
546 
547  # Only keep in if we manage to move doModules into this class
548  def _getType(self,val):
549  return re.sub(self._reg, "", str(type(val))).split(".")[-2:]
550 
551  """
552  Do Module Objects e.g. producers etc
553  """
554  def _doModules(self,modObj, dataFile, seq, seqs, currentName, innerSeq):
555  #name = modObj.label_()
556  name = self.config.label(modObj)
557  # If this is not an inner sequence then we add so it can go to paths
558  if(seq==0):
559  self._underPath.append(name)
560  else:
561  seqs[currentName].append([name])
562  # If we've seen this name before, no need to compute values again.
563  # we need to put this mod/seq name under the path name in the dict
564  if(name not in self._modulesToPaths.keys()):
565  self._modulesToPaths[name] =[self._pathLength]
566  filename = modObj._filename.split("/")[-1]
567  generic,specific = self._getType(modObj)
568  doTypes(specific,generic)
569  d = getParamSeqDict(getParameters(modObj.parameters_()),
570  filename, specific, modObj.type_())
571  theS='"%s":%s'
572  if(len(self._modulesToPaths) > 1): theS=","+theS
573  dataFile.write(theS%(name, JSONFormat(d)))
574  else:
575  #oldMods.append(name)
576  self._modulesToPaths[name].append(self._pathLength)
577 
578  def enter(self, value):
579  if(isinstance(value,cms._Module)):
580  self._doModules(value, self._df, self._seq,
581  self._seqs, self._currentName, self._innerSeq)
582  elif(isinstance(value,cms._Sequenceable)):
583  generic,specific = self._getType(value)
584  doTypes(specific, generic)
585  if(isinstance(value, cms._ModuleSequenceType)):
586  if(len(self._currentName) >0):
587  self._oldNames.insert(0, self._currentName)
588  name = self.config.label(value)
589  #name = value.label_()
590  if(self._seq >0):
591  # this is an inner sequence
592  self._innerSeq = True;
593  self._seqs[self._currentName].append([name])
594  else:
595  self._underPath.append(name)
596  self._seqs[name] = []
597  self._currentName = name
598  self._seq +=1
599  else:
600  # just sequenceable..
601  name = value.__str__()
602  if(self._currentName):
603  self._seqs[self._currentName].append([name, specific])
604  else:
605  self._underPath.append(value.__str__())
606  if(name not in self._done):
607  d = getParamSeqDict([], "", specific, "")
608  self._df.write(',"%s":%s'%(name,JSONFormat(d)))
609  self._done.append(name)
610 
611  def leave(self, value):
612  if(isinstance(value,cms._Module)):
613  return
614  elif(isinstance(value,cms._Sequenceable)):
615  # now need to determine difference between
616  #ones which have lists and ones which dont
617  if(isinstance(value, cms._ModuleSequenceType)):
618  #name = value.label()
619  name = self.config.label(value)
620  if(name in self._oldNames):self._oldNames.remove(name)
621  if(self._currentName == name):
622  if(self._oldNames):
623  self._currentName = self._oldNames.pop(0)
624  else:
625  self._currentName=""
626  if(name not in self._done):
627  generic,specific = self._getType(value)
628  d = getParamSeqDict(self._seqs.pop(name), "", specific, "")
629  self._df.write(',"%s":%s'%(name,JSONFormat(d)))
630  self._done.append(name)
631  self._seq -=1
632  if(self._seq==0): self._innerSeq = False;
633 
634 class html:
635  def __init__(self,name,js,items,theDir, helperDir, pN,pFN):
636  jqName = "%scfgJS.js"%(theDir)
637  jqLocal = "%scfgJS.js"%(helperDir)
638  css = "%sstyle.css"%(theDir)
639  cssL = "%sstyle.css"%(helperDir)
640  js.insert(0,jqLocal)
641  self._jqueryFile(jqName, pN,pFN)
642  self._printHtml(name,self._scripts(js),self._css(css, cssL),
643  self._items(items), self._searchitems(items))
644 
645  def _scripts(self, js):
646  x = """
647 <script type="text/javascript" src="%s"></script>"""
648  return "\n".join([x%(i) for i in js])
649 
650  def _items(self, items):
651  l= """
652 <option value=%(n)s data-base="%(d)s" data-files="%(f)s"> %(n)s</option>"""
653  s= [l%({"n":x,"f":y["data-files"],"d":y["data-base"]})
654  for x,y in six.iteritems(items)]
655  return " ".join(s)
656 
657  def _searchitems(self,items):
658  b = """<option value="%(name)s" data-base="%(d)s">%(name)s</option> """
659  return "\n ".join([b%({"name": x, "d":y["data-base"]})
660  for x,y in six.iteritems(items)])
661 
662  def _printHtml(self,name,scrip,css,items, search):
663  with open(name,'w') as htmlFile:
664  htmlFile.write("""<!DOCTYPE html>\n<html>\n <head>
665  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
666  <title>cfg-browser</title>\n <script type="text/javascript"
667  src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
668  </script>\n %(s)s\n %(css)s\n </head>\n <body>
669  <div class="topBox topSpec">
670  <input type="submit" value="Edit" id="editMode" autocomplete="off"
671  disabled/>\n <div class="helpLinks">
672  <a href="#" class="nowhere" id="helpMouse" data-help="#help">help
673  </a></br/>
674  <a href="mailto:susie.murphy@cern.ch?Subject=CfgBrowserhelp"
675  target="_top">Contact</a>\n </div>\n <div id="help"> </div>
676  <span id="mode">Normal Mode</span>
677  <div class="topBox hideTopBox">hide</div>\n </div>
678  <a id="topOfPage"></a>\n <br/><br/><br/>\n <div class="outerBox">
679  <div class="boxTitle"> Pick\n <div class="dottedBorder">
680  <form onsubmit="return false;">\n <select id="showType">
681  %(items)s\n </select>\n <br/><br/>
682  <input type="submit" id="docSubmit" value="submit">
683  </form>\n </div>\n </div>
684  <div class="boxTitle"> Pick\n <div class="dottedBorder">
685  <form onsubmit="return false;">
686  <input type="text" id="searchWord"/>
687  <select id="searchType">\n %(search)s
688  </select> \n <span id="addSearch"> </span>
689  <br/><br/>
690  <input type="submit" value="Search" id="search"/>
691  <input type="checkbox" id="rmHilight" value="File"/>
692  <span>Don't show highlights</span>\n </form>
693  </div>\n </div>\n </div> \n <br/>
694  <input type="checkbox" id="ShowFiles" value="File"/>
695  <span>Show file names</span>\n <br/><br/>\n <script>
696  document.getElementById("searchType").selectedIndex = -1;\n </script>
697  <div id="posty"> </div>\n <br/>\n <div id="current"></div>
698  <br/>\n <div id="searchCount"></div>\n <div id="attachParams"></div>
699  <div class="rightScroll">\n <a href="#topOfPage">Back to Top</a>
700  <p>\n <a id="hide" href="javascript:;" >Hide All</a>\n </p>
701  </div>\n </body>\n</html>\n"""%{
702  "s":scrip,"css":css,"items":items, "search":search})
703 
704  def _css(self, css, cssLocal):
705  with open(css, 'w') as cssfile:
706  cssfile.write("""
707 *{\n font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif;\n}
708 .topBox{\n opacity:0.9;\n background-color:#dfdfdf;\n}\n.topSpec{
709  position:fixed;\n top:0;\n left:0;\n width:100%;\n height:2.5em;
710  border-radius:.9em;\n}\n.hideTopBox, .showTopBox{\n position:absolute;
711  top:2.5em;\n right:2%;\n width:auto;\n height:auto;\n padding: 0.2em;
712  font-weight:bold;\n cursor:pointer;\n border-radius:.3em;\n}\n.negative{
713  position:absolute;\n right:0;\n text-decoration:none;
714  font-weight:bold;\n color:#565656;\n}\n#mode{\n position:absolute;
715  right:50%; \n color:#808080;\n font-size:12pt;\n}\n#editMode,#normalMode{
716  position:absolute;\n left:.3em;\n top:.5em;\n}\n#save{
717  position:absolute;\n top:.5em;\n}\n.helpLinks{\n position:absolute;
718  right:1.3em;\n width:6.2em;\n text-align:right;\n}
719 /* divs for the Pick and Search boxes.*/\n.outerBox{\n width:100%;
720  overflow:hidden;\n}\n.boxTitle{\n float:left;\n margin-left:.6em;
721  color:#A9A9A9;\n}\n.dottedBorder{\n width:25em;\n height:4em;
722  border:.1em dashed #A9A9A9;\n padding:.6em;\n}\n/* -- */
723 /* Right scroll box. */\n.rightScroll{\n position:fixed;\n bottom:50%;
724  right:0; \n width:6.2em;\n text-align:right;\n border:.1em solid #A9A9A9;
725  opacity:0.4;\n background-color:#F0FFF0;\n}\n#hide{\n cursor:default;
726  opacity:0.2;\n}\nli{\n padding-left:.8em;\n}\nul{\n list-style-type:none;
727  padding-left:.1em;\n}\n/* Icons before list items. */\n.expand:before{
728  content:'›';\n}\n.expanded:before{\n content:'ˇ';\n}
729 .expand:before,.expanded:before{\n float:left;\n margin-right:.6em;\n}
730 .expand,.expanded{\n cursor:pointer;\n}\n/* colours of each. */
731 .Path,.EndPath{\n color:#192B33;\n}\n.Modules{ \n color:#800080;\n}
732 .SequenceTypes{\n color:#0191C8\n}\n.paramInner,.Types{\n color:#4B4B81;\n}
733 .param{\n color:#9999CC;\n margin-left:.8em;\n cursor:default; \n}\n.value{
734  color:#0000FF;\n}\n.type{\n color:#00CCFF;\n}
735 /* Header for what's showing */\n#current{\n color:#808080;\n font-size:12pt;
736  text-decoration:underline; \n}\n/* help settings */\n#help{
737  position:absolute;\n display:none;\n background:#ccc;\n border:.1em solid;
738  width:19em;\n right:15em;\n top:1.2em;\n}\nh5{\n font-style:normal;
739  text-decoration:underline; \n margin:0;\n font-size:9pt;\n}\nh6{
740  margin:0;\n color:#666666;\n}\n#attachParams{\n color:#192B33;\n}\nem{
741  color:#FFA500;\n}\n.cellEdit{\n border:.1em dotted #A9A9A9;\n cursor: text;
742 }\n""")
743  return """<link href="%s" rel="stylesheet" \
744  type="text/css"/>"""%(cssLocal)
745 
746  def _jqueryFile(self,name, pN,pFN):
747  with open(name, 'w')as jq:
748  jq.write("""
749 \n$(document).ready(function(){ \n//Object used to get all details
750 var processName="%s";\nvar processFileName ="%s";
751 var CURRENT_OBJ;\nvar searchShowing= false;\nvar showParams = false
752 var alreadyShowing = false\nvar topClass = "Top"\nvar searching = false
753 var expandDisable = false;\nvar hideVisible=false //nothing is expanded.
754 // ---\n/*\n Functions used to abstract away name of function calls
755  on the object (CURRENT_OBJ).
756  (i.e. so function names can easily be changed.)\n*/
757 function baseParams(inputs){\n return CURRENT_OBJ.getParameters(inputs);\n}
758 function baseInnerParams(inputs, index){
759  return CURRENT_OBJ.getInnerParams(inputs, index);\n}
760 function baseType(inputs){\n return CURRENT_OBJ.getType(inputs);\n}
761 function baseFile(inputs){\n return CURRENT_OBJ.getFile(inputs);\n}
762 function baseTopFile(inputs){\n return CURRENT_OBJ.getTopFile(inputs);\n}
763 // --- Show some inital data operations ---\n/*\n Show something new!\n*/
764 $(document).on('click', '#docSubmit', function(e){
765  var $elem = $('#showType :selected')
766  //get the function we want and the lists\n setCURRENT_OBJ($elem)\n
767  addData($elem.attr("value"), CURRENT_OBJ.getKeys());\n searchShowing= false;
768 });\n/*\n Add data to the html.\n*/
769 function addData(docType, data, dataNames){
770  $("#editMode").removeAttr("disabled"); \n var dataNames = dataNames || data;
771  if(alreadyShowing){\n //need to click cancel if its active.
772  goNormal($("#normalMode"));\n if(!searching)$("#searchCount").html("")
773  invisibleHide()\n paramOptions(false)
774  $(document.getElementsByTagName('body')).children('ul').remove();\n }
775  $("#current").html(docType)\n var gen = getGenericType(docType)
776  var ty = docType\n if(gen != undefined){\n var gL = gen.toLowerCase()
777  if(gL=="modules"||gL=="types") var ty= gen;\n }
778  var $LI = $(document.createElement('li')
779  ).addClass("expand").addClass(ty).addClass(topClass);
780  docType= docType.toLowerCase()\n var showTypes = false\n showParams = true
781  switch(docType){\n case "producer":\n case "consumer":
782  showParams = false\n paramOptions(true)
783  $LI.addClass("Modules")\n showTypes = true\n break;
784  case "modules":\n $LI.addClass("Modules")\n showTypes = true
785  //showParams = true\n break;\n }
786  var $UL = addTopData(data,$LI,showTypes,dataNames)\n alreadyShowing = true;
787  $UL.appendTo('#attachParams');\n}\n/*
788  Used to add the top level data to html.\n*/
789 function addTopData(data,$LI,types,dataName){
790  var dataName = dataName || data;
791  var $UL = $(document.createElement('ul'));\n var doNormalFile = false;
792  var files = document.getElementById("ShowFiles").checked\n if(files){
793  try{\n baseTopFile(dataName[0])\n }\n catch(e){
794  doNormalFile = true;\n }\n }\n for(var i=0; i < data.length;i++){
795  var n = dataName[i]\n var t = data[i];
796  if(types)t += " ("+baseType(n)+")"\n if(files){
797  if(doNormalFile)var file = baseFile(n)
798  else var file = baseTopFile(n)\n t += " ("+file+")"}
799  $UL.append($LI.clone().attr("data-name",n).html(t));\n }\n return $UL;\n}
800 // --- end of inital showing data operations ---\n
801 // --- search operations ---\n
802 //$(document).on('click', "[name='searchTerm1']", function(e){
803 //$(document).on('click', "#searchType option", function(e){
804 $(document).on('click', '#searchType', function(e){\n $("#addSearch").empty()
805  var tname= $(this).text().toLowerCase();\n var sel= jQuery('<select/>', {
806  id:"searchType2"\n })
807  var li = (tname =="modules"|| tname == "producer"|| tname == "consumer")?
808  ["Name", "Type", "File"]: ["Name", "File"]\n for(var i in li){
809  var x = li[i]\n jQuery('<option/>',{\n value:x,\n text:x
810  }).appendTo(sel)\n }\n sel.appendTo("#addSearch");\n});\n/*
811  Current search only searches for top level things.\n*/
812 $(document).on('click','#search', function(e){\n searching = true
813  var first = $('#searchType :selected')\n if(first.length ==0){
814  window.alert("Please chose a search type."); \n return;\n }
815  var doc = first.text()\n var searchTerm = $('#searchWord').val()
816  var $elem = $('option[value="'+doc+'"]')\n setCURRENT_OBJ($elem)
817  var reg = new RegExp(searchTerm, 'g')
818  if($('#rmHilight').prop('checked'))\n var fin = searchTerm\n else
819  var fin = "<em>"+searchTerm+"</em>"
820  switch($('#searchType2 :selected').text()){\n case "File":
821  $("#ShowFiles").prop('checked', true);
822  var items = CURRENT_OBJ.searchFile(reg,searchTerm,fin)
823  var matchCount = fileTypeSearch(doc,items,true)\n break;
824  case "Type":\n var items = CURRENT_OBJ.searchType(reg,searchTerm,fin)
825  var matchCount = fileTypeSearch(doc,items,false)\n break
826  case "Name":\n var matchCount = easySearch(searchTerm,reg, doc, fin)
827  }\n $("#searchCount").html(matchCount+ " found.")\n searching = false;
828  searchShowing= true;\n});\n/*\n Used when searching top level elements.
829  i.e. Module names, path names etc.
830  We dont need to delve into any dictionaries, we just use the keys.\n*/
831 function easySearch(term,reg, doc, fin){\n var keys = CURRENT_OBJ.getKeys()
832  var matches = keys.filter(function(e, i, a){return (e.indexOf(term)>-1)})
833  var highlights = matches.map(function(e,i,a){
834  return e.replace(reg, fin)})
835  addData(doc, highlights,matches)\n return matches.length\n}\n/*
836  When searching type or file names of top level elements.\n*/
837 function fileTypeSearch(doc,items,file){
838  var newFunct = function(name){return items[name]}\n if(file){
839  var backup = baseFile\n var backup2 = baseTopFile
840  baseFile = newFunct \n baseTopFile = newFunct\n }\n else {
841  var backup = baseType\n baseType = newFunct\n }
842  var matches = Object.keys(items)\n addData(doc, matches)\n if(file){
843  baseFile = backup\n baseTopFile = backup2\n }\n else baseType = backup
844  return matches.length\n}\n// --- end of search operations ---\n
845 // --- edit operations ---\n// variables needed:
846 // will contain the highest parents, where something *might*
847 // be changed in its children.\nvar $potential=[]
848 // dict, keys are parentNames and values are lists of children changed
849 // under that parent\nvar parChildNames={}\n
850 $(document).on('click', '#editMode', function(e){\n if(searchShowing)
851  var dataType = $('#searchType :selected').attr("data-base")
852  else var dataType = $('#showType :selected').attr("data-base")
853  // Temp restriction of editing SequenceTypes e.g. Paths,EndPaths etc.
854  if(dataType=="modSeqCreate"){
855  window.alert("At the moment editing for SequenceTypes"+
856  " has been disabled.");\n return;\n }
857  else if (dataType == "prodConCreate"){
858  window.alert("Sorry, it is currently not possible to "+
859  "edit producers and consumers.");\n return;\n }
860  if(CURRENT_OBJ == undefined)return;
861  // this is editing mode, turn off expansion\n expandDisable = true;
862  $("#mode")[0].textContent = "Edit Mode"\n $(this).attr("value", "Cancel");
863  var l = ($(this).width()/ parseFloat($("body").css("font-size"))+2.5)+"em"
864  $(this).after(jQuery('<input>', {\n type:"submit",
865  value:"Save",\n id:"save"\n }).css({\n left:l\n}));
866  $(this).attr("id", "normalMode")\n makeEditable(searchShowing);
867  searchShowing = false;\n});\n/*
868  Adds in div elements to make cells editable.\n*/
869 function makeEditable(rmSearch){\n // add editable div to everything showing.
870  var todo = jQuery.makeArray($(".Top"));\n while(todo.length){
871  var e = $(todo.pop())\n if(rmSearch)
872  e.html(e.html().replace(/(<em>|<\/em>)/g, ""))
873  // we have the item.. lets get children
874  var kids = jQuery.makeArray(e.children());
875  // add divs to all children.\n while(kids.length){
876  var k = $(kids.pop())\n var tag = k.prop("tagName")\n
877  if(tag == "SPAN"){\n if(k.prop("class")!="type")
878  k.html('<div class="cellEdit" contenteditable>'+k.html()+'</div>')
879  continue\n }\n if(tag =="LI"){
880  // add the div but dont get children
881  $(k.contents()[0]).wrap('<div class="cellEdit" contenteditable />');
882  }\n // check if have any children
883  var moreKids = jQuery.makeArray(k.children());
884  if(moreKids.length){\n kids = kids.concat(moreKids)\n }
885  }\n // now do current one
886  $(e.contents()[0]).wrap('<div class="cellEdit" contenteditable />');\n }
887 }\n/*\n A cell which is editable has been clicked.\n*/
888 $(document).on('click', '.cellEdit', function(e){
889  // we're in edit so things have a div parent over the text.
890  // so get parent to get the thing we want.
891  var $itemChanged = $(this).parent()
892  // now go up until we find greatest parent(item with class==topClass)
893  var classes = $itemChanged.attr("class")\n var $parent = $itemChanged
894  while(classes.indexOf(topClass)==-1){\n $parent = $parent.parent();
895  classes = $parent.attr("class") || "";\n }
896  var parentName = $parent.attr("data-name");
897  // doesnt matter if parent and child are the same.
898  var parents = Object.keys(parChildNames)
899  if(parents.indexOf(parentName)>-1){\n // already been edited.
900  var kids = parChildNames[parentName]
901  if(kids.indexOf($itemChanged.attr("data-name"))==-1){
902  kids.push($itemChanged)\n }\n }\n else{
903  parChildNames[parentName]=[$itemChanged]\n }\n $potential.push($parent)
904 });\n//--- end of edit operations ---\n// --- start of save operations ---\n/*
905  Save any changes.\n*/\n$(document).on('click', '#save', function(e){
906  var allData = CURRENT_OBJ.getData();\n var oldData = allData[0]
907  goNormal($("#normalMode"));\n if(allData.length >1){
908  var top = allData[0];\n var rest = allData[1];
909  var changed = save(deepCopy(top),deepCopy(rest))\n }\n else{
910  var changed = save(deepCopy(allData[0]));\n }
911  if(Object.keys(changed).length ==0){
912  window.alert("Nothing was changed.");\n $potential=[]
913  parChildNames={}\n return \n }
914  //$('#svg_export_form > input[name=svg]').val("jhgjhg");
915  changed["processName"]= processName
916  changed["processFileName"]= processFileName\n $("#posty").empty()
917  var form = jQuery('<form/>', {\n id:"edited_write",\n method:"POST",
918  async: "false",\n enctype: "multipart/form-data",
919  style:"display:none;visibility:hidden",\n })\n jQuery('<input/>', {
920  type:"hidden",\n name:"changed",\n value:JSON.stringify(changed),
921  }).appendTo(form)\n form.appendTo("#posty")\n $('#edited_write').submit();
922  $potential=[]\n parChildNames={}\n});\n/*
923  Go to normal viewing mode. Discard any changes.\n*/
924 $(document).on('click', '#normalMode', function(e){
925  //remove all cell edit Divs\n goNormal($(this));\n //$potential =[]
926  //parChildNames={}\n});\n/*\n Couldn't find built-in deep clone or copy.\n*/
927 function deepCopy(obj){\n if(obj instanceof Array){\n var copy=[]
928  obj.forEach(function(x,i,a){copy[i]= deepCopy(x)})\n return copy\n }
929  else if(obj instanceof Object){\n var copy ={}\n for (key in obj){
930  copy[key] = deepCopy(obj[key])\n }\n return copy\n }\n return obj
931 }\n\n/*\n Returns a dict of everything that has changed.\n*/
932 function save(data, restData){\n var allChanged={}\n var done=[]
933  for(var i in $potential){\n var parent = $potential[i];
934  // we have the parent.
935  var oldParentName = $(parent).attr("data-name");
936  //bit iffy, can have same parent name multiple times? todo
937  if(done.indexOf(oldParentName)>-1) continue\n done.push(oldParentName)
938  if(typeof restData =='undefined'){
939  var allDict = deepCopy(data[oldParentName])
940  var allOldData = allDict["Parameters"]
941  var childChanged = parChildNames[oldParentName]
942  var oldToNew= chil(childChanged,parent, true)
943  if(oldToNew.length ==0) continue
944  var newpar = blah(oldToNew, oldParentName, allOldData, parent, false)
945  tempDict = allDict\n tempDict["Parameters"] = allOldData
946  allChanged[newpar] = tempDict\n if(oldToNew.length>0){
947  window.alert("Something went wrong, I did not find all changes.");
948  }\n }\n else{
949  // we have one data for the parents and one for rest
950  var allDict = deepCopy(data[oldParentName])
951  var allKids = allDict["Parameters"]\n var tem ={}
952  var childChanged = parChildNames[oldParentName];
953  var oldToNew = chil(childChanged,parent, false);
954  //if(Object.keys(oldToNew).length ==0) continue
955  if(oldToNew.length ==0) continue\n for (var y in allKids){
956  var n = allKids[y]\n var allOld2 = deepCopy(restData[n])
957  var allOldData = allOld2["Parameters"]
958  // blah chanhes allOldData
959  var newpar = blah(oldToNew, n, allOldData, parent, true)
960  allOld2["Parameters"]= allOldData\n tem[newpar] = allOld2
961  }\n var newParentName = $(parent).contents()[0].nodeValue
962  //allChanged[newParentName]= tem\n tempDict = allDict
963  tempDict["Parameters"] = tem\n allChanged[newParentName] = tempDict
964  continue\n }\n }\n return allChanged\n}\n/*
965  These three functions are used for getting data from
966  a structure such as [{},{},{}]\n*/\nfunction getValue(list, key){\n var re=[]
967  for(x in list){\n di = list[x]\n k = Object.keys(di)[0]
968  if(k==key)re.push(di[k])\n }\n return re\n}\nfunction getKeys(list){
969  var keys = []\n for (x in list)\n keys.push(Object.keys(list[x])[0])
970  return keys\n}\nfunction deleteValue(list, k,d){\n var inde =-1
971  var found = false\n for(var x in list){\n var di = list[x]
972  var key = Object.keys(di)[0]\n if(key==k && di[key]==d){
973  found = true\n inde = x\n break\n }\n }
974  if(found)list.splice(inde,1)\n}\n/*
975  allOldData will be changed with the new data.\n*/
976 function blah(oldToNew, oldParentName, allOldData, parent){
977  var newpar = oldParentName\n var keys = getKeys(oldToNew)
978  if(keys.indexOf(oldParentName)>-1){\n // parent is in
979  var tDatas = getValue(oldToNew,oldParentName);
980  for (var x in tDatas){\n var tData = tDatas[x]
981  if(tData["i"]==0 && tData["p"].length ==0){
982  var newpar = tData["new"];\n // this isnt finding tData
983  deleteValue(oldToNew, oldParentName,tData);\n }\n }\n }
984  // okay so here we have everything for this parent.
985  // now need to loop through the old data and changed for new.
986  if(oldToNew.length >0){
987  loopData(allOldData,oldToNew,[oldParentName], [0]);\n }
988  return newpar\n}\n//need to remember that current format is
989 //[name, parameters,type,optionalType]\n/*\n Loop around the data, \n*/
990 function loopData(thelist, items, parents, pIndex){\n for(var x in thelist){
991  var y = thelist[x]\n if(y instanceof Array){
992  // okay if array, we have full line
993  if(typeof y[0] == "string" && y[1] instanceof Array){
994  // this is what we want.\n var theName = y[0]
995  var rest = y[1]\n var types = [y[2]]\n if(y.length == 4)
996  types.push(y[3])\n // okay, name of this is theName == parent
997  // the index of this is x\n parents.unshift(theName)
998  pIndex.unshift(x)\n loopData(rest, items, parents, pIndex);
999  parents.shift()\n pIndex.shift()
1000  rightOne(thelist,x,theName,items,parents,pIndex)
1001  for(var index in types){\n var item = types[index]
1002  rightOne(thelist,x,item,items,parents,pIndex)\n }
1003  continue\n }
1004  if(y[0] instanceof Array && y[1] instanceof Array){
1005  // y1 is a parameter\n // y2 is a parameter
1006  for(var e in y){\n loopData(y[e],items,parents,pIndex);
1007  }\n continue;\n }\n // we are here,
1008  //so we have something that does not have parameters in a list
1009  var theName = y[0]\n for(var index in y){\n if(index >0){
1010  parents.unshift(theName) \n pIndex.unshift(x)\n }
1011  var item = y[index]
1012  rightOne(thelist,x,item,items,parents,pIndex)\n if(index >0){
1013  parents.shift()\n pIndex.shift()\n }\n }
1014  continue;\n }\n else {
1015  rightOne(thelist,x,y,items,parents,pIndex)\n }\n }\n}\n/*
1016  Helper function. We have a match, now change old values for new values.\n*/
1017 function rightOne(thelist,x,y,items,parents,pIndex){
1018  if(getKeys(items).indexOf(y)>-1){
1019  // we know that we have a match, but are indexes the same?
1020  // index will be in the same list so we can use x
1021  var dis = getValue(items, y)\n for (inde in dis){
1022  var di= dis[inde]\n if(x == di["i"]){
1023  if(arrayCompare(parents, pIndex,di["p"],di["pIndex"] )){
1024  //okay we can be sure we are changing the right thing.
1025  if(thelist[x] instanceof Array){
1026  for(var ind in thelist[x]){\n var z = thelist[x][ind]
1027  if(y == z){\n thelist[x][ind] = di["new"]
1028  break;\n } \n }\n }
1029  else{\n thelist[x] = di["new"]\n }
1030  deleteValue(items,y,di)\n }\n }\n }\n }\n}\n/*
1031  Returns true if arrays a1 is identical to a2 and
1032  a1Index is identical to a2Index.\n*/
1033 function arrayCompare(a1, a1Index, a2, a2Index) {
1034  if (a1.length != a2.length)return false;
1035  for (var i = 0; i < a1.length; i++) {
1036  if (a1[i] != a2[i] || a1Index[i] != a2Index[i]) {
1037  return false;\n }\n }\n return true;\n}\n/*
1038  Take in the children that might have been changed.
1039  If something has been changed, adds to a dictionary
1040  dictionary format is [data-name]={
1041  "new": newvalue, "i":data-index, "p":[parentNames],
1042  "pIndex": [indicies of parents]}
1043  TODO, need a new format, what if children have
1044  the same data-name and both are changed?\n*/
1045 function chil (childChanged, parent, addParent){\n var oldToNew=[]
1046  for (var x in childChanged){\n var child = childChanged[x]
1047  // we need to check if the child has been changed.
1048  var oldval = child.attr("data-name");
1049  var isSpan = child.prop("tagName") == "SPAN"\n var newval = isSpan ?
1050  child.contents().text(): child.contents()[0].nodeValue;
1051  //remove any enclosing brackets
1052  newval = newval.trim().replace(/\(.*\)$/, "");
1053  oldval = oldval.trim().replace(/\(.*\)$/, "");
1054  if(oldval==newval)continue\n else{
1055  //child has been changed.\n //we want to keep 4 pieces of data.
1056  //1. old name, new name\n //2. data-index
1057  //3. list of direct parents.\n //4. indexes of all parents.
1058  var inner ={}\n inner["new"] = newval;
1059  //depends if it was a span or not. Span means we use parents.
1060  inner["i"]= (isSpan? child.parent().attr("data-index"):
1061  child.attr("data-index")) || 0\n var allP = child.parents()
1062  var pNames =[]\n var pIndex =[]
1063  for(var y=0; y < allP.length; y++){\n var p = $(allP[y])
1064  var tag = p.prop("tagName")
1065  if(p.attr("data-name") == parent.attr("data-name")){
1066  if(addParent){\n pNames.push(parent.attr("data-name"))
1067  pIndex.push(parent.attr("data-index") || 0);\n }
1068  break;\n }\n else if(tag == "LI"){
1069  pNames.push(p.attr("data-name"));
1070  pIndex.push(p.attr("data-index") || 0);\n }\n }
1071  inner["p"] = pNames\n inner["pIndex"] = pIndex\n var t={}
1072  t[oldval]= inner\n oldToNew.push(t)\n }
1073  } // end of childchanged loop\n return oldToNew\n}
1074 // --- end of save operations ---
1075 // --- Expand and show more data operations ---\n/*
1076  Used when in edit mode to stop any items being added to the webpage.
1077  More items added after edit mode- they wont be editable, and when you
1078  click to edit something it loads its children.\n*/
1079 $(document).on('click','.expand, .expanded', function(event){
1080  if(expandDisable){\n event.stopImmediatePropagation();\n }\n});\n/*
1081  Retrieves and expands elements whose objects have multiple lists
1082  (i.e. onese who's data-base !=simpleData)\n*/
1083 $(document).on('click', '.Consumer.expand,.Producer.expand,'
1084 +'.Path.expand,.EndPath.expand ',function(event){
1085  var allModules = CURRENT_OBJ.getModules($(this).attr('data-name'));
1086  var UL = addParams(this,allModules)\n $(this).append(UL);
1087  event.stopPropagation();\n});\n/*\n Adds parameters onto objects.\n*/
1088 $(document).on('click','.Modules.expand,.SequenceTypes,.Types.expand'
1089 , function(event){\n if(showParams){\n addParams(this);\n }
1090  event.stopPropagation();\n});\n/*\n Hides/Shows children from class param.
1091 */ \n$(document).on('click', '.paramInner.expand, .paramInner.expanded',
1092  function(event){\n if($(this).children('ul').length ==0){
1093  // find parents\n var parents = findParents(this)
1094  var result = baseInnerParams(parents,parseInt(
1095  $(this).attr("data-index")) )[1]
1096  addParams(this, result);\n }\n else{
1097  //children already added, so just hide/show.
1098  $(this).children('ul').toggle();\n }\n event.stopPropagation();
1099  });\n/*\n Find the parents of a child.\n*/\nfunction findParents(child){
1100  var parents =[$(child).attr("data-name")]
1101  var theParent = $(child).attr("data-parent")
1102  while(theParent !=undefined){ \n var child = $(child).parent();
1103  if(child.prop("tagName")=="UL") continue;
1104  parents.unshift(child.attr("data-name"));
1105  theParent = child.attr("data-parent");\n }\n return parents\n}\n/*
1106  Helper function: returns filename appended onto val.\n*/
1107 function getFile(theName){\n var f = baseFile(theName)
1108  if(f)return theName+=type(f)\n return theName\n}\n/*
1109  Add params to the object. Object can be of any type
1110  (normally module or param).
1111  Will be used by modules adding parameters, psets adding parameters.\n*/
1112  var $LIBasic = $(document.createElement('li')).attr("class","param");
1113  var $LIExpand = $LIBasic.clone().attr("class","expand");\n
1114 function addParams(obj, params){
1115  var fileChecked = document.getElementById("ShowFiles").checked
1116  var $span = $(document.createElement("span"));
1117  var $typeSpan = $span.clone().addClass("type");
1118  var $valSpan = $span.clone().addClass("value");
1119  var $UL = $(document.createElement("ul"));
1120  var $objName = $(obj).attr('data-name');\n\n if(!params)
1121  params = baseParams($objName)\n for(var i =0; i < params.length; i++){
1122  var all = params[i].slice() // make copy of it
1123  var isList= typeof(all)=="object"
1124  var theName = isList ? all.shift(): all
1125  var typ= !isList || !all.length ? baseType(theName): all.pop()
1126  var gen = getGenericType(typ)
1127  var spt = $typeSpan.clone().attr("data-name",typ).text(type(typ))
1128  if(fileChecked) text = getFile(theName)
1129  if(isList && typeof(all[0]) == "object"){\n // PSets
1130  var cloLI = doLI(false,theName,i,"paramInner",spt)
1131  cloLI.attr("data-parent", $objName)\n }
1132  else if(baseParams(theName)){\n // Modules or sequences
1133  var cloLI = doLI(false,theName,i,gen,spt)\n }\n else{
1134  // Basic type, has no children\n var cloLI= doLI(true,theName,i)
1135  var value =""\n if(all.length)\n var value = all.shift()
1136  // formating so lots of strings look nicer\n var valDataName = value
1137  if(value.indexOf(",")>-1){
1138  value = "<ul><li>"+value.replace(/,/g, ",</li><li>")+"</li></ul>"
1139  }\n var add = type(typ)
1140  cloLI.append($valSpan.clone().attr("data-name",valDataName).html(value))
1141  cloLI.append($typeSpan.clone().attr("data-name",add).text(add))
1142  for(var p=0; p < all.length; p++){\n var n = type(all[p])
1143  cloLI.append($typeSpan.clone().attr("data-name",n).text(n))\n }
1144  } \n $UL.append(cloLI);\n }\n $(obj).append($UL);\n}\n
1145 function type(theName){\n return " ("+theName+")"\n}\n/*
1146  Helper function: Adds data to a LI.\n*/
1147 function doLI(basic,dataN,dataI,classes,html){
1148  if(basic) var $LI = $LIBasic.clone()\n else var $LI = $LIExpand.clone()
1149  $LI.attr("data-name", dataN).attr("data-index", dataI).text(dataN);
1150  if(classes)$LI.addClass(classes)\n if(html)$LI.append(html)\n return $LI
1151 }\n/*\n Box to show params has been clicked.\n*/
1152 $(document).on('click', '#ShowParams', function(e){
1153  if($(this).is (':checked')){\n showParams = true\n }\n else{
1154  $(this).next().hide()\n showParams = false\n }\n});\n/*
1155  Removes children from top level list elements.\n*/
1156 $(document).on('click', '#hide', function(e){
1157  //make sure not called when not needed.
1158  if($(this).css('cursor')!='default'){
1159  var selec = $(".expanded."+topClass).children("ul").hide()
1160  toggleExpand($(".expanded."+topClass ),e)\n invisibleHide()\n }\n});
1161 // --- end of expand and show more data operations ---
1162 // --- general helper operations and functions ---\n\n/*
1163  Return to normal viewing mode.\n*/\nfunction goNormal(it){
1164  expandDisable = false;
1165  $(".cellEdit").replaceWith(function() { return $(this).contents();});
1166  $("#save").remove()\n $("#mode")[0].textContent = "Normal Mode"
1167  it.attr("value", "Edit");\n it.attr("id", "editMode")\n}\n/*
1168  Set what the CURRENT_OBJ is.\n*/\nfunction setCURRENT_OBJ($element){
1169  var thefunction = $element.attr("data-base");
1170  var list = $element.attr("data-files").split(" ");\n if(list.length >1){
1171  CURRENT_OBJ = window[thefunction](list[1], list[0])\n } \n else{
1172  CURRENT_OBJ = window[thefunction](list[0])\n }\n}\n/*
1173  Add option in html to show/hide parameters.\n*/\nfunction paramOptions(bool){
1174  if(!bool){\n $("#attachParams").empty()\n return\n }
1175  var lb= jQuery('<label/>', {\n for:"ShowParams"\n })
1176  jQuery('<input/>', {\n type:"checkbox",\n id:"ShowParams",
1177  name:"ShowParams",\n value:"ShowParams",\n autocomplete:"off"
1178  }).appendTo(lb)\n lb.append("Show Parameters")
1179 lb.appendTo("#attachParams")\n}\n/*\n Small info about each option.\n*/
1180 $('#showType option').mouseover(function(){
1181  var docType = $(this).attr("value").toLowerCase();\n var info;
1182  switch(docType){\n case "producer":
1183  info="What's produced by each module."\n break;
1184  case "consumer":\n info="What's consumed by each module."
1185  break;\n default:\n info ="List of "+ docType+"s."\n }
1186  $(this).attr("title", info);\n});\n/*\n Small info about each option.\n*/
1187 $('span[name="Info"]').mouseover(function(){
1188  var docType = $(this).attr("value").toLowerCase();\n var info;
1189  switch(docType){\n case "producer":
1190  info="What's produced by each module."\n break;
1191  case "consumer":\n info="What's consumed by each module."
1192  break;\n default:\n info ="List of "+ docType+"s."\n }
1193  $(this).attr("title", info);\n});\n/*\n More info about what's shown.\n*/
1194 $("#helpMouse").hover(function(e) {
1195  $($(this).data("help")).stop().show(100);
1196  var title = "<h6>(Read the README file!)</h6><h4>Info:</h4> "
1197  var expl = "<h5>Colour codes:</h5> <h6><ul><li class='Path'>pathName"+
1198  " </li></ul><ul><li class='Modules'>Modules (e.g. "+
1199  "EDProducer, EDFilter etc)</li></ul><ul><li class='Types'>"+
1200  "Types (e.g. PSet)</li></ul><ul><li class='param'>"+
1201  "ParameterName:<span class='value'> value</span><span"+
1202  " class='type'>(type)</span></li></ul></h6>"
1203  var info ="<h5>The data</h5><h6>The headings you can choose from are"+
1204  " what was collected from the config file.<br/><br/> Any "+
1205  "change to the config file means having to run the script "+
1206  "again and then refresh this page (if same output file was "+
1207  "used).</h6><br/>"
1208  var tSearch="<h5>Search</h5><h6>Currently can only search by listing "+
1209  "what items you would like to be searched, and then what part"+
1210  " of each item.<br/><br/> I.e. search the producers for "+
1211  "certain names.</h6><br/>"
1212  var problems = "<h5>HTML/JSON/JS issues</h5><h6>If content isn't "+
1213  "loading,or json files cannot be loaded due to browser"+
1214  " security issues, try runing the local server created"+
1215  " by the script. This will be in the same place as "+
1216  "index.html.<br/><span class='Types'>'python cfgServer.py'"+
1217  " </span></h6><br/>"
1218  var editing = "<h5>Editing</h5><h6>In order to use the edit mode, you "+
1219  "need to run the cfgServer.py file, this will be in the "+
1220  "same directory as the index.html.<br/>Then go to <span"+
1221  " class='Types'> 'http://localhost:8000/index.html.'"+
1222  "</span><br/><strong>Please note that the editing of "+
1223  "SequenceTypes (i.e. Paths, EndPaths etc) and of producers"+
1224  " and consumers has been "
1225  $($(this).data("help")).html(title+expl+info+problems+editing);
1226  "disabled.</strong></h6><br/>"\n}, function() {
1227  $($(this).data("help")).hide();\n});\n/*
1228  These two functions hide/show the top box in browser.\n*/
1229 $(document).on('click', '.hideTopBox', function(e){
1230  $(".topSpec").animate({top: "-2.5em"}, 500);\n $(this).text("show");
1231  $(this).toggleClass("hideTopBox "+"showTopBox");\n});
1232 $(document).on('click', '.showTopBox', function(e){
1233  $(".topSpec").animate({top: "0em"}, 500);\n $(this).text("hide");
1234  $(this).toggleClass("showTopBox "+ "hideTopBox");\n});\n/*
1235  Stop some links from firing.\n*/\n$('a.nowhere').click(function(e)\n{
1236  e.preventDefault();\n});\n\n// Turn off any action for clicking help.
1237 $('a#help').bind('click', function() {\n return false;\n});\n/*
1238  If parameter value is a list, hide/show the list on click.\n*/
1239 $(document).on('click', '.param',function(event){\n if(!expandDisable){
1240  if($(this).find('ul').length >0){\n $(this).find('ul').toggle();\n }}
1241  event.stopPropagation();\n});\n/*
1242  Removes children from expanded paths or modules.\n*/
1243 $(document).on('click', '.expanded',function(event){
1244  var c = $(this).children('ul');\n if(c.length >0){\n $(c).remove();
1245  }\n event.stopPropagation();\n});\nfunction visibleHide(){
1246  $('#hide').css('opacity',1);\n $('#hide').css('cursor','pointer');
1247  hideVisible = true;\n}\nfunction invisibleHide(){
1248  $('#hide').css('opacity','');\n $('#hide').css('cursor','');
1249  hideVisible = false;\n}\n\n// Toggles class names.
1250 $(document).on('click','.expand, .expanded', function(event){
1251  if(!hideVisible && $(this).is('.expand')){\n visibleHide();\n }
1252  toggleExpand(this, event);\n});\n/*\n Helper function toggles class type.
1253 */\nfunction toggleExpand(me,event){\n $(me).toggleClass("expanded expand");
1254  event.stopPropagation();\n}\n});\n// end of jquery\n/*
1255 Function to load the JSON files.\n*/\nfunction loadJSON(theName){
1256  return $.ajax({\n type: "GET",\n url: theName,
1257  beforeSend: function(xhr){\n if (xhr.overrideMimeType)\n {
1258  xhr.overrideMimeType("application/json");\n }\n },
1259  contentType: "application/json",\n async: false,\n dataType: "json"
1260  });\n} \n"""%(pN,pFN))
1261 genericTypes={}
1262 
1263 def doTypes(spec, generic):
1264  genericTypes[spec] = generic
1265 
1266 def JSONFormat(d):
1267  import json
1268  return json.dumps(d)
1269 
1270 class server:
1271  def __init__(self, name):
1272  self.printServer(name)
1273 
1274  def printServer(self, name):
1275  with open(name, 'w') as f:
1276  f.write("""
1277 #!/usr/bin/env python\nimport SimpleHTTPServer\nimport SocketServer
1278 import shutil\nimport os\nimport cgi\nimport socket\nimport errno\n
1279 #Right now cannot deal with SequenceTypes\nclass CfgConvert:
1280  def __init__(self, obj):\n self._pName = obj["processName"]
1281  self._pFileN = obj["processFileName"]\n obj.__delitem__("processName")
1282  obj.__delitem__("processFileName")\n self._obj = obj
1283  self._func="cms.%s"
1284  self.header=\"""import FWCore.ParameterSet.Config as cms
1285 process = cms.Process('%(n)s')\nfrom %(fileN)s import *\n%(changes)s\n\n\"""
1286  def _doConversion(self):\n return self.header%(
1287  {"changes":self._doWork(self._obj),
1288  "n":self._pName,"fileN":self._pFileN})\n\n def _doWork(self, obj):
1289  result =""\n for key, value in six.iteritems(obj):
1290  _type = value["Type"]\n _file = value["File"]
1291  _params = value["Parameters"]\n _oType = value["oType"]
1292  if(_oType):\n _oType= "'%s',"%(value["oType"])
1293  #f = eval(func%(_type))\n if(type(_params)== list):
1294  if(len(_params)==0):
1295  result +="process.%s= cms.%s(%s)\\n"%(key,_type,_oType[:-1])
1296  else:\n params = self._convert(_params)
1297  result+="process.%s= cms.%s(%s%s)\\n"%(key,_type,_oType, params)
1298  #elif(type(_params)== dict):
1299  # return "Sorry path and endpaths can not currently be translated."
1300  #params = self._doWork(_params)\n
1301  #obj = f("actualType", *parameters)\n return result\n
1302  def _convert(self,params):
1303  # NOTE: params do not take names inside functions
1304  # It is: name = cms.type(value)\n # okay we have a list like
1305  #[name,params, untracked,type]||[name,params,type]
1306  # 2 format options in the params\n # 1. [["name", "value", "type"]]
1307  # 2. [["PsetName",[[as above or this]], "Pset"]]\n
1308  # At position 0 is name. list[0]==name or list[0]==list
1309  # then that will be all
1310  # At position 1 is value or list. list[1]==value||list.
1311  # At position 2 is type. list[2] == type || untracked.
1312  # If there is a position 3 its type. list[3]== type.
1313  if(all(type(x) == list for x in params)):
1314  return ",".join([self._convert(x) for x in params])
1315  length = len(params)\n if(length==1):
1316  if(type(params[0]) == list):\n # wont have params[1]etc
1317  # do inners\n return self._convert(params[0])
1318  #wrong format\n print "Error 01 %s"%(str(params))\n return ""
1319  if(length !=3 and length !=4):\n #wrong format
1320  print "Error 02 len is %s"%(str(params))\n return ""
1321  # okay get on with it.\n name = params[0]
1322  if(type(params[1])==list):\n # do listy things
1323  value = self._convert(params[1])\n else:\n value=params[1]
1324  ty = params[2]\n if(name==ty):\n name=""\n if(length==4):
1325  ty+="."+params[3]\n if(name== params[3]):\n name=""
1326  if("vstring" in ty):\n # split the value up by commas
1327  value = ",".join(["'%s'"%x for x in value.split(",")])
1328  elif("string" in ty):\n #surround string with quotation marks
1329  value = "%s"%(value)\n # okay now done with everything
1330  call= self._func%(ty)\n if(name):
1331  return"%s=%s(%s)"%(name,call,value)\n return"%s(%s)"%(call,value)\n
1332 class ServerHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):\n
1333  def do_GET(self):\n if(self.path == "/index.html"):
1334  # find out what cfg html folders we have below
1335  # and add each main html page to the index\n li = os.listdir(".")
1336  dEnd = "-cfghtml"
1337  dirs = [x for x in li if os.path.isdir(x) and x.endswith(dEnd)]
1338  name = "main.html"
1339  names = [os.path.join(x,name) for x in dirs if name in os.listdir(x)]
1340  tmpte = '<li><a href ="%(n)s">%(s)s</a></li>'
1341  lis = [tmpte%{"n":x,"s":os.path.split(x)[0].replace(dEnd, "")}
1342  for x in names]\n with open("index.html", 'w') as f:
1343  f.write(\"""\n<!DOCTYPE html>\n<html>\n <head>
1344  <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
1345  <title>cfg-browser</title>\n </head>\n <body>
1346  <h4>Configuration files:</h4>\n <ul>\n %s\n </ul>\n </body>
1347 </html>\n \"""%("".join(lis)))\n
1348  return SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)\n
1349  def do_POST(self):
1350  ctype,pdict= cgi.parse_header(self.headers.getheader('content-type'))
1351  bdy = cgi.parse_multipart(self.rfile,pdict)
1352  ch= " ".join(bdy[bdy.keys()[0]])\n self.conversion(eval(ch))
1353  self.writeFile()\n print "finished writing"\n
1354  def conversion(self, json):\n # Need to convert my json into config
1355  result = CfgConvert(json)._doConversion()
1356  with open("changed_cfg.py", 'w')as f:\n f.write(result)\n
1357  def writeFile(self):\n with open("changed_cfg.py", 'rb') as f:
1358  self.send_response(200)
1359  self.send_header("Content-Type", 'text/html')
1360  self.send_header("Content-Disposition",
1361  'attachment; filename="changed_cfg.py"')
1362  fs = os.fstat(f.fileno())
1363  self.send_header("Content-Length", str(fs.st_size))
1364  self.end_headers()\n shutil.copyfileobj(f, self.wfile)\n
1365 def main(port=8000, reattempts=5):\n if(port <1024):
1366  print \"""This port number may be refused permission.
1367 It is better to use a port number > 1023.\"""\n try:
1368  Handler = ServerHandler
1369  httpd = SocketServer.TCPServer(("", port), Handler)
1370  print "using port", port
1371  print "Open http://localhost:%s/index.html in your browser."%(port)
1372  httpd.serve_forever()\n except socket.error as e:
1373  if(reattempts >0 and e[0] == errno.EACCES):
1374  print "Permission was denied."
1375  elif(reattempts >0 and e[0]== errno.EADDRINUSE):
1376  print "Address %s is in use."%(port)\n else:\n raise
1377  print "Trying again with a new port number."\n if(port < 1024):
1378  port = 1024\n else:\n port = port +1
1379  main(port, reattempts-1)\n\nif __name__ == "__main__":\n import sys
1380  if(len(sys.argv)>1):\n try:\n port = int(sys.argv[1])
1381  main(port)\n sys.exit() \n except ValueError:
1382  print "Integer not valid, using default port number."\n main()
1383 """)
1384 
1385 def computeConfigs(args):
1386  pyList=[]
1387  for x in args:
1388  if(os.path.isdir(x)):
1389  # get all .py files.
1390  allItems = os.listdir(x)
1391  py = [os.path.join(x,y) for y in allItems if y.endswith(".py")]
1392  pyList.extend(computeConfigs(py))
1393  if(recurse):
1394  # print "recurse"
1395  # if we want to recurse, we look for everything
1396  dirs = []
1397  for y in os.listdir(x):
1398  path = os.path.join(x,y)
1399  if(os.path.isdir(path)):
1400  pyList.extend(computeConfigs([os.path.join(path,z)
1401  for z in os.listdir(path)]))
1402  elif(x.endswith(".py")):
1403  pyList.append(x)
1404  return pyList
1405 
1406 recurse=False
1407 
1408 def main(args,helperDir,htmlFile,quiet, noServer):
1409  dirName = "%s-cfghtml"
1410  # new dir format
1411  # cfgViewer.html
1412  # patTuple-html/
1413  # lower.html
1414  # cfgViewerHelper/
1415  # -json files
1416  pyconfigs = computeConfigs(args)
1417  tmpte = '<li><a href ="%(n)s">%(s)s</a></li>'
1418  lis=""
1419  found =0
1420  for x in pyconfigs:
1421  print("-----")
1422  # for every config file
1423  name = os.path.split(x)[1].replace(".py", "")
1424  dirN = dirName%(name)
1425  # we have the dir name now we only need
1426  # now we have thedir for everything to be stored in
1427  #htmlF = opts._htmlfile
1428  #htmldir= os.path.split(htmlFile)[0]
1429  #baseDir = os.path.join(htmldir,dirN)
1430  baseDir = dirN
1431  dirCreated = False
1432  if not os.path.exists(baseDir):
1433  os.makedirs(baseDir)
1434  dirCreated = True
1435  # base Dir under where the htmlFile will be.
1436  lowerHTML = os.path.join(baseDir, htmlFile)
1437  helper = os.path.join(helperDir, "")
1438  helperdir = os.path.join(baseDir, helper, "")
1439  if not os.path.exists(helperdir):
1440  os.makedirs(helperdir)
1441  print("Calculating", x)
1442  try:
1443  u = unscheduled(x, lowerHTML, quiet, helper,helperdir)
1444  except Exception as e:
1445  print("File %s is a config file but something went wrong"%(x))
1446  print("%s"%(e))
1447  continue
1448  print("Finished with", x)
1449  if(not u._computed and dirCreated):
1450  # remove any directories created
1451  shutil.rmtree(baseDir)
1452  continue
1453  found +=1
1454  lis += tmpte%{"n":os.path.join(dirN,htmlFile),"s":name}
1455  with open("index.html", 'w')as f:
1456  f.write("""
1457 <!DOCTYPE html>
1458 <html>
1459  <head>
1460  <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
1461  <title>cfg-browser</title>
1462  </head>
1463  <body>
1464  <h4>Configuration files:</h4>
1465  <ul>
1466  %s
1467  </ul>
1468  </body>
1469 </html>
1470  """%("".join(lis)))
1471  if(found == 0):
1472  print("Sorry, no configuration files were found.")
1473  return
1474  print("Finished dealing with configuration files.")
1475  server("cfgServer.py")
1476  if(not noServer):
1477  print("-----")
1478  print("Starting the python server..")
1479  import cfgServer
1480  cfgServer.main()
1481 
1482 
1483 if __name__ == "__main__":
1484  import sys, os, imp, shutil
1485  from optparse import OptionParser
1486  parser = OptionParser(usage="%prog <cfg-file> ")
1487  parser.add_option("-q", "--quiet",
1488  action="store_true", dest="_quiet", default=False,
1489  help="Print minimal messages to stdout")
1490  #parser.add_option("-o", "--html_file", dest="_htmlfile",
1491  # help="The output html file.", default="cfg-viewer.html")
1492  parser.add_option("-s", "--no_server",
1493  action="store_true", dest="_server", default=False,
1494  help="Disable starting a python server to view "\
1495  "the html after finishing with config files.")
1496  parser.add_option("-r", "--recurse", dest="_recurse",action="store_true",
1497  default=False,
1498  help="Search directories recursively for .py files.")
1499  # store in another dir down
1500  #additonalDir = "first"
1501  helper_dir = "cfgViewerJS"
1502  opts, args = parser.parse_args()
1503  #cfg = args
1504  try:
1505  distBaseDirectory=os.path.abspath(
1506  os.path.join(os.path.dirname(__file__),".."))
1507  if (not os.path.exists(distBaseDirectory) or
1508  not "Vispa" in os.listdir(distBaseDirectory)):
1509  distBaseDirectory=os.path.abspath(
1510  os.path.join(os.path.dirname(__file__),"../python"))
1511  if (not os.path.exists(distBaseDirectory) or
1512  not "Vispa" in os.listdir(distBaseDirectory)):
1513  distBaseDirectory=os.path.abspath(os.path.expandvars(
1514  "$CMSSW_BASE/python/FWCore/GuiBrowsers"))
1515  if (not os.path.exists(distBaseDirectory) or
1516  not "Vispa" in os.listdir(distBaseDirectory)):
1517  distBaseDirectory=os.path.abspath(os.path.expandvars(
1518  "$CMSSW_RELEASE_BASE/python/FWCore/GuiBrowsers"))
1519  except Exception:
1520  distBaseDirectory=os.path.abspath(
1521  os.path.join(os.path.dirname(sys.argv[0]),".."))
1522  sys.path.insert(0,distBaseDirectory)
1523  from Vispa.Main.Directories import *
1524  distBinaryBaseDirectory=os.path.join(baseDirectory,"dist")
1525  sys.path.append(distBinaryBaseDirectory)
1526  from FWCore.GuiBrowsers.Vispa.Plugins.ConfigEditor import ConfigDataAccessor
1527  print("starting..")
1528  recurse = opts._recurse
1529  doesNotExist = [x for x in args if not os.path.exists(x)]
1530  if(len(doesNotExist)):
1531  s =""
1532  for x in doesNotExist:
1533  args.remove(x)
1534  s += "%s does not exist.\n"%(x)
1535  print(s)
1536 
1537  if(len(args)==0 or len(doesNotExist)== len(args)):
1538  print("""
1539  Either you provided no arguments, or the arguments provided do not exist.
1540  Please try again.
1541  If you need help finding files, provide arguments "." -r and I will search
1542  recursively through the directories in the current directory.
1543  """)
1544  else:
1545  main(args,"cfgViewerJS","main.html",opts._quiet, opts._server)
1546 
def getParameters(parameters)
Definition: cfg-viewer.py:440
std::vector< std::string_view > split(std::string_view, const char *)
def _mothersDaughters(self, name, item)
Definition: cfg-viewer.py:121
def __init__(self, df, cfg)
Definition: cfg-viewer.py:525
def main(args, helperDir, htmlFile, quiet, noServer)
Definition: cfg-viewer.py:1408
def _scripts(self, js)
Definition: cfg-viewer.py:645
def enter(self, value)
Definition: cfg-viewer.py:578
def _doSequenceTypes(self, paths, namep)
Definition: cfg-viewer.py:87
def replace(string, replacements)
def _css(self, css, cssLocal)
Definition: cfg-viewer.py:704
S & print(S &os, JobReport::InputFile const &f)
Definition: JobReport.cc:66
def _writeProdConsum(self)
Definition: cfg-viewer.py:376
def __init__(self, cfgFile, html, quiet, helperDir, fullDir)
Definition: cfg-viewer.py:11
def _getType(self, val)
Definition: cfg-viewer.py:548
def _searchitems(self, items)
Definition: cfg-viewer.py:657
def _items(self, items)
Definition: cfg-viewer.py:650
def leave(self, value)
Definition: cfg-viewer.py:611
def _createObjects(self)
Definition: cfg-viewer.py:195
def _jqueryFile(self, name, pN, pFN)
Definition: cfg-viewer.py:746
def __init__(self, name)
Definition: cfg-viewer.py:1271
def _getData(self, objs)
Definition: cfg-viewer.py:60
def _finalExit(self)
Definition: cfg-viewer.py:541
def _doModules(self, modObj, dataFile, seq, seqs, currentName, innerSeq)
Definition: cfg-viewer.py:554
def _saveData(self, name, base, jsonfiles)
Definition: cfg-viewer.py:186
def _filenames(self, name, option="")
Definition: cfg-viewer.py:169
def __init__(self, name, js, items, theDir, helperDir, pN, pFN)
Definition: cfg-viewer.py:635
def computeConfigs(args)
Definition: cfg-viewer.py:1385
def _doNonSequenceType(self, objs, globalType)
Definition: cfg-viewer.py:130
def getParamSeqDict(params, fil, typ, oType)
Definition: cfg-viewer.py:516
static std::string join(char **cmd)
Definition: RemoteFile.cc:17
def _calcFilenames(self, name)
Definition: cfg-viewer.py:165
def _printHtml(self, name, scrip, css, items, search)
Definition: cfg-viewer.py:662
def _complexBase(self, parentName, extra)
Definition: cfg-viewer.py:415
def JSONFormat(d)
Definition: cfg-viewer.py:1266
def doTypes(spec, generic)
Definition: cfg-viewer.py:1263
def printServer(self, name)
Definition: cfg-viewer.py:1274
def _checkType(self, item)
Definition: cfg-viewer.py:114
Definition: main.py:1
def listBase(VList)
Definition: cfg-viewer.py:471
def _load(self, name, param, inner)
Definition: cfg-viewer.py:224
#define str(s)
def _writeModSeqParent(self)
Definition: cfg-viewer.py:350
def _writeDictParent(self, typeName)
Definition: cfg-viewer.py:230
def _proceed(self, fileName)
Definition: cfg-viewer.py:37
def _producersConsumers(self)
Definition: cfg-viewer.py:175