#!/usr/bin/env python3 """ sql2htmldoc.py - Create web pages for BIRCH documentation from birchdocdb database Synopsis: sql2htmldoc.py @modified: August 5, 2025 @author: Brian Fristensky and Dale Hamel @contact: frist@cc.umanitoba.ca """ import os import re import shutil import sqlite3 import sys blib = os.environ.get("BIRCHLIB") sys.path.append(blib) from birchlib import Birchmod from birchlib import Htmlutils from birchlib import HTMLWriter PROGRAM = "sql2htmldoc.py: " USAGE = "\n\t USAGE: sql2htmldoc.py [currently takes no paramters]" BM = Birchmod(PROGRAM, USAGE) PROGS = [] CATDICT = {} PROGDICT = {} PKGDICT = {} DOCDICT = {} HT = Htmlutils(CATDICT, PROGDICT) NL = "\n" # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class Parameters: "Wrapper class for global parameters" def __init__(self): """ Get the location of the BIRCH home directory, BIRCHPATH Preferrably, we get it from the BIRCH.properties file, but if that isn't found, we get it from the BIRCH environment variable. The one catch is that since we don't already know the location of BIRCHPATH, the former will only work if the current working directory is install-scripts. Normally, this would only be used when installing or updating BIRCH Otherwise, the environment variable will be read. """ FN = '../local/admin/BIRCH.properties' if os.path.exists(FN): print("sql2htmldoc.py: Reading $BIRCH from BIRCH.properties") self.BIRCHPATH = "" self.BIRCH_PLATFORM = "" FILE = open(FN, 'r') for LINE in FILE: TOKENS = LINE.split("=") if TOKENS[0] == 'BirchProps.homedir': self.BIRCHPATH = TOKENS[1].strip() if TOKENS[0] == 'BirchProps.platform': self.BIRCH_PLATFORM = TOKENS[1].strip() FILE.close() else: print("sql2htmldoc.py: Reading $BIRCH and $BIRCH_PLATFORM environment variables.") self.BIRCHPATH = os.environ['BIRCH'] # If BIRCH_PLATFORM is set in the environment, we want that # to supersede the value in BIRCH.properties plat = "" try: plat = os.environ['BIRCH_PLATFORM'] except: pass if plat != "": self.BIRCH_PLATFORM = plat # Everything else depends on BIRCHPATH print("sql2htmldoc.py: BIRCHPATH set to: " + self.BIRCHPATH) print("sql2htmldoc.py: BIRCH_PLATFORM set to: " + self.BIRCH_PLATFORM) self.BIRCHWEBPATH = self.BIRCHPATH + '/public_html' self.BIRCHDBPATH = self.BIRCHPATH + '/public_html/birchdocdb' self.BIRCHLOCALDBPATH = self.BIRCHPATH + '/local/public_html/birchdocdb' self.OUTFILE = "" # default prefix for http path to birch documentation #self.DOCPREFIX = 'file://' + self.BIRCHWEBPATH + '/doc' # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def AddToList(L, NAME): """ If a list contains NAME, do nothing If it does not exist, append it to the list @param L: The list to check for name @type L: list @param NAME: The name to be checked for @type NAME: str """ if NAME in L: pass else: L.append(NAME) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class Category: def __init__(self): """ Initializes arguments: name="" program=[] pkg=[] """ self.name = "" self.program = [] self.pkg = [] # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def ReadCategory(cursor, CATS): """ Read category.ace into a list of category objects @param cursor: The cursor pointing to the SQL database @param CATS: The categories object to be read into @type CATS: list """ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def AssignCategory(NAME): """ "If a category called NAME already exists, return a pointer" "If it does not exist, create a new category object and return a pointer" @param NAME: The name of the category to check for @type NAME: str """ if NAME in CATDICT: C = CATDICT[NAME] else: C = Category() CATS.append(C) C.name = NAME return C result = cursor.execute("SELECT CatName from Category;").fetchall() for item in result : name = item[0] C = AssignCategory(name) progs = cursor.execute("SELECT Program from ProgCat WHERE Category = " + "'" + name + "';").fetchall() for p in progs : C.program.append(p[0]) pkg = cursor.execute("SELECT Package from PkgCat WHERE Category = " + "'" + name + "';").fetchall() for p in pkg : C.pkg.append(p[0]) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class Package: def __init__(self): """ Initializes arguments: name="" description="" category=[] doc=[] program=[] data=[] platform=[] installation=[] """ self.name = "" self.description = "" self.category = [] self.doc = [] self.program = [] self.data = [] self.platform = [] self.installation = "" # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def ReadPackage(cursor, PKGS): """ Read package.ace into a list of Package objects @param FN: The name of the file to be read in @type FN: str @param PKGS: The list of package objects to be read into @type PKGS:list """ # - - - - - - - - - - - - - - - - - - - def AssignPackage(NAME): """ If a package called NAME already exists, return a pointer If it does not exist, create a new package object and return a pointer @param NAME:The name to attempt to assign @type NAME:str """ if NAME in PKGDICT: PK = PKGDICT[NAME] else: PK = Package() PKGS.append(PK) PK.name = NAME return PK result = cursor.execute("SELECT Name,Description,Installation from Package;").fetchall() for item in result : name = item[0] C = AssignPackage(name) C.description = item[1] C.installation = item[2] cats = cursor.execute("SELECT Category from PkgCat WHERE Package = " + "'" + name + "';").fetchall() for c in cats : C.category.append(c[0]) docs = cursor.execute("SELECT Documentation from PkgDoc WHERE Package = " + "'" + name + "';").fetchall() for c in docs : C.doc.append(c[0]) progs = cursor.execute("SELECT Program from PkgProg WHERE Package = " + "'" + name + "';").fetchall() for c in progs : C.program.append(c[0]) dat = cursor.execute("SELECT Data from PkgDat WHERE Package = " + "'" + name + "';").fetchall() for c in dat : C.data.append(c[0]) plat = cursor.execute("SELECT Platform from PkgPlat WHERE Package = " + "'" + name + "';").fetchall() for c in plat : C.platform.append(c[0]) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class Program: def __init__(self): """ Initializes arguments: name="" description="" category=[] interface=[] package="" doc=[] data=[] sampleinput=[] sampleoutput=[] platform=[] """ self.name = "" self.description = "" self.category = [] self.interface = [] self.package = "" self.doc = [] self.data = [] self.sampleinput = [] self.sampleoutput = [] self.platform = [] self.installation = "" # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def ReadProgram(cursor, PROGS): """ Read program.ace into a list of Program objects @param FN: The name of the file to be read in @type FN: str @param PROGS: The list of Program objects to read the file into @type PROGS: list """ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def AssignProgram(NAME): """ If a program called NAME already exists, return a pointer If it does not exist, create a new program object and return a pointer @param NAME: The name to attempt to assign @type NAME: str """ if NAME in PROGDICT: PR = PROGDICT[NAME] else: PR = Program() PROGS.append(PR) PR.name = NAME return PR result = cursor.execute("SELECT Name,Description,Installation from Program;").fetchall() for item in result : name = item[0] C = AssignProgram(name) C.description = item[1] C.installation = item[2] interface = cursor.execute("SELECT ComType,Command from ProgLaunch WHERE Program = " + "'" + name + "';").fetchall() for i in interface : C.interface.append(i) cats = cursor.execute("SELECT Category from ProgCat WHERE Program = " + "'" + name + "';").fetchall() for c in cats : C.category.append(c[0]) docs = cursor.execute("SELECT Documentation from ProgDoc WHERE Program = " + "'" + name + "';").fetchall() for c in docs : C.doc.append(c[0]) pkg = cursor.execute("SELECT Package from PkgProg WHERE Program = " + "'" + name + "';").fetchall() for c in pkg : C.package = c[0] dat = cursor.execute("SELECT Data from ProgDat WHERE Program = " + "'" + name + "';").fetchall() for c in dat : C.data.append(c[0]) dat = cursor.execute("SELECT SampleInput from ProgSampleInp WHERE Program = " + "'" + name + "';").fetchall() for c in dat : C.sampleinput.append(c[0]) dat = cursor.execute("SELECT SampleOutput from ProgSampleOut WHERE Program = " + "'" + name + "';").fetchall() for c in dat : C.sampleoutput.append(c[0]) plat = cursor.execute("SELECT Platform from ProgPlat WHERE Program = " + "'" + name + "';").fetchall() for c in plat : C.platform.append(c[0]) def write_category_page(catfn): """ FIXME @param catfn: @type catfn: """ "write html page listing program categories." # - - - - - - - - - - - def writecat(c): """ FIXME @param c: @type c: """ "write a page for a given category" catfn = c.name + '.html' catpagefile = open(catfn, 'w') h = HTMLWriter () h.start_page(catpagefile, 'category: ' + c.name) h.start(catpagefile, 'hr', '') h.start(catpagefile, 'h1', '') catpagefile.write('programs:') h.end(catpagefile, 'h1') h.start(catpagefile, 'ul', '') #c.program.sort(key=HT.cmp_to_key(lambda x, y: cmp(x.lower(), y.lower()))) #c.program.sort(key=lambda x: x.lower()) c.program.sort(key=lambda name: name.lower()) for pname in c.program: h.start(catpagefile, 'li', '') url = '../program/' + pname + '.html' #print("Progdict length:"+str(len(PROGDICT))) # The try/except clause is here because of a so-far unsolved KeyError problem. # See BIRCH mozilla bug 1141 # I think this is solved now, but we'll keep this code for the time being. try: text = pname + ' - ' + PROGDICT[pname].description + '\n' h.link(catpagefile, url, '', text) except KeyError : print('In writecat: KeyError: ' + pname) h.link(catpagefile, '', '', 'KeyError: ' + pname) h.end(catpagefile, 'li') h.end(catpagefile, 'ul') h.end_page(catpagefile) catpagefile.close() os.chmod(catfn, 0o664) catfile = open(catfn, 'w') h = HTMLWriter () h.start_page(catfile, 'programs by category') h.start(catfile, 'hr', '') h.start(catfile, 'br', '') # for each category, write an html page containing # a list of programs in that category h.start(catfile, 'ul', '') catlist = list(CATDICT.keys()) #catlist.sort(key=HT.cmp_to_key(lambda x, y: cmp(x.lower(), y.lower()))) #catlist.sort(key=lambda x: x.lower()) catlist.sort(key=lambda name: name.lower()) for catkey in catlist: c = CATDICT[catkey] writecat(c) h.start(catfile, 'li', '') url = c.name + '.html' text = c.name + '\n' h.link(catfile, url, '', text) h.end(catfile, 'li') h.end(catfile, 'ul') h.end_page(catfile) catfile.close() os.chmod(catfn, 0o664) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class File: def __init__(self): """ Initializes arguments: name="" description="" command='\"$ACE_FILE_LAUNCHER\" ' path="" """ self.name = "" self.description = "" self.command = "" self.path = "" # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def ReadDocFiles(cursor, DOCFILES): """ Read file.ace into a list of file objects @param FN: The name of the file to be read in @type FN: str @param DOCFILES: the list of file objects to be read into @type DOCFILES: list """ # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def AssignFile(NAME): """ If a file called NAME already exists, return a pointer If it does not exist, create a new file object and return a pointer @param NAME: The name to attempt to assign @type NAME: str """ if NAME in DOCDICT: FL = DOCDICT[NAME] else: FL = File() DOCFILES.append(FL) FL.name = NAME return FL result = cursor.execute("SELECT Name,Description,Action,PathOrURL from File;").fetchall() for item in result : name = item[0] C = AssignFile(name) C.description = item[1] C.command = item[2] C.path = item[3] # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def FreshDir(DIRNAME): """ Delete an existing directory and create an empty directory with the same name. @param DIRNAME: The name of the directory to be refreshed @type DIRNAME: str """ if os.path.isdir(DIRNAME): shutil.rmtree(DIRNAME) os.mkdir(DIRNAME) os.chmod(DIRNAME, 0o775) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def WritePackagePage(PKGFN, P): """ Write HTML page listing program packages. @param PKGFN: The name of the html page to be created @type PKGFN: str @param P: An instance of the Paramaters object @type P: Paramters object """ # - - - - - - - - - - - def WritePkg(PK): """ Write a page for a given package @param PK: The name of the package @type PK: str """ PKGFN = PK.name + '.html' PKGPAGEFILE = open(PKGFN, 'w') H = HTMLWriter () H.start_page(PKGPAGEFILE, 'Package: ' + PK.name) # Program information is in a table. # ATTRIBUTES = ' style="border: 1px solid";' ATTRIBUTES = ' style="font-family: helvetica,arial,sans-serif;"' H.start(PKGPAGEFILE, 'table', ATTRIBUTES) ATTRIBUTES = '' H.start(PKGPAGEFILE, 'tr', ATTRIBUTES) # Title row ATTRIBUTES = '' H.start(PKGPAGEFILE, 'tr', ATTRIBUTES) ATTRIBUTES = ' colspan="2" rowspan="1" style= "background-color: rgb(51, 255, 51);"' H.start(PKGPAGEFILE, 'td', ATTRIBUTES) ATTRIBUTES = '' H.start(PKGPAGEFILE, 'big', ATTRIBUTES) PKGPAGEFILE.write(PK.name + ' - ' + PK.description) H.end(PKGPAGEFILE, 'big') H.end(PKGPAGEFILE, 'td') H.end(PKGPAGEFILE, 'tr') # Documentation rows DocRows(PKGPAGEFILE, H, 'Documentation', PK.doc, DOCDICT, P) # Datafile rows DocRows(PKGPAGEFILE, H, 'Data', PK.data, DOCDICT, P) # Platform row ATTRIBUTES = '' H.start(PKGPAGEFILE, 'tr', ATTRIBUTES) ATTRIBUTES = ' colspan="2" rowspan="1" style= "background-color: rgb(204, 204, 204);"' H.start(PKGPAGEFILE, 'td', ATTRIBUTES) ATTRIBUTES = '' H.start(PKGPAGEFILE, 'big', ATTRIBUTES) URL = '../Doc_definitions.html#Platforms' TEXT = 'Platforms' ATTRIBUTES = 'target="FrameWindow"' H.link(PKGPAGEFILE, URL, ATTRIBUTES, TEXT) PKGPAGEFILE.write(': ') H.end(PKGPAGEFILE, 'big') I = 0 for PLAT in PK.platform: PKGPAGEFILE.write(PLAT) I = I + 1 if I < len(PK.platform): PKGPAGEFILE.write(', ') H.end(PKGPAGEFILE, 'td') H.end(PKGPAGEFILE, 'tr') # Installation row ATTRIBUTES = '' H.start(PKGPAGEFILE, 'tr', ATTRIBUTES) ATTRIBUTES = ' colspan="2" rowspan="1" style= "background-color: rgb(204, 204, 204);"' H.start(PKGPAGEFILE, 'td', ATTRIBUTES) ATTRIBUTES = '' H.start(PKGPAGEFILE, 'big', ATTRIBUTES) URL = '../Doc_definitions.html#Installation' TEXT = 'Installation' ATTRIBUTES = 'target="FrameWindow"' H.link(PKGPAGEFILE, URL, ATTRIBUTES, TEXT) PKGPAGEFILE.write(': ') H.end(PKGPAGEFILE, 'big') #I = 0 #for INST in PK.installation: # PKGPAGEFILE.write(INST) # I = I + 1 # if I < len(PK.installation): # PKGPAGEFILE.write(', ') PKGPAGEFILE.write(PK.installation) H.end(PKGPAGEFILE, 'td') H.end(PKGPAGEFILE, 'tr') # Program rows ATTRIBUTES = '' H.start(PKGPAGEFILE, 'tr', ATTRIBUTES) ATTRIBUTES = ' colspan="2" rowspan="1" style= "background-color: rgb(204, 204, 204);"' H.start(PKGPAGEFILE, 'td', ATTRIBUTES) ATTRIBUTES = '' H.start(PKGPAGEFILE, 'big', ATTRIBUTES) URL = '../Doc_definitions.html#Programs' TEXT = 'Programs' ATTRIBUTES = 'target="FrameWindow"' H.link(PKGPAGEFILE, URL, ATTRIBUTES, TEXT) PKGPAGEFILE.write(': ') H.end(PKGPAGEFILE, 'big') H.end(PKGPAGEFILE, 'td') H.end(PKGPAGEFILE, 'tr') ATTRIBUTES = '' H.start(PKGPAGEFILE, 'tr', ATTRIBUTES) ATTRIBUTES = ' colspan="2" rowspan="1" style= "background-color: rgb(255, 255, 255);"' H.start(PKGPAGEFILE, 'td', ATTRIBUTES) H.start(PKGPAGEFILE, 'ul', '') #PK.program.sort(key=HT.cmp_to_key(lambda x, y: cmp(x.lower(), y.lower()))) #PK.program.sort(key=lambda x: x.lower()) PK.program.sort(key=lambda name: name.lower()) for PNAME in PK.program: H.start(PKGPAGEFILE, 'li', '') URL = '../program/' + PNAME + '.html' TEXT = PNAME + ' - ' + PROGDICT[PNAME].description + '\n' H.link(PKGPAGEFILE, URL, '', TEXT) H.end(PKGPAGEFILE, 'li') H.end(PKGPAGEFILE, 'ul') H.end(PKGPAGEFILE, 'td') H.end(PKGPAGEFILE, 'tr') H.end(PKGPAGEFILE, 'table') H.end_page(PKGPAGEFILE) PKGPAGEFILE.close() os.chmod(PKGFN, 0o664) PKGFILE = open(PKGFN, 'w') H = HTMLWriter () H.start_page(PKGFILE, 'Programs by Package') H.start(PKGFILE, 'hr', '') H.start(PKGFILE, 'br', '') # For each package, write an HTML page containing # a list of programs in that package H.start(PKGFILE, 'ul', '') PKGLIST = list(PKGDICT.keys()) #PKGLIST.sort(key=HT.cmp_to_key(lambda x, y: cmp(x.lower(), y.lower()))) #PKGLIST.sort(key=lambda x: x.lower()) PKGLIST.sort(key=lambda name: name.lower()) for PKGKEY in PKGLIST: PK = PKGDICT[PKGKEY] WritePkg(PK) H.start(PKGFILE, 'li', '') URL = PK.name + '.html' TEXT = PK.name + ' - ' + PKGDICT[PK.name].description + '\n' H.link(PKGFILE, URL, '', TEXT) H.end(PKGFILE, 'li') H.end(PKGFILE, 'ul') H.end_page(PKGFILE) PKGFILE.close() os.chmod(PKGFN, 0o664) # - - - - - - - - - - - def DocRows(OUTFILE, H, HEADING, FILELIST, D, P): """ Write rows for documentation lines: Documentation, Data, Sample input, Sample output @param OUTFILE: The name of the output file @type OUTFILE: str @param H: An instance of HTMLWriter @type H: HTMLWriter @param HEADING: The heading to place in each row @type HEADING: str @param FILELIST: The list of files to be documented @type FILELIST: list @param D: The dictionary to use for documentation @type D: dictionary @param P: An instance of the Parameters class @type P: Parameters object """ # Documentation rows - title row is 1 column, other rows are 2 columns ATTRIBUTES = '' H.start(OUTFILE, 'tr', ATTRIBUTES) ATTRIBUTES = ' colspan="2" rowspan="1" style= "background-color: rgb(204, 204, 204);"' H.start(OUTFILE, 'td', ATTRIBUTES) ATTRIBUTES = '' H.start(OUTFILE, 'big', ATTRIBUTES) URL = '../Doc_definitions.html#' + HEADING.replace(' ', '_') TEXT = HEADING ATTRIBUTES = 'target="FrameWindow"' H.link(OUTFILE, URL, ATTRIBUTES, TEXT) H.end(OUTFILE, 'big') H.end(OUTFILE, 'td') H.end(OUTFILE, 'tr') for DOCNAME in FILELIST: ATTRIBUTES = '' if DOCNAME in D: DOCUMENT = D[DOCNAME] if len(DOCUMENT.path) > 0: H.start(OUTFILE, 'tr', ATTRIBUTES) ATTRIBUTES = ' border="0" colspan="1" rowspan="1" style= "background-color: rgb(255, 255, 255);"' H.start(OUTFILE, 'td', ATTRIBUTES) DOCTYPE = DOCUMENT.description H.indent_text(OUTFILE, DOCTYPE) H.end(OUTFILE, 'td') ATTRIBUTES = ' border="0" colspan="1" rowspan="1" style= "background-color: rgb(255, 255, 255);"' H.start(OUTFILE, 'td', ATTRIBUTES) URL = HT.name_to_url(DOCUMENT.path, P.DOCPREFIX) TEXT = DOCUMENT.path H.link(OUTFILE, URL, '', TEXT) H.end(OUTFILE, 'td') H.end(OUTFILE, 'tr') # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - def WriteProgramPage(PROGFN, P): """ Write HTML page listing programs in alphabetical order. @param PROGFN: The basename of the page to be written @type PROGFN: str @param P: An instance of the Parameters class @type P: Paramters object """ # - - - - - - - - - - - def WriteProg(PR, P): """ Write a page for a given program @param PR: The name of the program to write the page for @type PR: str @param P: An instance of the Parameters class @type P: Parameters object """ PROGFN = PR.name + '.html' PROGPAGEFILE = open(PROGFN, 'w') H = HTMLWriter () H.start_page(PROGPAGEFILE, PR.name) # Program information is in a table. # ATTRIBUTES = ' style="border: 1px solid";' ATTRIBUTES = ' style="font-family: helvetica,arial,sans-serif;"' H.start(PROGPAGEFILE, 'table', ATTRIBUTES) ATTRIBUTES = '' H.start(PROGPAGEFILE, 'tr', ATTRIBUTES) # Title row ATTRIBUTES = '' H.start(PROGPAGEFILE, 'tr', ATTRIBUTES) ATTRIBUTES = ' colspan="2" rowspan="1" style= "background-color: rgb(51, 255, 51);"' H.start(PROGPAGEFILE, 'td', ATTRIBUTES) ATTRIBUTES = '' H.start(PROGPAGEFILE, 'big', ATTRIBUTES) PROGPAGEFILE.write(PR.name + ' - ' + PR.description) H.end(PROGPAGEFILE, 'big') H.end(PROGPAGEFILE, 'td') H.end(PROGPAGEFILE, 'tr') # Command rows - title row is 1 column, other rows are 2 columns ATTRIBUTES = '' H.start(PROGPAGEFILE, 'tr', ATTRIBUTES) ATTRIBUTES = ' colspan="2" rowspan="1" style= "background-color: rgb(204, 204, 204);"' H.start(PROGPAGEFILE, 'td', ATTRIBUTES) ATTRIBUTES = '' H.start(PROGPAGEFILE, 'big', ATTRIBUTES) URL = '../Doc_definitions.html#Launching' TEXT = 'Launching the program' ATTRIBUTES = 'target="FrameWindow"' H.link(PROGPAGEFILE, URL, ATTRIBUTES, TEXT) H.end(PROGPAGEFILE, 'big') H.end(PROGPAGEFILE, 'td') H.end(PROGPAGEFILE, 'tr') for COMMAND in PR.interface: ATTRIBUTES = '' H.start(PROGPAGEFILE, 'tr', ATTRIBUTES) ATTRIBUTES = ' border="0" colspan="1" rowspan="1" style= "background-color: rgb(255, 255, 255);"' H.start(PROGPAGEFILE, 'td', ATTRIBUTES) H.indent_text(PROGPAGEFILE, COMMAND[0]) H.end(PROGPAGEFILE, 'td') ATTRIBUTES = ' border="0" colspan="1" rowspan="1" style= "background-color: rgb(255, 255, 255);"' H.start(PROGPAGEFILE, 'td', ATTRIBUTES) ATTRIBUTES = ' face="Courier New,Courier"' H.start(PROGPAGEFILE, 'font', ATTRIBUTES) PROGPAGEFILE.write(COMMAND[1]) H.end(PROGPAGEFILE, 'font') H.end(PROGPAGEFILE, 'td') H.end(PROGPAGEFILE, 'tr') # Documentation rows DocRows(PROGPAGEFILE, H, 'Documentation', PR.doc, DOCDICT, P) # Datafile rows DocRows(PROGPAGEFILE, H, 'Data', PR.data, DOCDICT, P) # Sample input rows DocRows(PROGPAGEFILE, H, 'Sample input', PR.sampleinput, DOCDICT, P) # Sample output rows DocRows(PROGPAGEFILE, H, 'Sample output', PR.sampleoutput, DOCDICT, P) # Package row ATTRIBUTES = '' H.start(PROGPAGEFILE, 'tr', ATTRIBUTES) ATTRIBUTES = ' colspan="2" rowspan="1" style= "background-color: rgb(204, 204, 204);"' H.start(PROGPAGEFILE, 'td', ATTRIBUTES) ATTRIBUTES = '' H.start(PROGPAGEFILE, 'big', ATTRIBUTES) URL = '../Doc_definitions.html#Package' TEXT = 'Package' ATTRIBUTES = 'target="FrameWindow"' H.link(PROGPAGEFILE, URL, ATTRIBUTES, TEXT) PROGPAGEFILE.write(': ') H.end(PROGPAGEFILE, 'big') URL = '../package/' + PR.package + '.html' TEXT = PR.package H.link(PROGPAGEFILE, URL, '', TEXT) H.end(PROGPAGEFILE, 'td') H.end(PROGPAGEFILE, 'tr') # Platform row ATTRIBUTES = '' H.start(PROGPAGEFILE, 'tr', ATTRIBUTES) ATTRIBUTES = ' colspan="2" rowspan="1" style= "background-color: rgb(204, 204, 204);"' H.start(PROGPAGEFILE, 'td', ATTRIBUTES) ATTRIBUTES = '' H.start(PROGPAGEFILE, 'big', ATTRIBUTES) URL = '../Doc_definitions.html#Platforms' TEXT = 'Platforms' ATTRIBUTES = 'target="FrameWindow"' H.link(PROGPAGEFILE, URL, ATTRIBUTES, TEXT) PROGPAGEFILE.write(': ') H.end(PROGPAGEFILE, 'big') I = 0 for PLAT in PR.platform: PROGPAGEFILE.write(PLAT) I = I + 1 if I < len(PR.platform): PROGPAGEFILE.write(', ') H.end(PROGPAGEFILE, 'td') H.end(PROGPAGEFILE, 'tr') H.end(PROGPAGEFILE, 'table') H.end_page(PROGPAGEFILE) PROGPAGEFILE.close() os.chmod(PROGFN, 0o664) PROGFILE = open(PROGFN, 'w') h = HTMLWriter () h.start_page(PROGFILE, 'Program Index') h.start(PROGFILE, 'hr', '') h.start(PROGFILE, 'ul', '') # For each program, write an HTML page containing # all information for that program PROGLIST = list(PROGDICT.keys()) #PROGLIST.sort(key=HT.cmp_to_key(lambda x, y: cmp(x.lower(), y.lower()))) #PROGLIST.sort(key=lambda x: x.lower()) PROGLIST.sort(key=lambda name: name.lower()) for PROGKEY in PROGLIST: PR = PROGDICT[PROGKEY] WriteProg(PR, P) h.start(PROGFILE, 'li', '') URL = PR.name + '.html' TEXT = PR.name + ' - ' + PROGDICT[PR.name].description + '\n' h.link(PROGFILE, URL, '', TEXT) h.end(PROGFILE, 'li') h.end(PROGFILE, 'ul') h.end_page(PROGFILE) PROGFILE.close() os.chmod(PROGFN, 0o664) #======================== MAIN PROCEDURE ========================== def main(): """ Called when not in documentation mode. """ # ------------------------- Parameters ----------------------- print ("***** obtaining parameters") P = Parameters() # Read in the prefix to begin URLs that will be used as links # to documentation files. print ("***** reading BIRCH.properties") P.DOCPREFIX = BM.GetBIRCHProperties(P.BIRCHPATH,"birchURL") # When birchprops creates BIRCH.properties, some special characters # are escaped with a left slash. We need to eliminate these left slashes # which would otherwise cause web browsers to incorrectly interpret URLs P.DOCPREFIX=P.DOCPREFIX.replace("\\",""); #P.DOCPREFIX = BM.GetBIRCHProperties(P.BIRCHPATH,"birchHomeURL") #P.DOCPREFIX="" print(('P.DOCPREFIX: ' + P.DOCPREFIX)) if P.DOCPREFIX != "" : OKAY = True else : OKAY = False # ------------------------- Read birchdocdb database ----------------------- # Read in birchdocdb.sqlite, and then birchdocdb.local.sqlite. If an object is present # in both files, the object from birchdocdb.local.sqlite replaces the object # from birchdocdb.sqlite. Thus, local versions of documentation can replace # documents from the birch core. # Open connections to main birchdocdb database and local birchdocdb database Connection = sqlite3.connect(os.path.join(P.BIRCHDBPATH,"birchdocdb.sqlite")) Cursor = Connection.cursor() # Read Categories CATS = [] print ("***** reading categories") ReadCategory(Cursor, CATS) print(("Categories:"+str(len(CATS)))) for C in CATS: CATDICT[C.name] = C if os.path.exists(os.path.join(P.BIRCHLOCALDBPATH,"birchdocdb.local.sqlite")): LocalConnection = sqlite3.connect(os.path.join(P.BIRCHLOCALDBPATH,"birchdocdb.local.sqlite")) LocalCursor = LocalConnection.cursor() ReadCategory(LocalCursor, CATS) for C in CATS: CATDICT[C.name] = C print('CATDICT size: ' + str(len(CATDICT))) # Read Packages PKGS = [] print ("***** reading packages") ReadPackage(Cursor, PKGS) print(("Packages:"+str(len(PKGS)))) for PK in PKGS: PKGDICT[PK.name] = PK if os.path.exists(os.path.join(P.BIRCHLOCALDBPATH,"birchdocdb.local.sqlite")): ReadPackage(LocalCursor, PKGS) for PK in PKGS: PKGDICT[PK.name] = PK print('PKGDICT size: ' + str(len(PKGDICT))) # Read programs print ("***** reading programs") ReadProgram(Cursor, PROGS) print(("Progs:"+str(len(PROGS)))) for PR in PROGS: PROGDICT[PR.name] = PR if os.path.exists(os.path.join(P.BIRCHLOCALDBPATH,"birchdocdb.local.sqlite")): ReadProgram(LocalCursor, PROGS) for PR in PROGS: PROGDICT[PR.name] = PR print('PROGDICT size: ' + str(len(PROGDICT))) # Read documentation file names DOCFILES = [] print ("***** reading documentation filenames") ReadDocFiles(Cursor, DOCFILES) for FL in DOCFILES: DOCDICT[FL.name] = FL if os.path.exists(os.path.join(P.BIRCHLOCALDBPATH,"birchdocdb.local.sqlite")): ReadDocFiles(LocalCursor, DOCFILES) for FL in DOCFILES: DOCDICT[FL.name] = FL # ------------------------- Write Web documentation pages ----------------------- # Remove existing directories for category, program and package, # and create new empty directories # This ensures that old files that are no longer needed (such # as files describing programs or packages that have been removed) # do not clutter up the directories. print ("***** freshdir") os.chdir(P.BIRCHPATH + '/public_html/birchdocdb') FreshDir('category') FreshDir('package') FreshDir('program') #os.chdir(P.BIRCHPATH + '/install-scripts') if OKAY: print ("***** read OK *****") # - - - - - - - - - - Output to the public_html/birchdocdb directory - - - - - - # For each category write a category page in HTML print ("***** writing category pages") os.chdir('category') CATFN = 'category.html' write_category_page(CATFN) # For each all programs write an HTML page with an alphabetical list of programs print ("***** writing program pages") os.chdir('../program') PROGFN = 'program.html' WriteProgramPage(PROGFN, P) # For each package, write a package page in HTML # For each category write a category page in HTML print ("***** writing package pages") os.chdir('../package') PKGFN = 'package.html' WritePackagePage(PKGFN, P) if __name__=="__main__": if (BM.documentor() or "-test" in sys.argv): pass else: main() BM.exit_success()