/
githubmirror
/
cmssw
Обзор
Документация
Войти
/
githubmirror
/
cmssw
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
Documentation/ReferenceManualScripts/python/MainPageGenerator.py
431 строка
20 KB
Shahzad Malik Muzaffar
[CORE] py2/3 compatibility:drop use of __future__
22 ноя 2024, 20:16
22 ноя 2024, 20:16
4759e53
Код
Авторство
О чём код?
import json, urllib2, os, sys from bs4 import BeautifulSoup ## MainPageGenerator class is used for generating main page that contains domain trees (Analysis, Calibration and Alignment, Core, DAQ etc.) class MainPageGenerator: ## Constructor method. # @param dataPath parameter gives path of data directory that contains .js, .css and image files needed for generating tree pages # @param path is the reference manual directory path and it is used as destination and source. # @param cmsVer is version of CMSSW. def __init__(self, dataPath, path, cmsVer = ""): self.path = path self.dataPath = dataPath self.CMSVER = cmsVer self.managersURL = 'http://cmsdoxy.web.cern.ch/cmsdoxy/tcproxy.php?type=managers' self.usersURL = 'http://cmsdoxy.web.cern.ch/cmsdoxy/tcproxy.php?type=users' self.CMSSWURL = 'http://cmsdoxy.web.cern.ch/cmsdoxy/tcproxy.php?type=packages&release=CMSSW_4_4_2' self.tWikiLinks = {'Analysis':'https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideCrab', 'Calibration and Alignment':'https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideCalAli', 'Core':'https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideFrameWork', 'DAQ':'https://twiki.cern.ch/twiki/bin/view/CMS/TriDASWikiHome', 'DQM':'https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideDQM', 'Database':'https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideCondDB', 'Documentation':'https://twiki.cern.ch/twiki/bin/view/CMS/SWGuide', 'Fast Simulation':'https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideFastSimulation', 'Full Simulation':'https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideSimulation', 'Generators':'https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideEventGeneration', 'Geometry':'https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideDetectorDescription', 'HLT':'https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideHighLevelTrigger', 'L1':'https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideL1Trigger', 'Reconstruction':'https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideReco', 'Visualization':'https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideVisualization'} self.data = None self.GitLink = "https://github.com/cms-sw/cmssw/tree/" + self.CMSVER + "/%s/%s" self.title = "<center>\n<h1>CMSSW Documentation</h1>\n<h2>" + self.CMSVER + "</h2>\n</center>\n" self.links = """ <p style="margin-left:10px;"> Learn <a href="ReferenceManual.html">how to build Reference Manual</a><br> Learn more about <a target="_blank" href="http://www.stack.nl/~dimitri/doxygen/commands.html">special doxygen commands</a> </p>\n\n""" self.head = """ <!-- Content Script & Style --> <script type="text/javascript"> var itemList = []; function toggleHoba(item, path) { for(var i = 0; i < itemList.length; i++) { if(itemList[i] == item) { var iframe = $("#"+itemList[i]+"_div").children("iframe:first"); if(!iframe.attr("src")) { iframe.attr("src", path) } $("#"+item+"_div").slideToggle(); } else $("#"+itemList[i]+"_div").slideUp(); } } $(document).ready(function() { searchBox.OnSelectItem(0); $(".doctable").find("td").each(function(){ if (this.id.indexOf("hoba_") != -1)itemList.push(this.id);}); }); </script> <style> .DCRow { background: #eeeeff; border-spacing: 0px; padding: 0px; border-bottom: 1px solid #c1c1dc; } .DCRow:hover { background: #cde4ec; } </style> <!-- Content Script & Style --> """ self.contentStamp = '$CONTENT$' self.mainPageTemplate = self.ReadFile("index.html") self.WriteFile("index_backup.html", self.mainPageTemplate) #backup file soup = BeautifulSoup(self.mainPageTemplate) soup.head.insert(len(soup.head), self.head) contents = soup.find("div", { "class" : "contents" }) for child in contents.findChildren(): child.extract() contents.insert(0, self.contentStamp) self.mainPageTemplate = str(soup) self.mainPageTemplate = self.mainPageTemplate.replace("CSCDQM Framework Guide", "") self.mainPageTemplate = self.mainPageTemplate.replace('<','<').replace('>', '>') print("Main page template created...") self.CreateBuildRefMan() print("RefMan created...") self.treePageTamplate = self.ReadFile(self.dataPath + "tree_template.html", pathFlag = False) self.classesSource = self.ReadFile("classes.html") self.filesSource = self.ReadFile("files.html") self.packageSource = self.ReadFile("pages.html") def ReadFile(self, fileName, pathFlag = True): """This method reads file directly or from path.""" if pathFlag: print("Read:", self.path + fileName) f = open(self.path + fileName) else: f = open(fileName) print("Read:", fileName) data = f.read() f.close() return data def WriteFile(self, fileName, data): """This method writes data""" print("Write:", self.path + fileName) f = open(self.path + fileName, "w") f.write(data) f.close() def GetFileName(self, fileName): """This method returns file name without extension""" if '.' in fileName: return fileName[0:fileName.find('.')] else: return fileName def ParseJsonFromURL(self, URL): """This method returns data which is read from URL""" u = urllib2.urlopen(URL) return json.loads(u.read()) def __ParseItem(self, str_): return str_[0:str_.find('/')] def __ParseSubItem(self, str_): if '/' in str_: return str_[str_.find('/')+1:] else: return None def __GetHTMLItemDepth(self, item): return item["id"].count("_") - 1 # 1 for doxygen 1.8.5, 2 for old ver. def __HTMLFileName(self, fileName): return fileName.lower().replace(' ', '_') def PrepareData(self): self.managers = self.ParseJsonFromURL(self.managersURL) print("Managers loaded and parsed...") self.users = self.ParseJsonFromURL(self.usersURL) print("Users loaded and parsed...") self.data = {} for i in self.managers.keys(): self.data[i] = {"__DATA__":{"Contact":[]}} for j in self.managers[i]: self.data[i]["__DATA__"]["Contact"].append(self.users[j]) self.domains = self.ParseJsonFromURL(self.CMSSWURL) print("Domains loaded and parsed...") for i in self.domains.keys(): for j in self.domains[i]: if self.__ParseItem(j) not in self.data[i]: self.data[i][self.__ParseItem(j)] = {} if self.__ParseSubItem(j) not in self.data[i][self.__ParseItem(j)]: self.data[i][self.__ParseItem(j)][self.__ParseSubItem(j)] = {} self.data[i][self.__ParseItem(j)][self.__ParseSubItem(j)]["__DATA__"] = { 'git': self.GitLink % (self.__ParseItem(j), self.__ParseSubItem(j)) } # for getting package links soup = BeautifulSoup(self.packageSource) contents = soup.find("div", { "class" : "contents" }) li = contents.findAll("tr", {}) self.packages = {} for i in li: if i.a["href"]: self.packages[i.a.text] = i.a["href"] print("Packages parsed(%d)..." % len(self.packages)) # for getting items from file.html soup = BeautifulSoup(self.filesSource) contents = soup.find("div", { "class" : "contents" }) tr = contents.findAll("tr", {}) self.classes= {} origin = 0 if tr[0].text == 'src': origin = -1 # depth of interface items can be only 3 flag = False for i in tr: if self.__GetHTMLItemDepth(i) + origin == 1: self.classes[i.text] = {} level1 = i.text flag = False if self.__GetHTMLItemDepth(i) + origin == 2: self.classes[level1][i.text] = {} level2 = i.text flag = False if self.__GetHTMLItemDepth(i) + origin == 3 and i.text == u'interface': flag = True if self.__GetHTMLItemDepth(i) + origin == 3 and i.text != u'interface': flag = False # print i.text, self.__GetHTMLItemDepth(i) # raw_input() if flag and i.text != u'interface': self.classes[level1][level2][i.text] = i.a["href"] #self.ZEG = i print("Class hierarchy loaded(%d)..." % len(self.classes)) # self.WriteFile("dbg.json", json.dumps(self.classes, indent = 1)) # for parsing classes links from classes.html soup = BeautifulSoup(self.classesSource) contents = soup.find("div", { "class" : "contents" }) td = contents.findAll("td", {}) self.classesURLs = {} # add items to self.classesURLs for i in td: if i.a and 'href' in i.a: self.classesURLs[i.a.text] = i.a['href'] print("Class URLs was loaded... (%s)" % len(self.classesURLs)) for i in self.data.keys(): for j in self.data[i].keys(): if j not in self.classes: continue for k in self.data[i][j].keys(): if "Package " + j + "/" + k in self.packages: self.data[i][j][k]["__DATA__"]["packageDoc"] = '../' + self.packages["Package " + j + "/" + k] if k not in self.classes[j]: continue for h in self.classes[j][k]: if self.GetFileName(h) in self.classesURLs: self.data[i][j][k][self.GetFileName(h)] = {"__DATA__": '../' + self.classesURLs[self.GetFileName(h)]} else: self.data[i][j][k][self.GetFileName(h) + ".h"] = {"__DATA__": '../' + self.classes[j][k][h]} def ExportJSON(self, fileName): if self.data == None: self.PrepareData() self.WriteFile(fileName, json.dumps(self.data, indent = 1)) def CreateBuildRefMan(self): content = """<h1>The Reference Manual </h1> This is the CMSSW Reference Manual, the reference documentation of all classes and packages in CMSSW.<p> This page explains how to write the documentation for your code. </p><h2>Class Documentation</h2> Classes and methods are documented with properly formatted <a target="_blank" class="el" href="d3/d88/namespacecomments.html">comments</a> in the code.<p> Here is a template of a documented <a target="_blank" href="http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/Documentation/CodingRules/Template.h?rev=HEAD&cvsroot=CMSSW&content-type=text/vnd.viewcvs-markup">.h file</a>, and of a <a target="_blank" href="http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/Documentation/CodingRules/Template.cc?rev=HEAD&cvsroot=CMSSW&content-type=text/vnd.viewcvs-markup">.cc file</a>. The resulting doxygen page is <a target="_blank" class="el" href="d6/d3e/classTemplate.html">here</a>. </p><h2>Package Documentation</h2> Each package should contain a very brief description of its content and purpose. Remember that this is a reference, and not a user's guide: tutorials, howtos, etc. are best documented in the <a target="_blank" href="https://twiki.cern.ch/twiki/bin/view/CMS/SWGuide">CMS Offline Guide</a> and in the <a target="_blank" href="https://twiki.cern.ch/twiki/bin/view/CMS/WorkBook">WorkBook</a>. Cross links between the CMS Offline Guide and the WorkBook and this manual are a good way to avoid duplication of content.<p> This documentation should be written in a file [Package]/doc/[Package].doc. The simplest way of doing this is to go to the doc/ directory in your package and then run the script <a target="_blank" href="http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/*checkout*/CMSSW/Documentation/ReferenceManualScripts/scripts/makePackageDoc?rev=HEAD&cvsroot=CMSSW">makePackageDoc</a>, which is available in your PATH. </p><h2> How to generate your documentation locally </h2> One you have updated your documentation, you can look at how it displays in the following way: <ul> <li>check out the following packages: <pre> > cmsrel CMSSW_7_X_X > cd CMSSW_7_X_X/ > cmsenv > git cms-addpkg Documentation > generate_reference_manual wait... > firefox doc/html/index.html </pre> </li> </ul>""" self.WriteFile('ReferenceManual.html', self.mainPageTemplate.replace(self.contentStamp, content)) def CreateNewMainPage(self, outputFileName): if self.data == None: self.PrepareData() contents = """ <table class="doctable" border="0" cellpadding="0" cellspacing="0"> <tbody> <tr class="top" valign="top"> <th class="domain">Domain</th><th class="contact">Contact</th> </tr> """ keysI = sorted(self.data.keys()) for i in keysI: ######################### if i == 'Other': continue self.__NewTreePage(i) contents = contents + '\n<tr class="DCRow">\n' ######### TAG: TR1 ######################### if i == 'Operations': contents = contents + """<td width="50%%" style="padding:8px">%s</td>\n""" % i else: contents = contents + """<td width="50%%" style="padding:8px;cursor:pointer" onclick="toggleHoba('hoba_%s', 'iframes/%s.html')" id="hoba_%s"><a>%s</a></td>\n""" % (i.replace(' ', '_'), i.lower().replace(' ', '_'), i.replace(' ', '_'), i) ######################### contents = contents + '<td width="50%" class="contact">' for j in range(len(self.data[i]["__DATA__"]["Contact"])): if j == len(self.data[i]["__DATA__"]["Contact"]) - 1: contents = contents + '<a href="mailto:%s">%s</a> ' % (self.data[i]["__DATA__"]["Contact"][j][1], self.data[i]["__DATA__"]["Contact"][j][0]) else: contents = contents + '<a href="mailto:%s">%s</a>, ' % (self.data[i]["__DATA__"]["Contact"][j][1], self.data[i]["__DATA__"]["Contact"][j][0]) contents = contents + '</td>\n' contents = contents + '</tr>\n\n' ######### TAG: TR1 ######################### if i == 'Operations': continue ######################### contents = contents + """ <tr><td colspan="2" style="background:#d7dbe3"> <div style="display:none;" id="hoba_%s_div"><iframe width="100%%" frameborder="0"></iframe></div> </td></tr> """ % (i.replace(' ', '_')) contents = contents + "</table>" self.WriteFile(outputFileName, self.mainPageTemplate.replace(self.contentStamp, self.title + contents + self.links)) def __NewTreePage(self, domain): if domain not in self.data: return content = '' keysI = sorted(self.data[domain].keys()) for i in keysI: if i == '__DATA__': continue content += self.HTMLTreeBegin(i) keysJ = sorted(self.data[domain][i].keys()) for j in keysJ: # if len(self.data[domain][i][j].keys()) == 1: # if self.data[domain][i][j].has_key("__DATA__"): # content += self.HTMLTreeAddItem(j, self.data[domain][i][j]["__DATA__"]) # else: # content += self.HTMLTreeAddItem(j) # continue keysK = sorted(self.data[domain][i][j].keys()) length = len(keysK) # content += "<!-- Begin -->" if length > 1: if "__DATA__" in self.data[domain][i][j]: content += self.HTMLTreeBegin(j, self.data[domain][i][j]["__DATA__"]) else: content += self.HTMLTreeBegin(j) else: if "__DATA__" in self.data[domain][i][j]: content += self.HTMLTreeAddItem(j, self.data[domain][i][j]["__DATA__"], folder = True) else: content += self.HTMLTreeAddItem(j, folder = True) for k in keysK: if k == '__DATA__': continue if self.data[domain][i][j][k]["__DATA__"]: content += self.HTMLTreeAddItem(k, self.data[domain][i][j][k]["__DATA__"]) else: content += self.HTMLTreeAddItem(k) if length > 1: content += self.HTMLTreeEnd() # content += "<!-- End -->" content += self.HTMLTreeEnd() if domain in self.tWikiLinks: self.WriteFile("iframes/%s.html" % domain.lower().replace(' ', '_'), self.treePageTamplate % (domain, self.tWikiLinks[domain], content)) else: print('Warning: The twiki link of "%s" domain not found...' % domain) self.WriteFile("iframes/%s.html" % domain.lower().replace(' ', '_'), self.treePageTamplate % (domain, '#', content)) def HTMLTreeBegin(self, title, links = {}): html = '\n<li>\n<div class="hitarea expandable-hitarea"></div>\n' html = html + '<span class="folder">%s\n' % title for i in links.keys(): html = html + '<a target="_blank" href="%s">[%s]</a> \n' % (links[i], i) html = html + '</span>\n' html = html + '<ul style="display: block;">\n' return html def HTMLTreeEnd(self): return '</li></ul>\n\n' def HTMLTreeAddItem(self, title, links = None, endNode = False, folder = False): if endNode: html = '\t<li class="last">' else: html = '\t<li>' if isinstance(links, str) or isinstance(links, type(u'')): if folder: html = html + '\t<a href="%s" target="_blank" class=""><span class="emptyFolder">%s</span></a>\n' % (links, title) else: html = html + '\t<a href="%s" target="_blank" class=""><span class="file">%s</span></a>\n' % (links, title) elif isinstance(links, dict): if folder: html = html + '<span class="emptyFolder">%s ' % title else: html = html + '<span class="file">%s ' % title for i in links.keys(): html = html + '<a target="_blank" href="%s">[%s]</a> \n' % (links[i], i) html = html + '</span>' else: html = html + '\t<span class="file">%s</span>\n' % title return html + '\t</li>\n' if len(sys.argv) == 5: DATA_PATH = sys.argv[1] PATH = sys.argv[2] VER = sys.argv[3] OUTF = sys.argv[4] #os.system("cp -rf %s../data/iframes/ %s" % (os.path.split(__file__)[0], PATH)) l = MainPageGenerator(DATA_PATH, PATH, cmsVer = VER) l.CreateNewMainPage(OUTF) else: print("parameter error. It must be like this: python MainPageGenerator.py DATA_PATH/ CMSSW/doc/html/ CMS_VER OUTPUT_FILE_NAME")