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 addDownload(self,name,dlist): 108 if not hasattr(self.argDB,'dlist'): 109 self.argDB.dlist = {} 110 else: 111 self.argDB.dlist[name] = dlist 112 113 def output(self, f = None, sections = None): 114 '''Print a help screen with all the argument information.''' 115 if f is None: 116 import sys 117 f = sys.stdout 118 if sections: sections = [s.lower() for s in sections] 119 self.printBanner(f) 120 (nameLen, descLen) = self.getTextSizes() 121# format = ' -%-'+str(nameLen)+'s: %s\n' 122# formatDef = ' -%-'+str(nameLen)+'s: %-'+str(descLen)+'s current: %s\n' 123 format = ' -%s\n %s\n' 124 formatDef = ' -%s\n %s current: %s\n' 125 items = self.sections.items() 126 items.sort(lambda a, b: a[1][0].__cmp__(b[1][0])) 127 for section, names in items: 128 if sections and not section.lower() in sections: continue 129 f.write(section+':\n') 130 for name in names[1]: 131 argName = self.getArgName(name) 132 type = self.argDB.getType(argName) 133 if argName in self.argDB: 134 f.write(formatDef % (name, type.help, str(self.argDB.getType(argName)))) 135 else: 136 f.write(format % (name, type.help)) 137 return 138 139 def outputDownload(self): 140 import nargs 141 import os 142 import sys 143 pkgdir = nargs.Arg.findArgument('with-packages-dir', self.clArgs) 144 missing = 0 145 print 'Download the following packages to '+pkgdir+' \n' 146 for i in self.argDB.dlist.keys(): 147 if not nargs.Arg.findArgument('download-'+i, self.clArgs) == None and not nargs.Arg.findArgument('download-'+i, self.clArgs) == '0': 148 dlist = self.argDB.dlist[i] 149 found = 0 150 for k in range(0,len(dlist)): 151 fd = os.path.join(pkgdir,os.path.basename(dlist[k])) 152 if os.path.isdir(fd) or os.path.isfile(fd): 153 found = 1 154 for k in range(0,len(self.clArgs)): 155 if self.clArgs[k].startswith('--download-'+i): 156 self.clArgs[k] = 'download-'+i+'='+fd 157 self.argDB.insertArgs([self.clArgs[k]]) 158 break 159 if not found: 160 print i + ' ' + str(self.argDB.dlist[i]) 161 missing = 1 162 if missing: 163 sys.exit() 164 165 166