xref: /petsc/config/BuildSystem/nargs.py (revision 9baa572492f2d5c9a9469100eb79348cae8ec756)
15b6bfdb9SJed Brownfrom __future__ import print_function
2179860b2SJed Browntry:
3179860b2SJed Brown  import readline
4179860b2SJed Brownexcept ImportError: pass
5179860b2SJed Brown
6179860b2SJed Brownclass Arg(object):
7179860b2SJed Brown  '''This is the base class for all objects contained in RDict. Access to the raw argument values is
8179860b2SJed Brownprovided by getValue() and setValue(). These objects can be thought of as type objects for the
9179860b2SJed Brownvalues themselves. It is possible to set an Arg in the RDict which has not yet been assigned a value
10179860b2SJed Brownin order to declare the type of that option.
11179860b2SJed Brown
12179860b2SJed BrownInputs which cannot be converted to the correct type will cause TypeError, those failing validation
13179860b2SJed Browntests will cause ValueError.
14179860b2SJed Brown'''
15179860b2SJed Brown  def __init__(self, key, value = None, help = '', isTemporary = False, deprecated = False):
16179860b2SJed Brown    self.key         = key
17179860b2SJed Brown    self.help        = help
18179860b2SJed Brown    self.isTemporary = isTemporary
19179860b2SJed Brown    self.deprecated  = False
20179860b2SJed Brown    if not value is None:
21179860b2SJed Brown      self.setValue(value)
22179860b2SJed Brown    self.deprecated  = deprecated
23179860b2SJed Brown    return
24179860b2SJed Brown
25179860b2SJed Brown  def isValueSet(self):
26179860b2SJed Brown    '''Determines whether the value of this argument has been set'''
27179860b2SJed Brown    return hasattr(self, 'value')
28179860b2SJed Brown
29179860b2SJed Brown  def getTemporary(self):
30179860b2SJed Brown    '''Retrieve the flag indicating whether the item should be persistent'''
31179860b2SJed Brown    return self.isTemporary
32179860b2SJed Brown
33179860b2SJed Brown  def setTemporary(self, isTemporary):
34179860b2SJed Brown    '''Set the flag indicating whether the item should be persistent'''
35179860b2SJed Brown    self.isTemporary = isTemporary
36179860b2SJed Brown    return
37179860b2SJed Brown
38179860b2SJed Brown  def parseValue(arg):
39179860b2SJed Brown    '''Return the object represented by the value portion of a string argument'''
40179860b2SJed Brown    # Should I replace this with a lexer?
41179860b2SJed Brown    if arg: arg = arg.strip()
42179860b2SJed Brown    if arg and arg[0] == '[' and arg[-1] == ']':
43179860b2SJed Brown      if len(arg) > 2: value = arg[1:-1].split(',')
44179860b2SJed Brown      else:            value = []
45179860b2SJed Brown    elif arg and arg[0] == '{' and arg[-1] == '}':
46179860b2SJed Brown      value = {}
47179860b2SJed Brown      idx = 1
48179860b2SJed Brown      oldIdx = idx
49179860b2SJed Brown      while idx < len(arg)-1:
50179860b2SJed Brown        if arg[oldIdx] == ',':
51179860b2SJed Brown          oldIdx += 1
52179860b2SJed Brown        while not arg[idx] == ':': idx += 1
53179860b2SJed Brown        key = arg[oldIdx:idx]
54179860b2SJed Brown        idx += 1
55179860b2SJed Brown        oldIdx = idx
56179860b2SJed Brown        nesting = 0
57179860b2SJed Brown        while not (arg[idx] == ',' or arg[idx] == '}') or nesting:
58179860b2SJed Brown          if arg[idx] == '[':
59179860b2SJed Brown            nesting += 1
60179860b2SJed Brown          elif arg[idx] == ']':
61179860b2SJed Brown            nesting -= 1
62179860b2SJed Brown          idx += 1
63179860b2SJed Brown        value[key] = Arg.parseValue(arg[oldIdx:idx])
64179860b2SJed Brown        oldIdx = idx
65179860b2SJed Brown    else:
66179860b2SJed Brown      value = arg
67179860b2SJed Brown    return value
68179860b2SJed Brown  parseValue = staticmethod(parseValue)
69179860b2SJed Brown
70179860b2SJed Brown  def parseArgument(arg, ignoreDouble = 0):
71179860b2SJed Brown    '''Split an argument into a (key, value) tuple, stripping off the leading dashes. Return (None, None) on failure.'''
72179860b2SJed Brown    start = 0
73179860b2SJed Brown    if arg and arg[0] == '-':
74179860b2SJed Brown      start = 1
75179860b2SJed Brown      if arg[1] == '-' and not ignoreDouble:
76179860b2SJed Brown        start = 2
77179860b2SJed Brown    if arg.find('=') >= 0:
78179860b2SJed Brown      (key, value) = arg[start:].split('=', 1)
79179860b2SJed Brown    else:
80179860b2SJed Brown      if start == 0:
81179860b2SJed Brown        (key, value) = (None, arg)
82179860b2SJed Brown      else:
83179860b2SJed Brown        (key, value) = (arg[start:], '1')
84179860b2SJed Brown    return (key, Arg.parseValue(value))
85179860b2SJed Brown
86179860b2SJed Brown  parseArgument = staticmethod(parseArgument)
87179860b2SJed Brown
88179860b2SJed Brown  def findArgument(key, argList):
89179860b2SJed Brown    '''Locate an argument with the given key in argList, returning the value or None on failure
90179860b2SJed Brown       - This is generally used to process arguments which must take effect before canonical argument parsing'''
91179860b2SJed Brown    if not isinstance(argList, list): return None
92179860b2SJed Brown    # Reverse the list so that we preserve the semantics which state that the last
93179860b2SJed Brown    #   argument with a given key takes effect
94179860b2SJed Brown    l = argList[:]
95179860b2SJed Brown    l.reverse()
96179860b2SJed Brown    for arg in l:
97179860b2SJed Brown      (k, value) = Arg.parseArgument(arg)
98179860b2SJed Brown      if k == key:
99179860b2SJed Brown        return value
100179860b2SJed Brown    return None
101179860b2SJed Brown  findArgument = staticmethod(findArgument)
102179860b2SJed Brown
103179860b2SJed Brown  def processAlternatePrefixes(argList):
104179860b2SJed Brown    '''Convert alternate prefixes to our normal form'''
105179860b2SJed Brown    for l in range(0, len(argList)):
106179860b2SJed Brown      name = argList[l]
107179860b2SJed Brown      if name.find('enable-') >= 0:
108179860b2SJed Brown        argList[l] = name.replace('enable-','with-')
109179860b2SJed Brown        if name.find('=') == -1: argList[l] = argList[l]+'=1'
110179860b2SJed Brown      if name.find('disable-') >= 0:
111179860b2SJed Brown        argList[l] = name.replace('disable-','with-')
112179860b2SJed Brown        if name.find('=') == -1: argList[l] = argList[l]+'=0'
113179860b2SJed Brown        elif name.endswith('=1'): argList[l].replace('=1','=0')
114179860b2SJed Brown      if name.find('without-') >= 0:
115179860b2SJed Brown        argList[l] = name.replace('without-','with-')
116179860b2SJed Brown        if name.find('=') == -1: argList[l] = argList[l]+'=0'
117179860b2SJed Brown        elif name.endswith('=1'): argList[l].replace('=1','=0')
118179860b2SJed Brown    return
119179860b2SJed Brown  processAlternatePrefixes = staticmethod(processAlternatePrefixes)
120179860b2SJed Brown
121179860b2SJed Brown  def __str__(self):
122179860b2SJed Brown    if not self.isValueSet():
123179860b2SJed Brown      return 'Empty '+str(self.__class__)
124cc267e83SJacob Faibussowitsch    value = self.value
125cc267e83SJacob Faibussowitsch    if isinstance(value, list):
126cc267e83SJacob Faibussowitsch      return str(list(map(str, value)))
127cc267e83SJacob Faibussowitsch    return str(value)
128179860b2SJed Brown
129179860b2SJed Brown  def getKey(self):
130179860b2SJed Brown    '''Returns the key. SHOULD MAKE THIS A PROPERTY'''
131179860b2SJed Brown    return self.key
132179860b2SJed Brown
133179860b2SJed Brown  def setKey(self, key):
134179860b2SJed Brown    '''Set the key. SHOULD MAKE THIS A PROPERTY'''
135179860b2SJed Brown    self.key = key
136179860b2SJed Brown    return
137179860b2SJed Brown
138179860b2SJed Brown  def getValue(self):
139179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
140179860b2SJed Brown    if not self.isValueSet():
141179860b2SJed Brown      raise KeyError('Could not find value for key '+str(self.key))
142179860b2SJed Brown    return self.value
143179860b2SJed Brown
144179860b2SJed Brown  def checkKey(self):
145179860b2SJed Brown    if self.deprecated:
146179860b2SJed Brown      if isinstance(self.deprecated, str):
147179860b2SJed Brown        raise KeyError('Deprecated option '+self.key+' should be '+self.deprecated)
148179860b2SJed Brown      raise KeyError('Deprecated option '+self.key)
149179860b2SJed Brown    return
150179860b2SJed Brown
151179860b2SJed Brown  def setValue(self, value):
152179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
153179860b2SJed Brown    self.checkKey()
154179860b2SJed Brown    self.value = value
155179860b2SJed Brown    return
156179860b2SJed Brown
157179860b2SJed Brownclass ArgBool(Arg):
158179860b2SJed Brown  '''Arguments that represent boolean values'''
159179860b2SJed Brown  def __init__(self, key, value = None, help = '', isTemporary = 0, deprecated = False):
160179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
161179860b2SJed Brown    return
162179860b2SJed Brown
163179860b2SJed Brown  def setValue(self, value):
164179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
165179860b2SJed Brown    self.checkKey()
166179860b2SJed Brown    try:
167179860b2SJed Brown      if   value == 'no':    value = 0
168179860b2SJed Brown      elif value == 'yes':   value = 1
169179860b2SJed Brown      elif value == 'true':  value = 1
170179860b2SJed Brown      elif value == 'false': value = 0
171179860b2SJed Brown      elif value == 'True':  value = 1
172179860b2SJed Brown      elif value == 'False': value = 0
173179860b2SJed Brown      else:                  value = int(value)
174179860b2SJed Brown    except:
175179860b2SJed Brown      raise TypeError('Invalid boolean value: '+str(value)+' for key '+str(self.key))
176179860b2SJed Brown    self.value = value
177179860b2SJed Brown    return
178179860b2SJed Brown
179179860b2SJed Brownclass ArgFuzzyBool(Arg):
180179860b2SJed Brown  '''Arguments that represent boolean values of an extended set'''
181179860b2SJed Brown  def __init__(self, key, value = None, help = '', isTemporary = 0, deprecated = False):
182179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
183179860b2SJed Brown    return
184179860b2SJed Brown
185179860b2SJed Brown  def valueName(self, value):
186179860b2SJed Brown    if value == 0:
187179860b2SJed Brown      return 'no'
188179860b2SJed Brown    elif value == 1:
189179860b2SJed Brown      return 'yes'
190179860b2SJed Brown    elif value == 2:
191179860b2SJed Brown      return 'ifneeded'
192179860b2SJed Brown    return str(value)
193179860b2SJed Brown
194179860b2SJed Brown  def __str__(self):
195179860b2SJed Brown    if not self.isValueSet():
196179860b2SJed Brown      return 'Empty '+str(self.__class__)
197179860b2SJed Brown    elif isinstance(self.value, list):
198179860b2SJed Brown      return str(map(self.valueName, self.value))
199179860b2SJed Brown    return self.valueName(self.value)
200179860b2SJed Brown
201179860b2SJed Brown  def setValue(self, value):
202179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
203179860b2SJed Brown    self.checkKey()
204179860b2SJed Brown    try:
205179860b2SJed Brown      if   value == '0':        value = 0
206179860b2SJed Brown      elif value == '1':        value = 1
207179860b2SJed Brown      elif value == 'no':       value = 0
208179860b2SJed Brown      elif value == 'yes':      value = 1
209179860b2SJed Brown      elif value == 'false':    value = 0
210179860b2SJed Brown      elif value == 'true':     value = 1
211179860b2SJed Brown      elif value == 'maybe':    value = 2
212179860b2SJed Brown      elif value == 'ifneeded': value = 2
213179860b2SJed Brown      elif value == 'client':   value = 2
214179860b2SJed Brown      elif value == 'server':   value = 3
215179860b2SJed Brown      else:                     value = int(value)
216179860b2SJed Brown    except:
217179860b2SJed Brown      raise TypeError('Invalid fuzzy boolean value: '+str(value)+' for key '+str(self.key))
218179860b2SJed Brown    self.value = value
219179860b2SJed Brown    return
220179860b2SJed Brown
221179860b2SJed Brownclass ArgInt(Arg):
222179860b2SJed Brown  '''Arguments that represent integer numbers'''
2235b6bfdb9SJed Brown  def __init__(self, key, value = None, help = '', min = -2147483647, max = 2147483648, isTemporary = 0, deprecated = False):
224179860b2SJed Brown    self.min = min
225179860b2SJed Brown    self.max = max
226179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
227179860b2SJed Brown    return
228179860b2SJed Brown
229179860b2SJed Brown  def setValue(self, value):
230179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
231179860b2SJed Brown    self.checkKey()
232179860b2SJed Brown    try:
233179860b2SJed Brown      value = int(value)
234179860b2SJed Brown    except:
235179860b2SJed Brown      raise TypeError('Invalid integer number: '+str(value)+' for key '+str(self.key))
236179860b2SJed Brown    if value < self.min or value >= self.max:
237179860b2SJed Brown      raise ValueError('Number out of range: '+str(value)+' not in ['+str(self.min)+','+str(self.max)+')'+' for key '+str(self.key))
238179860b2SJed Brown    self.value = value
239179860b2SJed Brown    return
240179860b2SJed Brown
241179860b2SJed Brownclass ArgReal(Arg):
242179860b2SJed Brown  '''Arguments that represent floating point numbers'''
243179860b2SJed Brown  def __init__(self, key, value = None, help = '', min = -1.7976931348623157e308, max = 1.7976931348623157e308, isTemporary = 0, deprecated = False):
244179860b2SJed Brown    self.min = min
245179860b2SJed Brown    self.max = max
246179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
247179860b2SJed Brown    return
248179860b2SJed Brown
249179860b2SJed Brown  def setValue(self, value):
250179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
251179860b2SJed Brown    self.checkKey()
252179860b2SJed Brown    try:
253179860b2SJed Brown      value = float(value)
254179860b2SJed Brown    except:
255179860b2SJed Brown      raise TypeError('Invalid floating point number: '+str(value)+' for key '+str(self.key))
256179860b2SJed Brown    if value < self.min or value >= self.max:
257179860b2SJed Brown      raise ValueError('Number out of range: '+str(value)+' not in ['+str(self.min)+','+str(self.max)+')'+' for key '+str(self.key))
258179860b2SJed Brown    self.value = value
259179860b2SJed Brown    return
260179860b2SJed Brown
261179860b2SJed Brownclass ArgDir(Arg):
262179860b2SJed Brown  '''Arguments that represent directories'''
263179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
264179860b2SJed Brown    self.mustExist = mustExist
265179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
266179860b2SJed Brown    return
267179860b2SJed Brown
268179860b2SJed Brown  def getValue(self):
269179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
270179860b2SJed Brown    if not self.isValueSet():
271179860b2SJed Brown      return Arg.getValue(self)
272179860b2SJed Brown    return self.value
273179860b2SJed Brown
274179860b2SJed Brown  def setValue(self, value):
275179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
276179860b2SJed Brown    import os
277179860b2SJed Brown    self.checkKey()
278179860b2SJed Brown    # Should check whether it is a well-formed path
279179860b2SJed Brown    if not isinstance(value, str):
280179860b2SJed Brown      raise TypeError('Invalid directory: '+str(value)+' for key '+str(self.key))
281179860b2SJed Brown    value = os.path.expanduser(value)
2829992b254SSatish Balay    value = os.path.abspath(value)
283179860b2SJed Brown    if self.mustExist and value and not os.path.isdir(value):
284179860b2SJed Brown      raise ValueError('Nonexistent directory: '+str(value)+' for key '+str(self.key))
285179860b2SJed Brown    self.value = value
286179860b2SJed Brown    return
287179860b2SJed Brown
288179860b2SJed Brownclass ArgDirList(Arg):
289179860b2SJed Brown  '''Arguments that represent directory lists'''
290179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
291179860b2SJed Brown    self.mustExist = mustExist
292179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
293179860b2SJed Brown    return
294179860b2SJed Brown
295179860b2SJed Brown  def getValue(self):
296179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
297179860b2SJed Brown    if not self.isValueSet():
298179860b2SJed Brown      return Arg.getValue(self)
299179860b2SJed Brown    return self.value
300179860b2SJed Brown
301179860b2SJed Brown  def setValue(self, value):
302179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
303179860b2SJed Brown    import os
304179860b2SJed Brown    self.checkKey()
305179860b2SJed Brown    if not isinstance(value, list):
306158e955bSSatish Balay      value = value.split(':')
307179860b2SJed Brown    # Should check whether it is a well-formed path
308179860b2SJed Brown    nvalue = []
309179860b2SJed Brown    for dir in value:
310928c5b42SSatish Balay      if dir:
311179860b2SJed Brown        nvalue.append(os.path.expanduser(dir))
312179860b2SJed Brown    value = nvalue
313179860b2SJed Brown    for dir in value:
314179860b2SJed Brown      if self.mustExist and not os.path.isdir(dir):
315179860b2SJed Brown        raise ValueError('Invalid directory: '+str(dir)+' for key '+str(self.key))
316179860b2SJed Brown    self.value = value
317179860b2SJed Brown    return
318179860b2SJed Brown
319c88f93c3SSatish Balayclass ArgFile(Arg):
320c88f93c3SSatish Balay  '''Arguments that represent a file'''
321c88f93c3SSatish Balay  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
322c88f93c3SSatish Balay    self.mustExist = mustExist
323c88f93c3SSatish Balay    Arg.__init__(self, key, value, help, isTemporary, deprecated)
324c88f93c3SSatish Balay    return
325c88f93c3SSatish Balay
326c88f93c3SSatish Balay  def getValue(self):
327c88f93c3SSatish Balay    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
328c88f93c3SSatish Balay    if not self.isValueSet():
329c88f93c3SSatish Balay      return Arg.getValue(self)
330c88f93c3SSatish Balay    return self.value
331c88f93c3SSatish Balay
332c88f93c3SSatish Balay  def setValue(self, value):
333c88f93c3SSatish Balay    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
334c88f93c3SSatish Balay    import os
335c88f93c3SSatish Balay    self.checkKey()
336c88f93c3SSatish Balay    # Should check whether it is a well-formed path
337c88f93c3SSatish Balay    if not isinstance(value, str):
338c88f93c3SSatish Balay      raise TypeError('Invalid file: '+str(value)+' for key '+str(self.key))
339c88f93c3SSatish Balay    value = os.path.expanduser(value)
340c88f93c3SSatish Balay    value = os.path.abspath(value)
341c88f93c3SSatish Balay    if self.mustExist and value and not os.path.isfile(value):
342c88f93c3SSatish Balay      raise ValueError('Nonexistent file: '+str(value)+' for key '+str(self.key))
343c88f93c3SSatish Balay    self.value = value
344c88f93c3SSatish Balay    return
345c88f93c3SSatish Balay
346c88f93c3SSatish Balayclass ArgFileList(Arg):
347c88f93c3SSatish Balay  '''Arguments that represent file lists'''
348c88f93c3SSatish Balay  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
349c88f93c3SSatish Balay    self.mustExist = mustExist
350c88f93c3SSatish Balay    Arg.__init__(self, key, value, help, isTemporary, deprecated)
351c88f93c3SSatish Balay    return
352c88f93c3SSatish Balay
353c88f93c3SSatish Balay  def getValue(self):
354c88f93c3SSatish Balay    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
355c88f93c3SSatish Balay    if not self.isValueSet():
356c88f93c3SSatish Balay      return Arg.getValue(self)
357c88f93c3SSatish Balay    return self.value
358c88f93c3SSatish Balay
359c88f93c3SSatish Balay  def setValue(self, value):
360c88f93c3SSatish Balay    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
361c88f93c3SSatish Balay    import os
362c88f93c3SSatish Balay    self.checkKey()
363c88f93c3SSatish Balay    if not isinstance(value, list):
364c88f93c3SSatish Balay      value = value.split(':')
365c88f93c3SSatish Balay    # Should check whether it is a well-formed path
366c88f93c3SSatish Balay    nvalue = []
367c88f93c3SSatish Balay    for file in value:
368c88f93c3SSatish Balay      if file:
369c88f93c3SSatish Balay        nvalue.append(os.path.expanduser(file))
370c88f93c3SSatish Balay    value = nvalue
371c88f93c3SSatish Balay    for file in value:
372c88f93c3SSatish Balay      if self.mustExist and not os.path.isfile(file):
373c88f93c3SSatish Balay        raise ValueError('Invalid file: '+str(file)+' for key '+str(self.key))
374c88f93c3SSatish Balay    self.value = value
375c88f93c3SSatish Balay    return
376c88f93c3SSatish Balay
377179860b2SJed Brownclass ArgLibrary(Arg):
378179860b2SJed Brown  '''Arguments that represent libraries'''
379179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
380179860b2SJed Brown    self.mustExist = mustExist
381179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
382179860b2SJed Brown    return
383179860b2SJed Brown
384179860b2SJed Brown  def getValue(self):
385179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
386179860b2SJed Brown    if not self.isValueSet():
387179860b2SJed Brown      return Arg.getValue(self)
388179860b2SJed Brown    return self.value
389179860b2SJed Brown
390179860b2SJed Brown  def setValue(self, value):
391179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
392179860b2SJed Brown    import os
393179860b2SJed Brown    self.checkKey()
394179860b2SJed Brown    # Should check whether it is a well-formed path and an archive or shared object
395179860b2SJed Brown    if self.mustExist:
396179860b2SJed Brown      if not isinstance(value, list):
397179860b2SJed Brown        value = value.split(' ')
398179860b2SJed Brown    self.value = value
399179860b2SJed Brown    return
400179860b2SJed Brown
401179860b2SJed Brownclass ArgExecutable(Arg):
402179860b2SJed Brown  '''Arguments that represent executables'''
403179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
404179860b2SJed Brown    self.mustExist = mustExist
405179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
406179860b2SJed Brown    return
407179860b2SJed Brown
408179860b2SJed Brown  def getValue(self):
409179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
410179860b2SJed Brown    if not self.isValueSet():
411179860b2SJed Brown      return Arg.getValue(self)
412179860b2SJed Brown    return self.value
413179860b2SJed Brown
414179860b2SJed Brown  def checkExecutable(self, dir, name):
415179860b2SJed Brown    import os
416179860b2SJed Brown    prog = os.path.join(dir, name)
417179860b2SJed Brown    return os.path.isfile(prog) and os.access(prog, os.X_OK)
418179860b2SJed Brown
419179860b2SJed Brown  def setValue(self, value):
420179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
421179860b2SJed Brown    import os
422179860b2SJed Brown    self.checkKey()
423179860b2SJed Brown    # Should check whether it is a well-formed path
424179860b2SJed Brown    if self.mustExist:
425179860b2SJed Brown      index = value.find(' ')
426179860b2SJed Brown      if index >= 0:
427179860b2SJed Brown        options = value[index:]
428179860b2SJed Brown        value   = value[:index]
429179860b2SJed Brown      else:
430179860b2SJed Brown        options = ''
431179860b2SJed Brown      found = self.checkExecutable('', value)
432179860b2SJed Brown      if not found:
433179860b2SJed Brown        for dir in os.environ['PATH'].split(os.path.pathsep):
434179860b2SJed Brown          if self.checkExecutable(dir, value):
435179860b2SJed Brown            found = 1
436179860b2SJed Brown            break
437179860b2SJed Brown      if not found:
438179860b2SJed Brown        raise ValueError('Invalid executable: '+str(value)+' for key '+str(self.key))
4397ce81a4bSJacob Faibussowitsch      value += options
4407ce81a4bSJacob Faibussowitsch    self.value = value
441179860b2SJed Brown    return
442179860b2SJed Brown
443179860b2SJed Brownclass ArgString(Arg):
444179860b2SJed Brown  '''Arguments that represent strings satisfying a given regular expression'''
445179860b2SJed Brown  def __init__(self, key, value = None, help = '', regExp = None, isTemporary = 0, deprecated = False):
446179860b2SJed Brown    self.regExp = regExp
447179860b2SJed Brown    if self.regExp:
448179860b2SJed Brown      import re
449179860b2SJed Brown      self.re = re.compile(self.regExp)
450179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
451179860b2SJed Brown    return
452179860b2SJed Brown
453179860b2SJed Brown  def setValue(self, value):
454179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
455179860b2SJed Brown    self.checkKey()
456179860b2SJed Brown    if self.regExp and not self.re.match(value):
457179860b2SJed Brown      raise ValueError('Invalid string '+str(value)+'. You must give a string satisfying "'+str(self.regExp)+'"'+' for key '+str(self.key))
458179860b2SJed Brown    self.value = value
459179860b2SJed Brown    return
460179860b2SJed Brown
461179860b2SJed Brownclass ArgDownload(Arg):
462179860b2SJed Brown  '''Arguments that represent software downloads'''
463179860b2SJed Brown  def __init__(self, key, value = None, help = '', isTemporary = 0, deprecated = False):
464179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
465179860b2SJed Brown    return
466179860b2SJed Brown
467179860b2SJed Brown  def valueName(self, value):
468179860b2SJed Brown    if value == 0:
469179860b2SJed Brown      return 'no'
470179860b2SJed Brown    elif value == 1:
471179860b2SJed Brown      return 'yes'
472179860b2SJed Brown    return str(value)
473179860b2SJed Brown
474179860b2SJed Brown  def __str__(self):
475179860b2SJed Brown    if not self.isValueSet():
476179860b2SJed Brown      return 'Empty '+str(self.__class__)
477179860b2SJed Brown    elif isinstance(self.value, list):
478179860b2SJed Brown      return str(map(self.valueName, self.value))
479179860b2SJed Brown    return self.valueName(self.value)
480179860b2SJed Brown
481179860b2SJed Brown  def setValue(self, value):
482179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
483179860b2SJed Brown    import os
484179860b2SJed Brown    self.checkKey()
485179860b2SJed Brown    try:
486179860b2SJed Brown      if   value == '0':        value = 0
487179860b2SJed Brown      elif value == '1':        value = 1
488179860b2SJed Brown      elif value == 'no':       value = 0
489179860b2SJed Brown      elif value == 'yes':      value = 1
490179860b2SJed Brown      elif value == 'false':    value = 0
491179860b2SJed Brown      elif value == 'true':     value = 1
492179860b2SJed Brown      elif not isinstance(value, int):
493179860b2SJed Brown        value = str(value)
494179860b2SJed Brown    except:
495179860b2SJed Brown      raise TypeError('Invalid download value: '+str(value)+' for key '+str(self.key))
496*ffde4defSBarry Smith    if isinstance(value, str) and value.startswith('git@'):
497*ffde4defSBarry Smith      # git@github.com:xrq-phys/blis_apple.git -> git://https://github.com/xrq-phys/blis_apple.git
498*ffde4defSBarry Smith      value = 'git://https://'+(value[len('git@'):].replace(':','/'))
499179860b2SJed Brown    if isinstance(value, str):
500df3bd252SSatish Balay      from urllib import parse as urlparse_local
501465d835dSVaclav Hapla      if not urlparse_local.urlparse(value)[0] and not os.path.exists(value):
502179860b2SJed Brown        raise ValueError('Invalid download location: '+str(value)+' for key '+str(self.key))
503179860b2SJed Brown    self.value = value
504179860b2SJed Brown    return
505