xref: /petsc/config/BuildSystem/nargs.py (revision 179860b23afbef20daed3359c1645679d1efa988)
1*179860b2SJed Browntry:
2*179860b2SJed Brown  import readline
3*179860b2SJed Brownexcept ImportError: pass
4*179860b2SJed Brown
5*179860b2SJed Browndef getInteractive():
6*179860b2SJed Brown  return isInteractive
7*179860b2SJed Brown
8*179860b2SJed Browndef setInteractive(interactive):
9*179860b2SJed Brown  global isInteractive
10*179860b2SJed Brown  isInteractive = interactive
11*179860b2SJed Brown  return
12*179860b2SJed Brown
13*179860b2SJed Browndef checkInteractive(key):
14*179860b2SJed Brown  if not isInteractive:
15*179860b2SJed Brown    raise ValueError('Value not set for key '+str(key))
16*179860b2SJed Brown  return
17*179860b2SJed BrownsetInteractive(1)
18*179860b2SJed Brown
19*179860b2SJed Brownclass Arg(object):
20*179860b2SJed Brown  '''This is the base class for all objects contained in RDict. Access to the raw argument values is
21*179860b2SJed Brownprovided by getValue() and setValue(). These objects can be thought of as type objects for the
22*179860b2SJed Brownvalues themselves. It is possible to set an Arg in the RDict which has not yet been assigned a value
23*179860b2SJed Brownin order to declare the type of that option.
24*179860b2SJed Brown
25*179860b2SJed BrownInputs which cannot be converted to the correct type will cause TypeError, those failing validation
26*179860b2SJed Browntests will cause ValueError.
27*179860b2SJed Brown'''
28*179860b2SJed Brown  def __init__(self, key, value = None, help = '', isTemporary = False, deprecated = False):
29*179860b2SJed Brown    self.key         = key
30*179860b2SJed Brown    self.help        = help
31*179860b2SJed Brown    self.isTemporary = isTemporary
32*179860b2SJed Brown    self.deprecated  = False
33*179860b2SJed Brown    if not value is None:
34*179860b2SJed Brown      self.setValue(value)
35*179860b2SJed Brown    self.deprecated  = deprecated
36*179860b2SJed Brown    return
37*179860b2SJed Brown
38*179860b2SJed Brown  def isValueSet(self):
39*179860b2SJed Brown    '''Determines whether the value of this argument has been set'''
40*179860b2SJed Brown    return hasattr(self, 'value')
41*179860b2SJed Brown
42*179860b2SJed Brown  def getTemporary(self):
43*179860b2SJed Brown    '''Retrieve the flag indicating whether the item should be persistent'''
44*179860b2SJed Brown    return self.isTemporary
45*179860b2SJed Brown
46*179860b2SJed Brown  def setTemporary(self, isTemporary):
47*179860b2SJed Brown    '''Set the flag indicating whether the item should be persistent'''
48*179860b2SJed Brown    self.isTemporary = isTemporary
49*179860b2SJed Brown    return
50*179860b2SJed Brown
51*179860b2SJed Brown  def parseValue(arg):
52*179860b2SJed Brown    '''Return the object represented by the value portion of a string argument'''
53*179860b2SJed Brown    # Should I replace this with a lexer?
54*179860b2SJed Brown    if arg: arg = arg.strip()
55*179860b2SJed Brown    if arg and arg[0] == '[' and arg[-1] == ']':
56*179860b2SJed Brown      if len(arg) > 2: value = arg[1:-1].split(',')
57*179860b2SJed Brown      else:            value = []
58*179860b2SJed Brown    elif arg and arg[0] == '{' and arg[-1] == '}':
59*179860b2SJed Brown      value = {}
60*179860b2SJed Brown      idx = 1
61*179860b2SJed Brown      oldIdx = idx
62*179860b2SJed Brown      while idx < len(arg)-1:
63*179860b2SJed Brown        if arg[oldIdx] == ',':
64*179860b2SJed Brown          oldIdx += 1
65*179860b2SJed Brown        while not arg[idx] == ':': idx += 1
66*179860b2SJed Brown        key = arg[oldIdx:idx]
67*179860b2SJed Brown        idx += 1
68*179860b2SJed Brown        oldIdx = idx
69*179860b2SJed Brown        nesting = 0
70*179860b2SJed Brown        while not (arg[idx] == ',' or arg[idx] == '}') or nesting:
71*179860b2SJed Brown          if arg[idx] == '[':
72*179860b2SJed Brown            nesting += 1
73*179860b2SJed Brown          elif arg[idx] == ']':
74*179860b2SJed Brown            nesting -= 1
75*179860b2SJed Brown          idx += 1
76*179860b2SJed Brown        value[key] = Arg.parseValue(arg[oldIdx:idx])
77*179860b2SJed Brown        oldIdx = idx
78*179860b2SJed Brown    else:
79*179860b2SJed Brown      value = arg
80*179860b2SJed Brown    return value
81*179860b2SJed Brown  parseValue = staticmethod(parseValue)
82*179860b2SJed Brown
83*179860b2SJed Brown  def parseArgument(arg, ignoreDouble = 0):
84*179860b2SJed Brown    '''Split an argument into a (key, value) tuple, stripping off the leading dashes. Return (None, None) on failure.'''
85*179860b2SJed Brown    start = 0
86*179860b2SJed Brown    if arg and arg[0] == '-':
87*179860b2SJed Brown      start = 1
88*179860b2SJed Brown      if arg[1] == '-' and not ignoreDouble:
89*179860b2SJed Brown        start = 2
90*179860b2SJed Brown    if arg.find('=') >= 0:
91*179860b2SJed Brown      (key, value) = arg[start:].split('=', 1)
92*179860b2SJed Brown    else:
93*179860b2SJed Brown      if start == 0:
94*179860b2SJed Brown        (key, value) = (None, arg)
95*179860b2SJed Brown      else:
96*179860b2SJed Brown        (key, value) = (arg[start:], '1')
97*179860b2SJed Brown    return (key, Arg.parseValue(value))
98*179860b2SJed Brown
99*179860b2SJed Brown  parseArgument = staticmethod(parseArgument)
100*179860b2SJed Brown
101*179860b2SJed Brown  def findArgument(key, argList):
102*179860b2SJed Brown    '''Locate an argument with the given key in argList, returning the value or None on failure
103*179860b2SJed Brown       - This is generally used to process arguments which must take effect before canonical argument parsing'''
104*179860b2SJed Brown    if not isinstance(argList, list): return None
105*179860b2SJed Brown    # Reverse the list so that we preserve the semantics which state that the last
106*179860b2SJed Brown    #   argument with a given key takes effect
107*179860b2SJed Brown    l = argList[:]
108*179860b2SJed Brown    l.reverse()
109*179860b2SJed Brown    for arg in l:
110*179860b2SJed Brown      (k, value) = Arg.parseArgument(arg)
111*179860b2SJed Brown      if k == key:
112*179860b2SJed Brown        return value
113*179860b2SJed Brown    return None
114*179860b2SJed Brown  findArgument = staticmethod(findArgument)
115*179860b2SJed Brown
116*179860b2SJed Brown  def processAlternatePrefixes(argList):
117*179860b2SJed Brown    '''Convert alternate prefixes to our normal form'''
118*179860b2SJed Brown    for l in range(0, len(argList)):
119*179860b2SJed Brown      name = argList[l]
120*179860b2SJed Brown      if name.find('enable-') >= 0:
121*179860b2SJed Brown        argList[l] = name.replace('enable-','with-')
122*179860b2SJed Brown        if name.find('=') == -1: argList[l] = argList[l]+'=1'
123*179860b2SJed Brown      if name.find('disable-') >= 0:
124*179860b2SJed Brown        argList[l] = name.replace('disable-','with-')
125*179860b2SJed Brown        if name.find('=') == -1: argList[l] = argList[l]+'=0'
126*179860b2SJed Brown        elif name.endswith('=1'): argList[l].replace('=1','=0')
127*179860b2SJed Brown      if name.find('without-') >= 0:
128*179860b2SJed Brown        argList[l] = name.replace('without-','with-')
129*179860b2SJed Brown        if name.find('=') == -1: argList[l] = argList[l]+'=0'
130*179860b2SJed Brown        elif name.endswith('=1'): argList[l].replace('=1','=0')
131*179860b2SJed Brown    return
132*179860b2SJed Brown  processAlternatePrefixes = staticmethod(processAlternatePrefixes)
133*179860b2SJed Brown
134*179860b2SJed Brown  def __str__(self):
135*179860b2SJed Brown    if not self.isValueSet():
136*179860b2SJed Brown      return 'Empty '+str(self.__class__)
137*179860b2SJed Brown    elif isinstance(self.value, list):
138*179860b2SJed Brown      return str(map(str, self.value))
139*179860b2SJed Brown    return str(self.value)
140*179860b2SJed Brown
141*179860b2SJed Brown  def getEntryPrompt(self):
142*179860b2SJed Brown    return 'Please enter value for '+str(self.key)+': '
143*179860b2SJed Brown
144*179860b2SJed Brown  def getKey(self):
145*179860b2SJed Brown    '''Returns the key. SHOULD MAKE THIS A PROPERTY'''
146*179860b2SJed Brown    return self.key
147*179860b2SJed Brown
148*179860b2SJed Brown  def setKey(self, key):
149*179860b2SJed Brown    '''Set the key. SHOULD MAKE THIS A PROPERTY'''
150*179860b2SJed Brown    self.key = key
151*179860b2SJed Brown    return
152*179860b2SJed Brown
153*179860b2SJed Brown  def getValue(self):
154*179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
155*179860b2SJed Brown    if not self.isValueSet():
156*179860b2SJed Brown      checkInteractive(self.key)
157*179860b2SJed Brown      if self.help: print self.help
158*179860b2SJed Brown      while 1:
159*179860b2SJed Brown        try:
160*179860b2SJed Brown          self.setValue(Arg.parseValue(raw_input(self.getEntryPrompt())))
161*179860b2SJed Brown          break
162*179860b2SJed Brown        except KeyboardInterrupt:
163*179860b2SJed Brown          raise KeyError('Could not find value for key '+str(self.key))
164*179860b2SJed Brown        except TypeError, e:
165*179860b2SJed Brown          print str(e)
166*179860b2SJed Brown    return self.value
167*179860b2SJed Brown
168*179860b2SJed Brown  def checkKey(self):
169*179860b2SJed Brown    if self.deprecated:
170*179860b2SJed Brown      if isinstance(self.deprecated, str):
171*179860b2SJed Brown        raise KeyError('Deprecated option '+self.key+' should be '+self.deprecated)
172*179860b2SJed Brown      raise KeyError('Deprecated option '+self.key)
173*179860b2SJed Brown    return
174*179860b2SJed Brown
175*179860b2SJed Brown  def setValue(self, value):
176*179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
177*179860b2SJed Brown    self.checkKey()
178*179860b2SJed Brown    self.value = value
179*179860b2SJed Brown    return
180*179860b2SJed Brown
181*179860b2SJed Brownclass ArgBool(Arg):
182*179860b2SJed Brown  '''Arguments that represent boolean values'''
183*179860b2SJed Brown  def __init__(self, key, value = None, help = '', isTemporary = 0, deprecated = False):
184*179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
185*179860b2SJed Brown    return
186*179860b2SJed Brown
187*179860b2SJed Brown  def getEntryPrompt(self):
188*179860b2SJed Brown    return 'Please enter boolean value for '+str(self.key)+': '
189*179860b2SJed Brown
190*179860b2SJed Brown  def setValue(self, value):
191*179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
192*179860b2SJed Brown    self.checkKey()
193*179860b2SJed Brown    try:
194*179860b2SJed Brown      if   value == 'no':    value = 0
195*179860b2SJed Brown      elif value == 'yes':   value = 1
196*179860b2SJed Brown      elif value == 'true':  value = 1
197*179860b2SJed Brown      elif value == 'false': value = 0
198*179860b2SJed Brown      elif value == 'True':  value = 1
199*179860b2SJed Brown      elif value == 'False': value = 0
200*179860b2SJed Brown      else:                  value = int(value)
201*179860b2SJed Brown    except:
202*179860b2SJed Brown      raise TypeError('Invalid boolean value: '+str(value)+' for key '+str(self.key))
203*179860b2SJed Brown    self.value = value
204*179860b2SJed Brown    return
205*179860b2SJed Brown
206*179860b2SJed Brownclass ArgFuzzyBool(Arg):
207*179860b2SJed Brown  '''Arguments that represent boolean values of an extended set'''
208*179860b2SJed Brown  def __init__(self, key, value = None, help = '', isTemporary = 0, deprecated = False):
209*179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
210*179860b2SJed Brown    return
211*179860b2SJed Brown
212*179860b2SJed Brown  def valueName(self, value):
213*179860b2SJed Brown    if value == 0:
214*179860b2SJed Brown      return 'no'
215*179860b2SJed Brown    elif value == 1:
216*179860b2SJed Brown      return 'yes'
217*179860b2SJed Brown    elif value == 2:
218*179860b2SJed Brown      return 'ifneeded'
219*179860b2SJed Brown    return str(value)
220*179860b2SJed Brown
221*179860b2SJed Brown  def __str__(self):
222*179860b2SJed Brown    if not self.isValueSet():
223*179860b2SJed Brown      return 'Empty '+str(self.__class__)
224*179860b2SJed Brown    elif isinstance(self.value, list):
225*179860b2SJed Brown      return str(map(self.valueName, self.value))
226*179860b2SJed Brown    return self.valueName(self.value)
227*179860b2SJed Brown
228*179860b2SJed Brown  def getEntryPrompt(self):
229*179860b2SJed Brown    return 'Please enter fuzzy boolean value for '+str(self.key)+': '
230*179860b2SJed Brown
231*179860b2SJed Brown  def setValue(self, value):
232*179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
233*179860b2SJed Brown    self.checkKey()
234*179860b2SJed Brown    try:
235*179860b2SJed Brown      if   value == '0':        value = 0
236*179860b2SJed Brown      elif value == '1':        value = 1
237*179860b2SJed Brown      elif value == 'no':       value = 0
238*179860b2SJed Brown      elif value == 'yes':      value = 1
239*179860b2SJed Brown      elif value == 'false':    value = 0
240*179860b2SJed Brown      elif value == 'true':     value = 1
241*179860b2SJed Brown      elif value == 'maybe':    value = 2
242*179860b2SJed Brown      elif value == 'ifneeded': value = 2
243*179860b2SJed Brown      elif value == 'client':   value = 2
244*179860b2SJed Brown      elif value == 'server':   value = 3
245*179860b2SJed Brown      else:                     value = int(value)
246*179860b2SJed Brown    except:
247*179860b2SJed Brown      raise TypeError('Invalid fuzzy boolean value: '+str(value)+' for key '+str(self.key))
248*179860b2SJed Brown    self.value = value
249*179860b2SJed Brown    return
250*179860b2SJed Brown
251*179860b2SJed Brownclass ArgInt(Arg):
252*179860b2SJed Brown  '''Arguments that represent integer numbers'''
253*179860b2SJed Brown  def __init__(self, key, value = None, help = '', min = -2147483647L, max = 2147483648L, isTemporary = 0, deprecated = False):
254*179860b2SJed Brown    self.min = min
255*179860b2SJed Brown    self.max = max
256*179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
257*179860b2SJed Brown    return
258*179860b2SJed Brown
259*179860b2SJed Brown  def getEntryPrompt(self):
260*179860b2SJed Brown    return 'Please enter integer value for '+str(self.key)+': '
261*179860b2SJed Brown
262*179860b2SJed Brown  def setValue(self, value):
263*179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
264*179860b2SJed Brown    self.checkKey()
265*179860b2SJed Brown    try:
266*179860b2SJed Brown      value = int(value)
267*179860b2SJed Brown    except:
268*179860b2SJed Brown      raise TypeError('Invalid integer number: '+str(value)+' for key '+str(self.key))
269*179860b2SJed Brown    if value < self.min or value >= self.max:
270*179860b2SJed Brown      raise ValueError('Number out of range: '+str(value)+' not in ['+str(self.min)+','+str(self.max)+')'+' for key '+str(self.key))
271*179860b2SJed Brown    self.value = value
272*179860b2SJed Brown    return
273*179860b2SJed Brown
274*179860b2SJed Brownclass ArgReal(Arg):
275*179860b2SJed Brown  '''Arguments that represent floating point numbers'''
276*179860b2SJed Brown  def __init__(self, key, value = None, help = '', min = -1.7976931348623157e308, max = 1.7976931348623157e308, isTemporary = 0, deprecated = False):
277*179860b2SJed Brown    self.min = min
278*179860b2SJed Brown    self.max = max
279*179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
280*179860b2SJed Brown    return
281*179860b2SJed Brown
282*179860b2SJed Brown  def getEntryPrompt(self):
283*179860b2SJed Brown    return 'Please enter floating point value for '+str(self.key)+': '
284*179860b2SJed Brown
285*179860b2SJed Brown  def setValue(self, value):
286*179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
287*179860b2SJed Brown    self.checkKey()
288*179860b2SJed Brown    try:
289*179860b2SJed Brown      value = float(value)
290*179860b2SJed Brown    except:
291*179860b2SJed Brown      raise TypeError('Invalid floating point number: '+str(value)+' for key '+str(self.key))
292*179860b2SJed Brown    if value < self.min or value >= self.max:
293*179860b2SJed Brown      raise ValueError('Number out of range: '+str(value)+' not in ['+str(self.min)+','+str(self.max)+')'+' for key '+str(self.key))
294*179860b2SJed Brown    self.value = value
295*179860b2SJed Brown    return
296*179860b2SJed Brown
297*179860b2SJed Brownclass ArgDir(Arg):
298*179860b2SJed Brown  '''Arguments that represent directories'''
299*179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
300*179860b2SJed Brown    self.mustExist = mustExist
301*179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
302*179860b2SJed Brown    return
303*179860b2SJed Brown
304*179860b2SJed Brown  def getEntryPrompt(self):
305*179860b2SJed Brown    return 'Please enter directory for '+str(self.key)+': '
306*179860b2SJed Brown
307*179860b2SJed Brown  def getValue(self):
308*179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
309*179860b2SJed Brown    if not self.isValueSet():
310*179860b2SJed Brown      checkInteractive(self.key)
311*179860b2SJed Brown      try:
312*179860b2SJed Brown        import GUI.FileBrowser
313*179860b2SJed Brown        import SIDL.Loader
314*179860b2SJed Brown        db = GUI.FileBrowser.FileBrowser(SIDL.Loader.createClass('GUI.Default.DefaultFileBrowser'))
315*179860b2SJed Brown        if self.help: db.setTitle(self.help)
316*179860b2SJed Brown        else:         db.setTitle('Select the directory for '+self.key)
317*179860b2SJed Brown        db.setMustExist(self.exist)
318*179860b2SJed Brown        self.value = db.getDirectory()
319*179860b2SJed Brown      except Exception:
320*179860b2SJed Brown        return Arg.getValue(self)
321*179860b2SJed Brown    return self.value
322*179860b2SJed Brown
323*179860b2SJed Brown  def setValue(self, value):
324*179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
325*179860b2SJed Brown    import os
326*179860b2SJed Brown    self.checkKey()
327*179860b2SJed Brown    # Should check whether it is a well-formed path
328*179860b2SJed Brown    if not isinstance(value, str):
329*179860b2SJed Brown      raise TypeError('Invalid directory: '+str(value)+' for key '+str(self.key))
330*179860b2SJed Brown    value = os.path.expanduser(value)
331*179860b2SJed Brown    if self.mustExist and value and not os.path.isdir(value):
332*179860b2SJed Brown      raise ValueError('Nonexistent directory: '+str(value)+' for key '+str(self.key))
333*179860b2SJed Brown    self.value = value
334*179860b2SJed Brown    return
335*179860b2SJed Brown
336*179860b2SJed Brownclass ArgDirList(Arg):
337*179860b2SJed Brown  '''Arguments that represent directory lists'''
338*179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
339*179860b2SJed Brown    self.mustExist = mustExist
340*179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
341*179860b2SJed Brown    return
342*179860b2SJed Brown
343*179860b2SJed Brown  def getEntryPrompt(self):
344*179860b2SJed Brown    return 'Please enter directory list for '+str(self.key)+': '
345*179860b2SJed Brown
346*179860b2SJed Brown  def getValue(self):
347*179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
348*179860b2SJed Brown    if not self.isValueSet():
349*179860b2SJed Brown      checkInteractive(self.key)
350*179860b2SJed Brown      try:
351*179860b2SJed Brown        import GUI.FileBrowser
352*179860b2SJed Brown        import SIDL.Loader
353*179860b2SJed Brown        db = GUI.FileBrowser.FileBrowser(SIDL.Loader.createClass('GUI.Default.DefaultFileBrowser'))
354*179860b2SJed Brown        if self.help: db.setTitle(self.help)
355*179860b2SJed Brown        else:         db.setTitle('Select the directory for '+self.key)
356*179860b2SJed Brown        db.setMustExist(self.exist)
357*179860b2SJed Brown        self.value = db.getDirectory()
358*179860b2SJed Brown      except Exception:
359*179860b2SJed Brown        return Arg.getValue(self)
360*179860b2SJed Brown    return self.value
361*179860b2SJed Brown
362*179860b2SJed Brown  def setValue(self, value):
363*179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
364*179860b2SJed Brown    import os
365*179860b2SJed Brown    self.checkKey()
366*179860b2SJed Brown    if not isinstance(value, list):
367*179860b2SJed Brown      value = [value]
368*179860b2SJed Brown    # Should check whether it is a well-formed path
369*179860b2SJed Brown    nvalue = []
370*179860b2SJed Brown    for dir in value:
371*179860b2SJed Brown      nvalue.append(os.path.expanduser(dir))
372*179860b2SJed Brown    value = nvalue
373*179860b2SJed Brown    for dir in value:
374*179860b2SJed Brown      if self.mustExist and not os.path.isdir(dir):
375*179860b2SJed Brown        raise ValueError('Invalid directory: '+str(dir)+' for key '+str(self.key))
376*179860b2SJed Brown    self.value = value
377*179860b2SJed Brown    return
378*179860b2SJed Brown
379*179860b2SJed Brownclass ArgLibrary(Arg):
380*179860b2SJed Brown  '''Arguments that represent libraries'''
381*179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
382*179860b2SJed Brown    self.mustExist = mustExist
383*179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
384*179860b2SJed Brown    return
385*179860b2SJed Brown
386*179860b2SJed Brown  def getEntryPrompt(self):
387*179860b2SJed Brown    return 'Please enter library for '+str(self.key)+': '
388*179860b2SJed Brown
389*179860b2SJed Brown  def getValue(self):
390*179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
391*179860b2SJed Brown    if not self.isValueSet():
392*179860b2SJed Brown      checkInteractive(self.key)
393*179860b2SJed Brown      try:
394*179860b2SJed Brown        import GUI.FileBrowser
395*179860b2SJed Brown        import SIDL.Loader
396*179860b2SJed Brown        db = GUI.FileBrowser.FileBrowser(SIDL.Loader.createClass('GUI.Default.DefaultFileBrowser'))
397*179860b2SJed Brown        if self.help: db.setTitle(self.help)
398*179860b2SJed Brown        else:         db.setTitle('Select the library for '+self.key)
399*179860b2SJed Brown        db.setMustExist(self.exist)
400*179860b2SJed Brown        self.value = db.getFile()
401*179860b2SJed Brown      except Exception:
402*179860b2SJed Brown        return Arg.getValue(self)
403*179860b2SJed Brown    return self.value
404*179860b2SJed Brown
405*179860b2SJed Brown  def setValue(self, value):
406*179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
407*179860b2SJed Brown    import os
408*179860b2SJed Brown    self.checkKey()
409*179860b2SJed Brown    # Should check whether it is a well-formed path and an archive or shared object
410*179860b2SJed Brown    if self.mustExist:
411*179860b2SJed Brown      if not isinstance(value, list):
412*179860b2SJed Brown        value = value.split(' ')
413*179860b2SJed Brown    self.value = value
414*179860b2SJed Brown    return
415*179860b2SJed Brown
416*179860b2SJed Brownclass ArgExecutable(Arg):
417*179860b2SJed Brown  '''Arguments that represent executables'''
418*179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
419*179860b2SJed Brown    self.mustExist = mustExist
420*179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
421*179860b2SJed Brown    return
422*179860b2SJed Brown
423*179860b2SJed Brown  def getEntryPrompt(self):
424*179860b2SJed Brown    return 'Please enter executable for '+str(self.key)+': '
425*179860b2SJed Brown
426*179860b2SJed Brown  def getValue(self):
427*179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
428*179860b2SJed Brown    if not self.isValueSet():
429*179860b2SJed Brown      checkInteractive(self.key)
430*179860b2SJed Brown      try:
431*179860b2SJed Brown        import GUI.FileBrowser
432*179860b2SJed Brown        import SIDL.Loader
433*179860b2SJed Brown        db = GUI.FileBrowser.FileBrowser(SIDL.Loader.createClass('GUI.Default.DefaultFileBrowser'))
434*179860b2SJed Brown        if self.help: db.setTitle(self.help)
435*179860b2SJed Brown        else:         db.setTitle('Select the executable for '+self.key)
436*179860b2SJed Brown        db.setMustExist(self.exist)
437*179860b2SJed Brown        self.value = db.getFile()
438*179860b2SJed Brown      except Exception:
439*179860b2SJed Brown        return Arg.getValue(self)
440*179860b2SJed Brown    return self.value
441*179860b2SJed Brown
442*179860b2SJed Brown  def checkExecutable(self, dir, name):
443*179860b2SJed Brown    import os
444*179860b2SJed Brown    prog = os.path.join(dir, name)
445*179860b2SJed Brown    return os.path.isfile(prog) and os.access(prog, os.X_OK)
446*179860b2SJed Brown
447*179860b2SJed Brown  def setValue(self, value):
448*179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
449*179860b2SJed Brown    import os
450*179860b2SJed Brown    self.checkKey()
451*179860b2SJed Brown    # Should check whether it is a well-formed path
452*179860b2SJed Brown    if self.mustExist:
453*179860b2SJed Brown      index = value.find(' ')
454*179860b2SJed Brown      if index >= 0:
455*179860b2SJed Brown        options = value[index:]
456*179860b2SJed Brown        value   = value[:index]
457*179860b2SJed Brown      else:
458*179860b2SJed Brown        options = ''
459*179860b2SJed Brown      found = self.checkExecutable('', value)
460*179860b2SJed Brown      if not found:
461*179860b2SJed Brown        for dir in os.environ['PATH'].split(os.path.pathsep):
462*179860b2SJed Brown          if self.checkExecutable(dir, value):
463*179860b2SJed Brown            found = 1
464*179860b2SJed Brown            break
465*179860b2SJed Brown      if not found:
466*179860b2SJed Brown        raise ValueError('Invalid executable: '+str(value)+' for key '+str(self.key))
467*179860b2SJed Brown    self.value = value+options
468*179860b2SJed Brown    return
469*179860b2SJed Brown
470*179860b2SJed Brownclass ArgString(Arg):
471*179860b2SJed Brown  '''Arguments that represent strings satisfying a given regular expression'''
472*179860b2SJed Brown  def __init__(self, key, value = None, help = '', regExp = None, isTemporary = 0, deprecated = False):
473*179860b2SJed Brown    self.regExp = regExp
474*179860b2SJed Brown    if self.regExp:
475*179860b2SJed Brown      import re
476*179860b2SJed Brown      self.re = re.compile(self.regExp)
477*179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
478*179860b2SJed Brown    return
479*179860b2SJed Brown
480*179860b2SJed Brown  def setValue(self, value):
481*179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
482*179860b2SJed Brown    self.checkKey()
483*179860b2SJed Brown    if self.regExp and not self.re.match(value):
484*179860b2SJed Brown      raise ValueError('Invalid string '+str(value)+'. You must give a string satisfying "'+str(self.regExp)+'"'+' for key '+str(self.key))
485*179860b2SJed Brown    self.value = value
486*179860b2SJed Brown    return
487*179860b2SJed Brown
488*179860b2SJed Brownclass ArgDownload(Arg):
489*179860b2SJed Brown  '''Arguments that represent software downloads'''
490*179860b2SJed Brown  def __init__(self, key, value = None, help = '', isTemporary = 0, deprecated = False):
491*179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
492*179860b2SJed Brown    return
493*179860b2SJed Brown
494*179860b2SJed Brown  def valueName(self, value):
495*179860b2SJed Brown    if value == 0:
496*179860b2SJed Brown      return 'no'
497*179860b2SJed Brown    elif value == 1:
498*179860b2SJed Brown      return 'yes'
499*179860b2SJed Brown    return str(value)
500*179860b2SJed Brown
501*179860b2SJed Brown  def __str__(self):
502*179860b2SJed Brown    if not self.isValueSet():
503*179860b2SJed Brown      return 'Empty '+str(self.__class__)
504*179860b2SJed Brown    elif isinstance(self.value, list):
505*179860b2SJed Brown      return str(map(self.valueName, self.value))
506*179860b2SJed Brown    return self.valueName(self.value)
507*179860b2SJed Brown
508*179860b2SJed Brown  def getEntryPrompt(self):
509*179860b2SJed Brown    return 'Please enter download value for '+str(self.key)+': '
510*179860b2SJed Brown
511*179860b2SJed Brown  def setValue(self, value):
512*179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
513*179860b2SJed Brown    import os
514*179860b2SJed Brown    self.checkKey()
515*179860b2SJed Brown    try:
516*179860b2SJed Brown      if   value == '0':        value = 0
517*179860b2SJed Brown      elif value == '1':        value = 1
518*179860b2SJed Brown      elif value == 'no':       value = 0
519*179860b2SJed Brown      elif value == 'yes':      value = 1
520*179860b2SJed Brown      elif value == 'false':    value = 0
521*179860b2SJed Brown      elif value == 'true':     value = 1
522*179860b2SJed Brown      elif not isinstance(value, int):
523*179860b2SJed Brown        value = str(value)
524*179860b2SJed Brown    except:
525*179860b2SJed Brown      raise TypeError('Invalid download value: '+str(value)+' for key '+str(self.key))
526*179860b2SJed Brown    if isinstance(value, str):
527*179860b2SJed Brown      import urlparse
528*179860b2SJed Brown      if not urlparse.urlparse(value)[0]: # how do we check if the URL is invalid?
529*179860b2SJed Brown        if os.path.isfile(value):
530*179860b2SJed Brown          value = 'file://'+os.path.abspath(value)
531*179860b2SJed Brown        else:
532*179860b2SJed Brown          raise ValueError('Invalid download location: '+str(value)+' for key '+str(self.key))
533*179860b2SJed Brown    self.value = value
534*179860b2SJed Brown    return
535