xref: /petsc/config/BuildSystem/help.py (revision c524ecbbce6aa063af9ca27248ef883cbe329b4c)
1179860b2SJed Brown'''This module is meant to provide support for information and help systems based upon RDict.'''
2179860b2SJed Brownimport logger
3179860b2SJed Brown
4179860b2SJed Brownclass Info(logger.Logger):
5179860b2SJed Brown  '''This basic class provides information independent of RDict'''
6179860b2SJed Brown  def __init__(self, argDB = None):
7179860b2SJed Brown    '''Creates a dictionary "sections" whose keys are section names, and values are a tuple of (ordinal, nameList)'''
8179860b2SJed Brown    logger.Logger.__init__(self, None, argDB)
9179860b2SJed Brown    self.sections = {}
10179860b2SJed Brown    return
11179860b2SJed Brown
12179860b2SJed Brown  def getTitle(self):
13179860b2SJed Brown    return self._title
14179860b2SJed Brown
15179860b2SJed Brown  def setTitle(self, title):
16179860b2SJed Brown    self._title = str(title)
17179860b2SJed Brown  title = property(getTitle, setTitle, None, 'Title of the Information Menu')
18179860b2SJed Brown
19179860b2SJed Brown  def getDescription(self, section, name):
20179860b2SJed Brown    return self._desc[(section, name)]
21179860b2SJed Brown
22179860b2SJed Brown  def setDescription(self, section, name, desc):
23179860b2SJed Brown    if not hasattr(self, '_desc'):
24179860b2SJed Brown      self._desc = {}
25179860b2SJed Brown    self._desc[(section, name)] = desc
26179860b2SJed Brown    return
27179860b2SJed Brown
28179860b2SJed Brown  def addArgument(self, section, name, desc):
29179860b2SJed Brown    '''Add an argument with given name and string to an information section'''
30179860b2SJed Brown    if not section in self.sections:
31179860b2SJed Brown      self.sections[section] = (len(self.sections), [])
32179860b2SJed Brown    if name in self.sections[section][1]:
33179860b2SJed Brown      name += '@'+str(len(filter(lambda n: name == n.split('@')[0], self.sections[section][1]))+1)
34179860b2SJed Brown    self.sections[section][1].append(name)
35179860b2SJed Brown    self.setDescription(section, name, desc)
36179860b2SJed Brown    return
37179860b2SJed Brown
38179860b2SJed Brown  def printBanner(self, f):
39179860b2SJed Brown    '''Print a banner for the information screen'''
40179860b2SJed Brown    f.write(self.title+'\n')
41179860b2SJed Brown    for i in range(max(map(len, self.title.split('\n')))): f.write('-')
42179860b2SJed Brown    f.write('\n')
43179860b2SJed Brown    return
44179860b2SJed Brown
45179860b2SJed Brown  def getTextSizes(self):
46179860b2SJed Brown    '''Returns the maximum name and description lengths'''
47179860b2SJed Brown    nameLen = 1
48179860b2SJed Brown    descLen = 1
49179860b2SJed Brown    for section in self.sections:
50179860b2SJed Brown      nameLen = max([nameLen, max(map(lambda n: len(n.split('@')[0]), self.sections[section][1]))+1])
51179860b2SJed Brown      descLen = max([descLen, max(map(lambda name: len(self.getDescription(section, name)), self.sections[section][1]))+1])
52179860b2SJed Brown    return (nameLen, descLen)
53179860b2SJed Brown
54179860b2SJed Brown  def output(self, f = None):
55179860b2SJed Brown    '''Print a help screen with all the argument information.'''
56179860b2SJed Brown    if f is  None:
57179860b2SJed Brown      import sys
58179860b2SJed Brown      f = sys.stdout
59179860b2SJed Brown    self.printBanner(f)
60179860b2SJed Brown    (nameLen, descLen) = self.getTextSizes()
61179860b2SJed Brown    format = '  %-'+str(nameLen)+'s: %s\n'
62179860b2SJed Brown    items  = self.sections.items()
63179860b2SJed Brown    items.sort(lambda a, b: a[1][0].__cmp__(b[1][0]))
64179860b2SJed Brown    for section, names in items:
65179860b2SJed Brown      f.write(section+':\n')
66179860b2SJed Brown      for name in names[1]:
67179860b2SJed Brown        f.write(format % (name.split('@')[0], self.getDescription(section, name)))
68179860b2SJed Brown    return
69179860b2SJed Brown
70b93f8388SBarry Smith# I don't know how to not have this stupid global variable
71b93f8388SBarry Smith_outputDownloadDone = 0
72b93f8388SBarry Smith
73179860b2SJed Brownclass Help(Info):
74179860b2SJed Brown  '''Help provides a simple help system for RDict'''
75179860b2SJed Brown  def __init__(self, argDB):
76179860b2SJed 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.'''
77179860b2SJed Brown    Info.__init__(self, argDB)
78179860b2SJed Brown    self.title = 'Help'
79179860b2SJed Brown    return
80179860b2SJed Brown
81179860b2SJed Brown  def getDescription(self, section, name):
82179860b2SJed Brown    return self.argDB.getType(self.getArgName(name)).help
83179860b2SJed Brown
84179860b2SJed Brown  def setDescription(self, section, name, desc):
85179860b2SJed Brown    return
86179860b2SJed Brown
87179860b2SJed Brown  def getArgName(self, name):
88179860b2SJed Brown    '''Return the RDict key corresponding to a more verbose help name. Right now, this means discard everything after "=".'''
89179860b2SJed Brown    #return name.split('=')[0].strip('-')
90179860b2SJed Brown    argName = name.split('=')[0]
91179860b2SJed Brown    while argName[0] == '-': argName = argName[1:]
92179860b2SJed Brown    return argName
93179860b2SJed Brown
94179860b2SJed Brown  def addArgument(self, section, name, argType, ignoreDuplicates = 0):
95179860b2SJed 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.'''
96179860b2SJed Brown##  super(Info, self).addArgument(section, name, None)
97179860b2SJed Brown    if section in self.sections:
98179860b2SJed Brown      if name in self.sections[section][1]:
99179860b2SJed Brown        if ignoreDuplicates:
100179860b2SJed Brown          return
101179860b2SJed Brown        raise RuntimeError('Duplicate configure option '+name+' in section '+section)
102179860b2SJed Brown    else:
103179860b2SJed Brown      self.sections[section] = (len(self.sections), [])
104179860b2SJed Brown    if not argType.deprecated:
105179860b2SJed Brown      self.sections[section][1].append(name)
106179860b2SJed Brown
107179860b2SJed Brown    self.argDB.setType(self.getArgName(name), argType, forceLocal = 1)
108179860b2SJed Brown    return
109179860b2SJed Brown
11075f179b0SBarry Smith  def addDownload(self,name,dlist):
11175f179b0SBarry Smith    if not hasattr(self.argDB,'dlist'):
11275f179b0SBarry Smith      self.argDB.dlist = {}
11375f179b0SBarry Smith    else:
11475f179b0SBarry Smith      self.argDB.dlist[name] = dlist
11575f179b0SBarry Smith
116179860b2SJed Brown  def output(self, f = None, sections = None):
117179860b2SJed Brown    '''Print a help screen with all the argument information.'''
118179860b2SJed Brown    if f is  None:
119179860b2SJed Brown      import sys
120179860b2SJed Brown      f = sys.stdout
121179860b2SJed Brown    if sections: sections = [s.lower() for s in sections]
122179860b2SJed Brown    self.printBanner(f)
123179860b2SJed Brown    (nameLen, descLen) = self.getTextSizes()
124179860b2SJed Brown#    format    = '  -%-'+str(nameLen)+'s: %s\n'
125179860b2SJed Brown#    formatDef = '  -%-'+str(nameLen)+'s: %-'+str(descLen)+'s  current: %s\n'
126179860b2SJed Brown    format    = '  -%s\n       %s\n'
127179860b2SJed Brown    formatDef = '  -%s\n       %s  current: %s\n'
128179860b2SJed Brown    items = self.sections.items()
129179860b2SJed Brown    items.sort(lambda a, b: a[1][0].__cmp__(b[1][0]))
130179860b2SJed Brown    for section, names in items:
131179860b2SJed Brown      if sections and not section.lower() in sections: continue
132179860b2SJed Brown      f.write(section+':\n')
133179860b2SJed Brown      for name in names[1]:
134179860b2SJed Brown        argName = self.getArgName(name)
135179860b2SJed Brown        type    = self.argDB.getType(argName)
136179860b2SJed Brown        if argName in self.argDB:
137179860b2SJed Brown          f.write(formatDef % (name, type.help, str(self.argDB.getType(argName))))
138179860b2SJed Brown        else:
139179860b2SJed Brown          f.write(format % (name, type.help))
140179860b2SJed Brown    return
14175f179b0SBarry Smith
142b93f8388SBarry Smith
14375f179b0SBarry Smith  def outputDownload(self):
144b93f8388SBarry Smith    ''' Looks for downloaded packages in --with-packages-dir
145b93f8388SBarry Smith        For any it finds it updates the --download-xxx= argument to point to this local copy
146b93f8388SBarry Smith        If it does not find some needed packages then prints the packages that need to be downloaded and exits'''
14775f179b0SBarry Smith    import nargs
14875f179b0SBarry Smith    import os
14975f179b0SBarry Smith    import sys
150b93f8388SBarry Smith    global _outputDownloadDone
151b93f8388SBarry Smith    if _outputDownloadDone: return
152b93f8388SBarry Smith    _outputDownloadDone = 1
153b93f8388SBarry Smith    pkgdir = os.path.abspath(os.path.expanduser(nargs.Arg.findArgument('with-packages-dir', self.clArgs)))
15475f179b0SBarry Smith    missing = 0
155b93f8388SBarry Smith    for i in self.argDB.dlist.keys():
156b93f8388SBarry Smith      if not nargs.Arg.findArgument('download-'+i, self.clArgs) == None and not nargs.Arg.findArgument('download-'+i, self.clArgs) == '0':
157b93f8388SBarry Smith        dlist = self.argDB.dlist[i]
158b93f8388SBarry Smith        found = 0
159b93f8388SBarry Smith        for k in range(0,len(dlist)):
160b93f8388SBarry Smith          fd = os.path.join(pkgdir,os.path.basename(dlist[k]))
161b93f8388SBarry Smith          if os.path.isdir(fd) or os.path.isfile(fd):
162b93f8388SBarry Smith            found = 1
163b93f8388SBarry Smith            break
164b93f8388SBarry Smith        if not found:
165b93f8388SBarry Smith          missing = 1
166b93f8388SBarry Smith    if missing:
16775f179b0SBarry Smith      print 'Download the following packages to '+pkgdir+' \n'
16875f179b0SBarry Smith      for i in self.argDB.dlist.keys():
16975f179b0SBarry Smith        if not nargs.Arg.findArgument('download-'+i, self.clArgs) == None and not nargs.Arg.findArgument('download-'+i, self.clArgs) == '0':
17075f179b0SBarry Smith          dlist = self.argDB.dlist[i]
17175f179b0SBarry Smith          found = 0
17275f179b0SBarry Smith          for k in range(0,len(dlist)):
17375f179b0SBarry Smith            fd = os.path.join(pkgdir,os.path.basename(dlist[k]))
17475f179b0SBarry Smith            if os.path.isdir(fd) or os.path.isfile(fd):
17575f179b0SBarry Smith              found = 1
17675f179b0SBarry Smith              for k in range(0,len(self.clArgs)):
17775f179b0SBarry Smith                if self.clArgs[k].startswith('--download-'+i):
17875f179b0SBarry Smith                  self.clArgs[k] = 'download-'+i+'='+fd
17975f179b0SBarry Smith                  self.argDB.insertArgs([self.clArgs[k]])
18075f179b0SBarry Smith              break
18175f179b0SBarry Smith          if not found:
18275f179b0SBarry Smith            print i + ' ' + str(self.argDB.dlist[i])
183b93f8388SBarry Smith      print '\nThen run the script again\n'
184*c524ecbbSBarry Smith      sys.exit(10)
18575f179b0SBarry Smith
18675f179b0SBarry Smith
187