1*179860b2SJed Brown'''This module is meant to provide support for information and help systems based upon RDict.''' 2*179860b2SJed Brownimport logger 3*179860b2SJed Brown 4*179860b2SJed Brownclass Info(logger.Logger): 5*179860b2SJed Brown '''This basic class provides information independent of RDict''' 6*179860b2SJed Brown def __init__(self, argDB = None): 7*179860b2SJed Brown '''Creates a dictionary "sections" whose keys are section names, and values are a tuple of (ordinal, nameList)''' 8*179860b2SJed Brown logger.Logger.__init__(self, None, argDB) 9*179860b2SJed Brown self.sections = {} 10*179860b2SJed Brown return 11*179860b2SJed Brown 12*179860b2SJed Brown def getTitle(self): 13*179860b2SJed Brown return self._title 14*179860b2SJed Brown 15*179860b2SJed Brown def setTitle(self, title): 16*179860b2SJed Brown self._title = str(title) 17*179860b2SJed Brown title = property(getTitle, setTitle, None, 'Title of the Information Menu') 18*179860b2SJed Brown 19*179860b2SJed Brown def getDescription(self, section, name): 20*179860b2SJed Brown return self._desc[(section, name)] 21*179860b2SJed Brown 22*179860b2SJed Brown def setDescription(self, section, name, desc): 23*179860b2SJed Brown if not hasattr(self, '_desc'): 24*179860b2SJed Brown self._desc = {} 25*179860b2SJed Brown self._desc[(section, name)] = desc 26*179860b2SJed Brown return 27*179860b2SJed Brown 28*179860b2SJed Brown def addArgument(self, section, name, desc): 29*179860b2SJed Brown '''Add an argument with given name and string to an information section''' 30*179860b2SJed Brown if not section in self.sections: 31*179860b2SJed Brown self.sections[section] = (len(self.sections), []) 32*179860b2SJed Brown if name in self.sections[section][1]: 33*179860b2SJed Brown name += '@'+str(len(filter(lambda n: name == n.split('@')[0], self.sections[section][1]))+1) 34*179860b2SJed Brown self.sections[section][1].append(name) 35*179860b2SJed Brown self.setDescription(section, name, desc) 36*179860b2SJed Brown return 37*179860b2SJed Brown 38*179860b2SJed Brown def printBanner(self, f): 39*179860b2SJed Brown '''Print a banner for the information screen''' 40*179860b2SJed Brown f.write(self.title+'\n') 41*179860b2SJed Brown for i in range(max(map(len, self.title.split('\n')))): f.write('-') 42*179860b2SJed Brown f.write('\n') 43*179860b2SJed Brown return 44*179860b2SJed Brown 45*179860b2SJed Brown def getTextSizes(self): 46*179860b2SJed Brown '''Returns the maximum name and description lengths''' 47*179860b2SJed Brown nameLen = 1 48*179860b2SJed Brown descLen = 1 49*179860b2SJed Brown for section in self.sections: 50*179860b2SJed Brown nameLen = max([nameLen, max(map(lambda n: len(n.split('@')[0]), self.sections[section][1]))+1]) 51*179860b2SJed Brown descLen = max([descLen, max(map(lambda name: len(self.getDescription(section, name)), self.sections[section][1]))+1]) 52*179860b2SJed Brown return (nameLen, descLen) 53*179860b2SJed Brown 54*179860b2SJed Brown def output(self, f = None): 55*179860b2SJed Brown '''Print a help screen with all the argument information.''' 56*179860b2SJed Brown if f is None: 57*179860b2SJed Brown import sys 58*179860b2SJed Brown f = sys.stdout 59*179860b2SJed Brown self.printBanner(f) 60*179860b2SJed Brown (nameLen, descLen) = self.getTextSizes() 61*179860b2SJed Brown format = ' %-'+str(nameLen)+'s: %s\n' 62*179860b2SJed Brown items = self.sections.items() 63*179860b2SJed Brown items.sort(lambda a, b: a[1][0].__cmp__(b[1][0])) 64*179860b2SJed Brown for section, names in items: 65*179860b2SJed Brown f.write(section+':\n') 66*179860b2SJed Brown for name in names[1]: 67*179860b2SJed Brown f.write(format % (name.split('@')[0], self.getDescription(section, name))) 68*179860b2SJed Brown return 69*179860b2SJed Brown 70*179860b2SJed Brownclass Help(Info): 71*179860b2SJed Brown '''Help provides a simple help system for RDict''' 72*179860b2SJed Brown def __init__(self, argDB): 73*179860b2SJed Brown '''Creates a dictionary "sections" whose keys are section names, and values are a tuple of (ordinal, nameList). Also provide the RDict upon which this will be based.''' 74*179860b2SJed Brown Info.__init__(self, argDB) 75*179860b2SJed Brown self.title = 'Help' 76*179860b2SJed Brown return 77*179860b2SJed Brown 78*179860b2SJed Brown def getDescription(self, section, name): 79*179860b2SJed Brown return self.argDB.getType(self.getArgName(name)).help 80*179860b2SJed Brown 81*179860b2SJed Brown def setDescription(self, section, name, desc): 82*179860b2SJed Brown return 83*179860b2SJed Brown 84*179860b2SJed Brown def getArgName(self, name): 85*179860b2SJed Brown '''Return the RDict key corresponding to a more verbose help name. Right now, this means discard everything after "=".''' 86*179860b2SJed Brown #return name.split('=')[0].strip('-') 87*179860b2SJed Brown argName = name.split('=')[0] 88*179860b2SJed Brown while argName[0] == '-': argName = argName[1:] 89*179860b2SJed Brown return argName 90*179860b2SJed Brown 91*179860b2SJed Brown def addArgument(self, section, name, argType, ignoreDuplicates = 0): 92*179860b2SJed Brown '''Add an argument with given name and type to a help section. The type, which can also have an initializer and help string, will be put into RDict.''' 93*179860b2SJed Brown## super(Info, self).addArgument(section, name, None) 94*179860b2SJed Brown if section in self.sections: 95*179860b2SJed Brown if name in self.sections[section][1]: 96*179860b2SJed Brown if ignoreDuplicates: 97*179860b2SJed Brown return 98*179860b2SJed Brown raise RuntimeError('Duplicate configure option '+name+' in section '+section) 99*179860b2SJed Brown else: 100*179860b2SJed Brown self.sections[section] = (len(self.sections), []) 101*179860b2SJed Brown if not argType.deprecated: 102*179860b2SJed Brown self.sections[section][1].append(name) 103*179860b2SJed Brown 104*179860b2SJed Brown self.argDB.setType(self.getArgName(name), argType, forceLocal = 1) 105*179860b2SJed Brown return 106*179860b2SJed Brown 107*179860b2SJed Brown def output(self, f = None, sections = None): 108*179860b2SJed Brown '''Print a help screen with all the argument information.''' 109*179860b2SJed Brown if f is None: 110*179860b2SJed Brown import sys 111*179860b2SJed Brown f = sys.stdout 112*179860b2SJed Brown if sections: sections = [s.lower() for s in sections] 113*179860b2SJed Brown self.printBanner(f) 114*179860b2SJed Brown (nameLen, descLen) = self.getTextSizes() 115*179860b2SJed Brown# format = ' -%-'+str(nameLen)+'s: %s\n' 116*179860b2SJed Brown# formatDef = ' -%-'+str(nameLen)+'s: %-'+str(descLen)+'s current: %s\n' 117*179860b2SJed Brown format = ' -%s\n %s\n' 118*179860b2SJed Brown formatDef = ' -%s\n %s current: %s\n' 119*179860b2SJed Brown items = self.sections.items() 120*179860b2SJed Brown items.sort(lambda a, b: a[1][0].__cmp__(b[1][0])) 121*179860b2SJed Brown for section, names in items: 122*179860b2SJed Brown if sections and not section.lower() in sections: continue 123*179860b2SJed Brown f.write(section+':\n') 124*179860b2SJed Brown for name in names[1]: 125*179860b2SJed Brown argName = self.getArgName(name) 126*179860b2SJed Brown type = self.argDB.getType(argName) 127*179860b2SJed Brown if argName in self.argDB: 128*179860b2SJed Brown f.write(formatDef % (name, type.help, str(self.argDB.getType(argName)))) 129*179860b2SJed Brown else: 130*179860b2SJed Brown f.write(format % (name, type.help)) 131*179860b2SJed Brown return 132