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