xref: /petsc/config/BuildSystem/nargs.py (revision c88f93c3b5212fd7ace2a6a4ad766edcf46c6841)
15b6bfdb9SJed Brownfrom __future__ import print_function
2179860b2SJed Browntry:
3179860b2SJed Brown  import readline
4179860b2SJed Brownexcept ImportError: pass
5179860b2SJed Brown
6179860b2SJed Browndef getInteractive():
7179860b2SJed Brown  return isInteractive
8179860b2SJed Brown
9179860b2SJed Browndef setInteractive(interactive):
10179860b2SJed Brown  global isInteractive
11179860b2SJed Brown  isInteractive = interactive
12179860b2SJed Brown  return
13179860b2SJed Brown
14179860b2SJed Browndef checkInteractive(key):
15179860b2SJed Brown  if not isInteractive:
16179860b2SJed Brown    raise ValueError('Value not set for key '+str(key))
17179860b2SJed Brown  return
18179860b2SJed BrownsetInteractive(1)
19179860b2SJed Brown
20179860b2SJed Brownclass Arg(object):
21179860b2SJed Brown  '''This is the base class for all objects contained in RDict. Access to the raw argument values is
22179860b2SJed Brownprovided by getValue() and setValue(). These objects can be thought of as type objects for the
23179860b2SJed Brownvalues themselves. It is possible to set an Arg in the RDict which has not yet been assigned a value
24179860b2SJed Brownin order to declare the type of that option.
25179860b2SJed Brown
26179860b2SJed BrownInputs which cannot be converted to the correct type will cause TypeError, those failing validation
27179860b2SJed Browntests will cause ValueError.
28179860b2SJed Brown'''
29179860b2SJed Brown  def __init__(self, key, value = None, help = '', isTemporary = False, deprecated = False):
30179860b2SJed Brown    self.key         = key
31179860b2SJed Brown    self.help        = help
32179860b2SJed Brown    self.isTemporary = isTemporary
33179860b2SJed Brown    self.deprecated  = False
34179860b2SJed Brown    if not value is None:
35179860b2SJed Brown      self.setValue(value)
36179860b2SJed Brown    self.deprecated  = deprecated
37179860b2SJed Brown    return
38179860b2SJed Brown
39179860b2SJed Brown  def isValueSet(self):
40179860b2SJed Brown    '''Determines whether the value of this argument has been set'''
41179860b2SJed Brown    return hasattr(self, 'value')
42179860b2SJed Brown
43179860b2SJed Brown  def getTemporary(self):
44179860b2SJed Brown    '''Retrieve the flag indicating whether the item should be persistent'''
45179860b2SJed Brown    return self.isTemporary
46179860b2SJed Brown
47179860b2SJed Brown  def setTemporary(self, isTemporary):
48179860b2SJed Brown    '''Set the flag indicating whether the item should be persistent'''
49179860b2SJed Brown    self.isTemporary = isTemporary
50179860b2SJed Brown    return
51179860b2SJed Brown
52179860b2SJed Brown  def parseValue(arg):
53179860b2SJed Brown    '''Return the object represented by the value portion of a string argument'''
54179860b2SJed Brown    # Should I replace this with a lexer?
55179860b2SJed Brown    if arg: arg = arg.strip()
56179860b2SJed Brown    if arg and arg[0] == '[' and arg[-1] == ']':
57179860b2SJed Brown      if len(arg) > 2: value = arg[1:-1].split(',')
58179860b2SJed Brown      else:            value = []
59179860b2SJed Brown    elif arg and arg[0] == '{' and arg[-1] == '}':
60179860b2SJed Brown      value = {}
61179860b2SJed Brown      idx = 1
62179860b2SJed Brown      oldIdx = idx
63179860b2SJed Brown      while idx < len(arg)-1:
64179860b2SJed Brown        if arg[oldIdx] == ',':
65179860b2SJed Brown          oldIdx += 1
66179860b2SJed Brown        while not arg[idx] == ':': idx += 1
67179860b2SJed Brown        key = arg[oldIdx:idx]
68179860b2SJed Brown        idx += 1
69179860b2SJed Brown        oldIdx = idx
70179860b2SJed Brown        nesting = 0
71179860b2SJed Brown        while not (arg[idx] == ',' or arg[idx] == '}') or nesting:
72179860b2SJed Brown          if arg[idx] == '[':
73179860b2SJed Brown            nesting += 1
74179860b2SJed Brown          elif arg[idx] == ']':
75179860b2SJed Brown            nesting -= 1
76179860b2SJed Brown          idx += 1
77179860b2SJed Brown        value[key] = Arg.parseValue(arg[oldIdx:idx])
78179860b2SJed Brown        oldIdx = idx
79179860b2SJed Brown    else:
80179860b2SJed Brown      value = arg
81179860b2SJed Brown    return value
82179860b2SJed Brown  parseValue = staticmethod(parseValue)
83179860b2SJed Brown
84179860b2SJed Brown  def parseArgument(arg, ignoreDouble = 0):
85179860b2SJed Brown    '''Split an argument into a (key, value) tuple, stripping off the leading dashes. Return (None, None) on failure.'''
86179860b2SJed Brown    start = 0
87179860b2SJed Brown    if arg and arg[0] == '-':
88179860b2SJed Brown      start = 1
89179860b2SJed Brown      if arg[1] == '-' and not ignoreDouble:
90179860b2SJed Brown        start = 2
91179860b2SJed Brown    if arg.find('=') >= 0:
92179860b2SJed Brown      (key, value) = arg[start:].split('=', 1)
93179860b2SJed Brown    else:
94179860b2SJed Brown      if start == 0:
95179860b2SJed Brown        (key, value) = (None, arg)
96179860b2SJed Brown      else:
97179860b2SJed Brown        (key, value) = (arg[start:], '1')
98179860b2SJed Brown    return (key, Arg.parseValue(value))
99179860b2SJed Brown
100179860b2SJed Brown  parseArgument = staticmethod(parseArgument)
101179860b2SJed Brown
102179860b2SJed Brown  def findArgument(key, argList):
103179860b2SJed Brown    '''Locate an argument with the given key in argList, returning the value or None on failure
104179860b2SJed Brown       - This is generally used to process arguments which must take effect before canonical argument parsing'''
105179860b2SJed Brown    if not isinstance(argList, list): return None
106179860b2SJed Brown    # Reverse the list so that we preserve the semantics which state that the last
107179860b2SJed Brown    #   argument with a given key takes effect
108179860b2SJed Brown    l = argList[:]
109179860b2SJed Brown    l.reverse()
110179860b2SJed Brown    for arg in l:
111179860b2SJed Brown      (k, value) = Arg.parseArgument(arg)
112179860b2SJed Brown      if k == key:
113179860b2SJed Brown        return value
114179860b2SJed Brown    return None
115179860b2SJed Brown  findArgument = staticmethod(findArgument)
116179860b2SJed Brown
117179860b2SJed Brown  def processAlternatePrefixes(argList):
118179860b2SJed Brown    '''Convert alternate prefixes to our normal form'''
119179860b2SJed Brown    for l in range(0, len(argList)):
120179860b2SJed Brown      name = argList[l]
121179860b2SJed Brown      if name.find('enable-') >= 0:
122179860b2SJed Brown        argList[l] = name.replace('enable-','with-')
123179860b2SJed Brown        if name.find('=') == -1: argList[l] = argList[l]+'=1'
124179860b2SJed Brown      if name.find('disable-') >= 0:
125179860b2SJed Brown        argList[l] = name.replace('disable-','with-')
126179860b2SJed Brown        if name.find('=') == -1: argList[l] = argList[l]+'=0'
127179860b2SJed Brown        elif name.endswith('=1'): argList[l].replace('=1','=0')
128179860b2SJed Brown      if name.find('without-') >= 0:
129179860b2SJed Brown        argList[l] = name.replace('without-','with-')
130179860b2SJed Brown        if name.find('=') == -1: argList[l] = argList[l]+'=0'
131179860b2SJed Brown        elif name.endswith('=1'): argList[l].replace('=1','=0')
132179860b2SJed Brown    return
133179860b2SJed Brown  processAlternatePrefixes = staticmethod(processAlternatePrefixes)
134179860b2SJed Brown
135179860b2SJed Brown  def __str__(self):
136179860b2SJed Brown    if not self.isValueSet():
137179860b2SJed Brown      return 'Empty '+str(self.__class__)
138179860b2SJed Brown    elif isinstance(self.value, list):
139179860b2SJed Brown      return str(map(str, self.value))
140179860b2SJed Brown    return str(self.value)
141179860b2SJed Brown
142179860b2SJed Brown  def getEntryPrompt(self):
143179860b2SJed Brown    return 'Please enter value for '+str(self.key)+': '
144179860b2SJed Brown
145179860b2SJed Brown  def getKey(self):
146179860b2SJed Brown    '''Returns the key. SHOULD MAKE THIS A PROPERTY'''
147179860b2SJed Brown    return self.key
148179860b2SJed Brown
149179860b2SJed Brown  def setKey(self, key):
150179860b2SJed Brown    '''Set the key. SHOULD MAKE THIS A PROPERTY'''
151179860b2SJed Brown    self.key = key
152179860b2SJed Brown    return
153179860b2SJed Brown
154179860b2SJed Brown  def getValue(self):
155179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
156179860b2SJed Brown    if not self.isValueSet():
157179860b2SJed Brown      checkInteractive(self.key)
1585b6bfdb9SJed Brown      if self.help: print(self.help)
159179860b2SJed Brown      while 1:
160179860b2SJed Brown        try:
161179860b2SJed Brown          self.setValue(Arg.parseValue(raw_input(self.getEntryPrompt())))
162179860b2SJed Brown          break
163179860b2SJed Brown        except KeyboardInterrupt:
164179860b2SJed Brown          raise KeyError('Could not find value for key '+str(self.key))
1655b6bfdb9SJed Brown        except TypeError as e:
1665b6bfdb9SJed Brown          print(str(e))
167179860b2SJed Brown    return self.value
168179860b2SJed Brown
169179860b2SJed Brown  def checkKey(self):
170179860b2SJed Brown    if self.deprecated:
171179860b2SJed Brown      if isinstance(self.deprecated, str):
172179860b2SJed Brown        raise KeyError('Deprecated option '+self.key+' should be '+self.deprecated)
173179860b2SJed Brown      raise KeyError('Deprecated option '+self.key)
174179860b2SJed Brown    return
175179860b2SJed Brown
176179860b2SJed Brown  def setValue(self, value):
177179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
178179860b2SJed Brown    self.checkKey()
179179860b2SJed Brown    self.value = value
180179860b2SJed Brown    return
181179860b2SJed Brown
182179860b2SJed Brownclass ArgBool(Arg):
183179860b2SJed Brown  '''Arguments that represent boolean values'''
184179860b2SJed Brown  def __init__(self, key, value = None, help = '', isTemporary = 0, deprecated = False):
185179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
186179860b2SJed Brown    return
187179860b2SJed Brown
188179860b2SJed Brown  def getEntryPrompt(self):
189179860b2SJed Brown    return 'Please enter boolean value for '+str(self.key)+': '
190179860b2SJed Brown
191179860b2SJed Brown  def setValue(self, value):
192179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
193179860b2SJed Brown    self.checkKey()
194179860b2SJed Brown    try:
195179860b2SJed Brown      if   value == 'no':    value = 0
196179860b2SJed Brown      elif value == 'yes':   value = 1
197179860b2SJed Brown      elif value == 'true':  value = 1
198179860b2SJed Brown      elif value == 'false': value = 0
199179860b2SJed Brown      elif value == 'True':  value = 1
200179860b2SJed Brown      elif value == 'False': value = 0
201179860b2SJed Brown      else:                  value = int(value)
202179860b2SJed Brown    except:
203179860b2SJed Brown      raise TypeError('Invalid boolean value: '+str(value)+' for key '+str(self.key))
204179860b2SJed Brown    self.value = value
205179860b2SJed Brown    return
206179860b2SJed Brown
207179860b2SJed Brownclass ArgFuzzyBool(Arg):
208179860b2SJed Brown  '''Arguments that represent boolean values of an extended set'''
209179860b2SJed Brown  def __init__(self, key, value = None, help = '', isTemporary = 0, deprecated = False):
210179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
211179860b2SJed Brown    return
212179860b2SJed Brown
213179860b2SJed Brown  def valueName(self, value):
214179860b2SJed Brown    if value == 0:
215179860b2SJed Brown      return 'no'
216179860b2SJed Brown    elif value == 1:
217179860b2SJed Brown      return 'yes'
218179860b2SJed Brown    elif value == 2:
219179860b2SJed Brown      return 'ifneeded'
220179860b2SJed Brown    return str(value)
221179860b2SJed Brown
222179860b2SJed Brown  def __str__(self):
223179860b2SJed Brown    if not self.isValueSet():
224179860b2SJed Brown      return 'Empty '+str(self.__class__)
225179860b2SJed Brown    elif isinstance(self.value, list):
226179860b2SJed Brown      return str(map(self.valueName, self.value))
227179860b2SJed Brown    return self.valueName(self.value)
228179860b2SJed Brown
229179860b2SJed Brown  def getEntryPrompt(self):
230179860b2SJed Brown    return 'Please enter fuzzy boolean value for '+str(self.key)+': '
231179860b2SJed Brown
232179860b2SJed Brown  def setValue(self, value):
233179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
234179860b2SJed Brown    self.checkKey()
235179860b2SJed Brown    try:
236179860b2SJed Brown      if   value == '0':        value = 0
237179860b2SJed Brown      elif value == '1':        value = 1
238179860b2SJed Brown      elif value == 'no':       value = 0
239179860b2SJed Brown      elif value == 'yes':      value = 1
240179860b2SJed Brown      elif value == 'false':    value = 0
241179860b2SJed Brown      elif value == 'true':     value = 1
242179860b2SJed Brown      elif value == 'maybe':    value = 2
243179860b2SJed Brown      elif value == 'ifneeded': value = 2
244179860b2SJed Brown      elif value == 'client':   value = 2
245179860b2SJed Brown      elif value == 'server':   value = 3
246179860b2SJed Brown      else:                     value = int(value)
247179860b2SJed Brown    except:
248179860b2SJed Brown      raise TypeError('Invalid fuzzy boolean value: '+str(value)+' for key '+str(self.key))
249179860b2SJed Brown    self.value = value
250179860b2SJed Brown    return
251179860b2SJed Brown
252179860b2SJed Brownclass ArgInt(Arg):
253179860b2SJed Brown  '''Arguments that represent integer numbers'''
2545b6bfdb9SJed Brown  def __init__(self, key, value = None, help = '', min = -2147483647, max = 2147483648, isTemporary = 0, deprecated = False):
255179860b2SJed Brown    self.min = min
256179860b2SJed Brown    self.max = max
257179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
258179860b2SJed Brown    return
259179860b2SJed Brown
260179860b2SJed Brown  def getEntryPrompt(self):
261179860b2SJed Brown    return 'Please enter integer value for '+str(self.key)+': '
262179860b2SJed Brown
263179860b2SJed Brown  def setValue(self, value):
264179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
265179860b2SJed Brown    self.checkKey()
266179860b2SJed Brown    try:
267179860b2SJed Brown      value = int(value)
268179860b2SJed Brown    except:
269179860b2SJed Brown      raise TypeError('Invalid integer number: '+str(value)+' for key '+str(self.key))
270179860b2SJed Brown    if value < self.min or value >= self.max:
271179860b2SJed Brown      raise ValueError('Number out of range: '+str(value)+' not in ['+str(self.min)+','+str(self.max)+')'+' for key '+str(self.key))
272179860b2SJed Brown    self.value = value
273179860b2SJed Brown    return
274179860b2SJed Brown
275179860b2SJed Brownclass ArgReal(Arg):
276179860b2SJed Brown  '''Arguments that represent floating point numbers'''
277179860b2SJed Brown  def __init__(self, key, value = None, help = '', min = -1.7976931348623157e308, max = 1.7976931348623157e308, isTemporary = 0, deprecated = False):
278179860b2SJed Brown    self.min = min
279179860b2SJed Brown    self.max = max
280179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
281179860b2SJed Brown    return
282179860b2SJed Brown
283179860b2SJed Brown  def getEntryPrompt(self):
284179860b2SJed Brown    return 'Please enter floating point value for '+str(self.key)+': '
285179860b2SJed Brown
286179860b2SJed Brown  def setValue(self, value):
287179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
288179860b2SJed Brown    self.checkKey()
289179860b2SJed Brown    try:
290179860b2SJed Brown      value = float(value)
291179860b2SJed Brown    except:
292179860b2SJed Brown      raise TypeError('Invalid floating point number: '+str(value)+' for key '+str(self.key))
293179860b2SJed Brown    if value < self.min or value >= self.max:
294179860b2SJed Brown      raise ValueError('Number out of range: '+str(value)+' not in ['+str(self.min)+','+str(self.max)+')'+' for key '+str(self.key))
295179860b2SJed Brown    self.value = value
296179860b2SJed Brown    return
297179860b2SJed Brown
298179860b2SJed Brownclass ArgDir(Arg):
299179860b2SJed Brown  '''Arguments that represent directories'''
300179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
301179860b2SJed Brown    self.mustExist = mustExist
302179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
303179860b2SJed Brown    return
304179860b2SJed Brown
305179860b2SJed Brown  def getEntryPrompt(self):
306179860b2SJed Brown    return 'Please enter directory for '+str(self.key)+': '
307179860b2SJed Brown
308179860b2SJed Brown  def getValue(self):
309179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
310179860b2SJed Brown    if not self.isValueSet():
311179860b2SJed Brown      checkInteractive(self.key)
312179860b2SJed Brown      return Arg.getValue(self)
313179860b2SJed Brown    return self.value
314179860b2SJed Brown
315179860b2SJed Brown  def setValue(self, value):
316179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
317179860b2SJed Brown    import os
318179860b2SJed Brown    self.checkKey()
319179860b2SJed Brown    # Should check whether it is a well-formed path
320179860b2SJed Brown    if not isinstance(value, str):
321179860b2SJed Brown      raise TypeError('Invalid directory: '+str(value)+' for key '+str(self.key))
322179860b2SJed Brown    value = os.path.expanduser(value)
3239992b254SSatish Balay    value = os.path.abspath(value)
324179860b2SJed Brown    if self.mustExist and value and not os.path.isdir(value):
325179860b2SJed Brown      raise ValueError('Nonexistent directory: '+str(value)+' for key '+str(self.key))
326179860b2SJed Brown    self.value = value
327179860b2SJed Brown    return
328179860b2SJed Brown
329179860b2SJed Brownclass ArgDirList(Arg):
330179860b2SJed Brown  '''Arguments that represent directory lists'''
331179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
332179860b2SJed Brown    self.mustExist = mustExist
333179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
334179860b2SJed Brown    return
335179860b2SJed Brown
336179860b2SJed Brown  def getEntryPrompt(self):
337179860b2SJed Brown    return 'Please enter directory list for '+str(self.key)+': '
338179860b2SJed Brown
339179860b2SJed Brown  def getValue(self):
340179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
341179860b2SJed Brown    if not self.isValueSet():
342179860b2SJed Brown      checkInteractive(self.key)
343179860b2SJed Brown      return Arg.getValue(self)
344179860b2SJed Brown    return self.value
345179860b2SJed Brown
346179860b2SJed Brown  def setValue(self, value):
347179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
348179860b2SJed Brown    import os
349179860b2SJed Brown    self.checkKey()
350179860b2SJed Brown    if not isinstance(value, list):
351158e955bSSatish Balay      value = value.split(':')
352179860b2SJed Brown    # Should check whether it is a well-formed path
353179860b2SJed Brown    nvalue = []
354179860b2SJed Brown    for dir in value:
355928c5b42SSatish Balay      if dir:
356179860b2SJed Brown        nvalue.append(os.path.expanduser(dir))
357179860b2SJed Brown    value = nvalue
358179860b2SJed Brown    for dir in value:
359179860b2SJed Brown      if self.mustExist and not os.path.isdir(dir):
360179860b2SJed Brown        raise ValueError('Invalid directory: '+str(dir)+' for key '+str(self.key))
361179860b2SJed Brown    self.value = value
362179860b2SJed Brown    return
363179860b2SJed Brown
364*c88f93c3SSatish Balayclass ArgFile(Arg):
365*c88f93c3SSatish Balay  '''Arguments that represent a file'''
366*c88f93c3SSatish Balay  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
367*c88f93c3SSatish Balay    self.mustExist = mustExist
368*c88f93c3SSatish Balay    Arg.__init__(self, key, value, help, isTemporary, deprecated)
369*c88f93c3SSatish Balay    return
370*c88f93c3SSatish Balay
371*c88f93c3SSatish Balay  def getEntryPrompt(self):
372*c88f93c3SSatish Balay    return 'Please enter file path for '+str(self.key)+': '
373*c88f93c3SSatish Balay
374*c88f93c3SSatish Balay  def getValue(self):
375*c88f93c3SSatish Balay    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
376*c88f93c3SSatish Balay    if not self.isValueSet():
377*c88f93c3SSatish Balay      checkInteractive(self.key)
378*c88f93c3SSatish Balay      return Arg.getValue(self)
379*c88f93c3SSatish Balay    return self.value
380*c88f93c3SSatish Balay
381*c88f93c3SSatish Balay  def setValue(self, value):
382*c88f93c3SSatish Balay    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
383*c88f93c3SSatish Balay    import os
384*c88f93c3SSatish Balay    self.checkKey()
385*c88f93c3SSatish Balay    # Should check whether it is a well-formed path
386*c88f93c3SSatish Balay    if not isinstance(value, str):
387*c88f93c3SSatish Balay      raise TypeError('Invalid file: '+str(value)+' for key '+str(self.key))
388*c88f93c3SSatish Balay    value = os.path.expanduser(value)
389*c88f93c3SSatish Balay    value = os.path.abspath(value)
390*c88f93c3SSatish Balay    if self.mustExist and value and not os.path.isfile(value):
391*c88f93c3SSatish Balay      raise ValueError('Nonexistent file: '+str(value)+' for key '+str(self.key))
392*c88f93c3SSatish Balay    self.value = value
393*c88f93c3SSatish Balay    return
394*c88f93c3SSatish Balay
395*c88f93c3SSatish Balayclass ArgFileList(Arg):
396*c88f93c3SSatish Balay  '''Arguments that represent file lists'''
397*c88f93c3SSatish Balay  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
398*c88f93c3SSatish Balay    self.mustExist = mustExist
399*c88f93c3SSatish Balay    Arg.__init__(self, key, value, help, isTemporary, deprecated)
400*c88f93c3SSatish Balay    return
401*c88f93c3SSatish Balay
402*c88f93c3SSatish Balay  def getEntryPrompt(self):
403*c88f93c3SSatish Balay    return 'Please enter file list for '+str(self.key)+': '
404*c88f93c3SSatish Balay
405*c88f93c3SSatish Balay  def getValue(self):
406*c88f93c3SSatish Balay    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
407*c88f93c3SSatish Balay    if not self.isValueSet():
408*c88f93c3SSatish Balay      checkInteractive(self.key)
409*c88f93c3SSatish Balay      return Arg.getValue(self)
410*c88f93c3SSatish Balay    return self.value
411*c88f93c3SSatish Balay
412*c88f93c3SSatish Balay  def setValue(self, value):
413*c88f93c3SSatish Balay    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
414*c88f93c3SSatish Balay    import os
415*c88f93c3SSatish Balay    self.checkKey()
416*c88f93c3SSatish Balay    if not isinstance(value, list):
417*c88f93c3SSatish Balay      value = value.split(':')
418*c88f93c3SSatish Balay    # Should check whether it is a well-formed path
419*c88f93c3SSatish Balay    nvalue = []
420*c88f93c3SSatish Balay    for file in value:
421*c88f93c3SSatish Balay      if file:
422*c88f93c3SSatish Balay        nvalue.append(os.path.expanduser(file))
423*c88f93c3SSatish Balay    value = nvalue
424*c88f93c3SSatish Balay    for file in value:
425*c88f93c3SSatish Balay      if self.mustExist and not os.path.isfile(file):
426*c88f93c3SSatish Balay        raise ValueError('Invalid file: '+str(file)+' for key '+str(self.key))
427*c88f93c3SSatish Balay    self.value = value
428*c88f93c3SSatish Balay    return
429*c88f93c3SSatish Balay
430179860b2SJed Brownclass ArgLibrary(Arg):
431179860b2SJed Brown  '''Arguments that represent libraries'''
432179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
433179860b2SJed Brown    self.mustExist = mustExist
434179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
435179860b2SJed Brown    return
436179860b2SJed Brown
437179860b2SJed Brown  def getEntryPrompt(self):
438179860b2SJed Brown    return 'Please enter library for '+str(self.key)+': '
439179860b2SJed Brown
440179860b2SJed Brown  def getValue(self):
441179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
442179860b2SJed Brown    if not self.isValueSet():
443179860b2SJed Brown      checkInteractive(self.key)
444179860b2SJed Brown      return Arg.getValue(self)
445179860b2SJed Brown    return self.value
446179860b2SJed Brown
447179860b2SJed Brown  def setValue(self, value):
448179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
449179860b2SJed Brown    import os
450179860b2SJed Brown    self.checkKey()
451179860b2SJed Brown    # Should check whether it is a well-formed path and an archive or shared object
452179860b2SJed Brown    if self.mustExist:
453179860b2SJed Brown      if not isinstance(value, list):
454179860b2SJed Brown        value = value.split(' ')
455179860b2SJed Brown    self.value = value
456179860b2SJed Brown    return
457179860b2SJed Brown
458179860b2SJed Brownclass ArgExecutable(Arg):
459179860b2SJed Brown  '''Arguments that represent executables'''
460179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
461179860b2SJed Brown    self.mustExist = mustExist
462179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
463179860b2SJed Brown    return
464179860b2SJed Brown
465179860b2SJed Brown  def getEntryPrompt(self):
466179860b2SJed Brown    return 'Please enter executable for '+str(self.key)+': '
467179860b2SJed Brown
468179860b2SJed Brown  def getValue(self):
469179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
470179860b2SJed Brown    if not self.isValueSet():
471179860b2SJed Brown      checkInteractive(self.key)
472179860b2SJed Brown      return Arg.getValue(self)
473179860b2SJed Brown    return self.value
474179860b2SJed Brown
475179860b2SJed Brown  def checkExecutable(self, dir, name):
476179860b2SJed Brown    import os
477179860b2SJed Brown    prog = os.path.join(dir, name)
478179860b2SJed Brown    return os.path.isfile(prog) and os.access(prog, os.X_OK)
479179860b2SJed Brown
480179860b2SJed Brown  def setValue(self, value):
481179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
482179860b2SJed Brown    import os
483179860b2SJed Brown    self.checkKey()
484179860b2SJed Brown    # Should check whether it is a well-formed path
485179860b2SJed Brown    if self.mustExist:
486179860b2SJed Brown      index = value.find(' ')
487179860b2SJed Brown      if index >= 0:
488179860b2SJed Brown        options = value[index:]
489179860b2SJed Brown        value   = value[:index]
490179860b2SJed Brown      else:
491179860b2SJed Brown        options = ''
492179860b2SJed Brown      found = self.checkExecutable('', value)
493179860b2SJed Brown      if not found:
494179860b2SJed Brown        for dir in os.environ['PATH'].split(os.path.pathsep):
495179860b2SJed Brown          if self.checkExecutable(dir, value):
496179860b2SJed Brown            found = 1
497179860b2SJed Brown            break
498179860b2SJed Brown      if not found:
499179860b2SJed Brown        raise ValueError('Invalid executable: '+str(value)+' for key '+str(self.key))
500179860b2SJed Brown    self.value = value+options
501179860b2SJed Brown    return
502179860b2SJed Brown
503179860b2SJed Brownclass ArgString(Arg):
504179860b2SJed Brown  '''Arguments that represent strings satisfying a given regular expression'''
505179860b2SJed Brown  def __init__(self, key, value = None, help = '', regExp = None, isTemporary = 0, deprecated = False):
506179860b2SJed Brown    self.regExp = regExp
507179860b2SJed Brown    if self.regExp:
508179860b2SJed Brown      import re
509179860b2SJed Brown      self.re = re.compile(self.regExp)
510179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
511179860b2SJed Brown    return
512179860b2SJed Brown
513179860b2SJed Brown  def setValue(self, value):
514179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
515179860b2SJed Brown    self.checkKey()
516179860b2SJed Brown    if self.regExp and not self.re.match(value):
517179860b2SJed Brown      raise ValueError('Invalid string '+str(value)+'. You must give a string satisfying "'+str(self.regExp)+'"'+' for key '+str(self.key))
518179860b2SJed Brown    self.value = value
519179860b2SJed Brown    return
520179860b2SJed Brown
521179860b2SJed Brownclass ArgDownload(Arg):
522179860b2SJed Brown  '''Arguments that represent software downloads'''
523179860b2SJed Brown  def __init__(self, key, value = None, help = '', isTemporary = 0, deprecated = False):
524179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
525179860b2SJed Brown    return
526179860b2SJed Brown
527179860b2SJed Brown  def valueName(self, value):
528179860b2SJed Brown    if value == 0:
529179860b2SJed Brown      return 'no'
530179860b2SJed Brown    elif value == 1:
531179860b2SJed Brown      return 'yes'
532179860b2SJed Brown    return str(value)
533179860b2SJed Brown
534179860b2SJed Brown  def __str__(self):
535179860b2SJed Brown    if not self.isValueSet():
536179860b2SJed Brown      return 'Empty '+str(self.__class__)
537179860b2SJed Brown    elif isinstance(self.value, list):
538179860b2SJed Brown      return str(map(self.valueName, self.value))
539179860b2SJed Brown    return self.valueName(self.value)
540179860b2SJed Brown
541179860b2SJed Brown  def getEntryPrompt(self):
542179860b2SJed Brown    return 'Please enter download value for '+str(self.key)+': '
543179860b2SJed Brown
544179860b2SJed Brown  def setValue(self, value):
545179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
546179860b2SJed Brown    import os
547179860b2SJed Brown    self.checkKey()
548179860b2SJed Brown    try:
549179860b2SJed Brown      if   value == '0':        value = 0
550179860b2SJed Brown      elif value == '1':        value = 1
551179860b2SJed Brown      elif value == 'no':       value = 0
552179860b2SJed Brown      elif value == 'yes':      value = 1
553179860b2SJed Brown      elif value == 'false':    value = 0
554179860b2SJed Brown      elif value == 'true':     value = 1
555179860b2SJed Brown      elif not isinstance(value, int):
556179860b2SJed Brown        value = str(value)
557179860b2SJed Brown    except:
558179860b2SJed Brown      raise TypeError('Invalid download value: '+str(value)+' for key '+str(self.key))
559179860b2SJed Brown    if isinstance(value, str):
560e7c47bf1SJed Brown      try:
561179860b2SJed Brown        import urlparse
5629ad79eecSSatish Balay      except ImportError:
563e7c47bf1SJed Brown        from urllib import parse as urlparse
564179860b2SJed Brown      if not urlparse.urlparse(value)[0]: # how do we check if the URL is invalid?
565179860b2SJed Brown        if os.path.isfile(value):
566179860b2SJed Brown          value = 'file://'+os.path.abspath(value)
56752df3566SBarry Smith        elif os.path.isdir(value):
56846a3cf90SSatish Balay          if os.path.isdir(os.path.join(value,'.git')):
56946a3cf90SSatish Balay            value = 'git://'+os.path.abspath(value)
57046a3cf90SSatish Balay          else:
57152df3566SBarry Smith            value = 'dir://'+os.path.abspath(value)
572179860b2SJed Brown        else:
573179860b2SJed Brown          raise ValueError('Invalid download location: '+str(value)+' for key '+str(self.key))
574179860b2SJed Brown    self.value = value
575179860b2SJed Brown    return
576