xref: /petsc/config/BuildSystem/nargs.py (revision df3bd252dbc574245cbbb4edf6b407438c525c05)
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__)
124179860b2SJed Brown    elif isinstance(self.value, list):
125179860b2SJed Brown      return str(map(str, self.value))
126179860b2SJed Brown    return str(self.value)
127179860b2SJed Brown
128179860b2SJed Brown  def getKey(self):
129179860b2SJed Brown    '''Returns the key. SHOULD MAKE THIS A PROPERTY'''
130179860b2SJed Brown    return self.key
131179860b2SJed Brown
132179860b2SJed Brown  def setKey(self, key):
133179860b2SJed Brown    '''Set the key. SHOULD MAKE THIS A PROPERTY'''
134179860b2SJed Brown    self.key = key
135179860b2SJed Brown    return
136179860b2SJed Brown
137179860b2SJed Brown  def getValue(self):
138179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
139179860b2SJed Brown    if not self.isValueSet():
140179860b2SJed Brown      raise KeyError('Could not find value for key '+str(self.key))
141179860b2SJed Brown    return self.value
142179860b2SJed Brown
143179860b2SJed Brown  def checkKey(self):
144179860b2SJed Brown    if self.deprecated:
145179860b2SJed Brown      if isinstance(self.deprecated, str):
146179860b2SJed Brown        raise KeyError('Deprecated option '+self.key+' should be '+self.deprecated)
147179860b2SJed Brown      raise KeyError('Deprecated option '+self.key)
148179860b2SJed Brown    return
149179860b2SJed Brown
150179860b2SJed Brown  def setValue(self, value):
151179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
152179860b2SJed Brown    self.checkKey()
153179860b2SJed Brown    self.value = value
154179860b2SJed Brown    return
155179860b2SJed Brown
156179860b2SJed Brownclass ArgBool(Arg):
157179860b2SJed Brown  '''Arguments that represent boolean values'''
158179860b2SJed Brown  def __init__(self, key, value = None, help = '', isTemporary = 0, deprecated = False):
159179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
160179860b2SJed Brown    return
161179860b2SJed Brown
162179860b2SJed Brown  def setValue(self, value):
163179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
164179860b2SJed Brown    self.checkKey()
165179860b2SJed Brown    try:
166179860b2SJed Brown      if   value == 'no':    value = 0
167179860b2SJed Brown      elif value == 'yes':   value = 1
168179860b2SJed Brown      elif value == 'true':  value = 1
169179860b2SJed Brown      elif value == 'false': value = 0
170179860b2SJed Brown      elif value == 'True':  value = 1
171179860b2SJed Brown      elif value == 'False': value = 0
172179860b2SJed Brown      else:                  value = int(value)
173179860b2SJed Brown    except:
174179860b2SJed Brown      raise TypeError('Invalid boolean value: '+str(value)+' for key '+str(self.key))
175179860b2SJed Brown    self.value = value
176179860b2SJed Brown    return
177179860b2SJed Brown
178179860b2SJed Brownclass ArgFuzzyBool(Arg):
179179860b2SJed Brown  '''Arguments that represent boolean values of an extended set'''
180179860b2SJed Brown  def __init__(self, key, value = None, help = '', isTemporary = 0, deprecated = False):
181179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
182179860b2SJed Brown    return
183179860b2SJed Brown
184179860b2SJed Brown  def valueName(self, value):
185179860b2SJed Brown    if value == 0:
186179860b2SJed Brown      return 'no'
187179860b2SJed Brown    elif value == 1:
188179860b2SJed Brown      return 'yes'
189179860b2SJed Brown    elif value == 2:
190179860b2SJed Brown      return 'ifneeded'
191179860b2SJed Brown    return str(value)
192179860b2SJed Brown
193179860b2SJed Brown  def __str__(self):
194179860b2SJed Brown    if not self.isValueSet():
195179860b2SJed Brown      return 'Empty '+str(self.__class__)
196179860b2SJed Brown    elif isinstance(self.value, list):
197179860b2SJed Brown      return str(map(self.valueName, self.value))
198179860b2SJed Brown    return self.valueName(self.value)
199179860b2SJed Brown
200179860b2SJed Brown  def setValue(self, value):
201179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
202179860b2SJed Brown    self.checkKey()
203179860b2SJed Brown    try:
204179860b2SJed Brown      if   value == '0':        value = 0
205179860b2SJed Brown      elif value == '1':        value = 1
206179860b2SJed Brown      elif value == 'no':       value = 0
207179860b2SJed Brown      elif value == 'yes':      value = 1
208179860b2SJed Brown      elif value == 'false':    value = 0
209179860b2SJed Brown      elif value == 'true':     value = 1
210179860b2SJed Brown      elif value == 'maybe':    value = 2
211179860b2SJed Brown      elif value == 'ifneeded': value = 2
212179860b2SJed Brown      elif value == 'client':   value = 2
213179860b2SJed Brown      elif value == 'server':   value = 3
214179860b2SJed Brown      else:                     value = int(value)
215179860b2SJed Brown    except:
216179860b2SJed Brown      raise TypeError('Invalid fuzzy boolean value: '+str(value)+' for key '+str(self.key))
217179860b2SJed Brown    self.value = value
218179860b2SJed Brown    return
219179860b2SJed Brown
220179860b2SJed Brownclass ArgInt(Arg):
221179860b2SJed Brown  '''Arguments that represent integer numbers'''
2225b6bfdb9SJed Brown  def __init__(self, key, value = None, help = '', min = -2147483647, max = 2147483648, isTemporary = 0, deprecated = False):
223179860b2SJed Brown    self.min = min
224179860b2SJed Brown    self.max = max
225179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
226179860b2SJed Brown    return
227179860b2SJed Brown
228179860b2SJed Brown  def setValue(self, value):
229179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
230179860b2SJed Brown    self.checkKey()
231179860b2SJed Brown    try:
232179860b2SJed Brown      value = int(value)
233179860b2SJed Brown    except:
234179860b2SJed Brown      raise TypeError('Invalid integer number: '+str(value)+' for key '+str(self.key))
235179860b2SJed Brown    if value < self.min or value >= self.max:
236179860b2SJed Brown      raise ValueError('Number out of range: '+str(value)+' not in ['+str(self.min)+','+str(self.max)+')'+' for key '+str(self.key))
237179860b2SJed Brown    self.value = value
238179860b2SJed Brown    return
239179860b2SJed Brown
240179860b2SJed Brownclass ArgReal(Arg):
241179860b2SJed Brown  '''Arguments that represent floating point numbers'''
242179860b2SJed Brown  def __init__(self, key, value = None, help = '', min = -1.7976931348623157e308, max = 1.7976931348623157e308, isTemporary = 0, deprecated = False):
243179860b2SJed Brown    self.min = min
244179860b2SJed Brown    self.max = max
245179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
246179860b2SJed Brown    return
247179860b2SJed Brown
248179860b2SJed Brown  def setValue(self, value):
249179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
250179860b2SJed Brown    self.checkKey()
251179860b2SJed Brown    try:
252179860b2SJed Brown      value = float(value)
253179860b2SJed Brown    except:
254179860b2SJed Brown      raise TypeError('Invalid floating point number: '+str(value)+' for key '+str(self.key))
255179860b2SJed Brown    if value < self.min or value >= self.max:
256179860b2SJed Brown      raise ValueError('Number out of range: '+str(value)+' not in ['+str(self.min)+','+str(self.max)+')'+' for key '+str(self.key))
257179860b2SJed Brown    self.value = value
258179860b2SJed Brown    return
259179860b2SJed Brown
260179860b2SJed Brownclass ArgDir(Arg):
261179860b2SJed Brown  '''Arguments that represent directories'''
262179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
263179860b2SJed Brown    self.mustExist = mustExist
264179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
265179860b2SJed Brown    return
266179860b2SJed Brown
267179860b2SJed Brown  def getValue(self):
268179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
269179860b2SJed Brown    if not self.isValueSet():
270179860b2SJed Brown      return Arg.getValue(self)
271179860b2SJed Brown    return self.value
272179860b2SJed Brown
273179860b2SJed Brown  def setValue(self, value):
274179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
275179860b2SJed Brown    import os
276179860b2SJed Brown    self.checkKey()
277179860b2SJed Brown    # Should check whether it is a well-formed path
278179860b2SJed Brown    if not isinstance(value, str):
279179860b2SJed Brown      raise TypeError('Invalid directory: '+str(value)+' for key '+str(self.key))
280179860b2SJed Brown    value = os.path.expanduser(value)
2819992b254SSatish Balay    value = os.path.abspath(value)
282179860b2SJed Brown    if self.mustExist and value and not os.path.isdir(value):
283179860b2SJed Brown      raise ValueError('Nonexistent directory: '+str(value)+' for key '+str(self.key))
284179860b2SJed Brown    self.value = value
285179860b2SJed Brown    return
286179860b2SJed Brown
287179860b2SJed Brownclass ArgDirList(Arg):
288179860b2SJed Brown  '''Arguments that represent directory lists'''
289179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
290179860b2SJed Brown    self.mustExist = mustExist
291179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
292179860b2SJed Brown    return
293179860b2SJed Brown
294179860b2SJed Brown  def getValue(self):
295179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
296179860b2SJed Brown    if not self.isValueSet():
297179860b2SJed Brown      return Arg.getValue(self)
298179860b2SJed Brown    return self.value
299179860b2SJed Brown
300179860b2SJed Brown  def setValue(self, value):
301179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
302179860b2SJed Brown    import os
303179860b2SJed Brown    self.checkKey()
304179860b2SJed Brown    if not isinstance(value, list):
305158e955bSSatish Balay      value = value.split(':')
306179860b2SJed Brown    # Should check whether it is a well-formed path
307179860b2SJed Brown    nvalue = []
308179860b2SJed Brown    for dir in value:
309928c5b42SSatish Balay      if dir:
310179860b2SJed Brown        nvalue.append(os.path.expanduser(dir))
311179860b2SJed Brown    value = nvalue
312179860b2SJed Brown    for dir in value:
313179860b2SJed Brown      if self.mustExist and not os.path.isdir(dir):
314179860b2SJed Brown        raise ValueError('Invalid directory: '+str(dir)+' for key '+str(self.key))
315179860b2SJed Brown    self.value = value
316179860b2SJed Brown    return
317179860b2SJed Brown
318c88f93c3SSatish Balayclass ArgFile(Arg):
319c88f93c3SSatish Balay  '''Arguments that represent a file'''
320c88f93c3SSatish Balay  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
321c88f93c3SSatish Balay    self.mustExist = mustExist
322c88f93c3SSatish Balay    Arg.__init__(self, key, value, help, isTemporary, deprecated)
323c88f93c3SSatish Balay    return
324c88f93c3SSatish Balay
325c88f93c3SSatish Balay  def getValue(self):
326c88f93c3SSatish Balay    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
327c88f93c3SSatish Balay    if not self.isValueSet():
328c88f93c3SSatish Balay      return Arg.getValue(self)
329c88f93c3SSatish Balay    return self.value
330c88f93c3SSatish Balay
331c88f93c3SSatish Balay  def setValue(self, value):
332c88f93c3SSatish Balay    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
333c88f93c3SSatish Balay    import os
334c88f93c3SSatish Balay    self.checkKey()
335c88f93c3SSatish Balay    # Should check whether it is a well-formed path
336c88f93c3SSatish Balay    if not isinstance(value, str):
337c88f93c3SSatish Balay      raise TypeError('Invalid file: '+str(value)+' for key '+str(self.key))
338c88f93c3SSatish Balay    value = os.path.expanduser(value)
339c88f93c3SSatish Balay    value = os.path.abspath(value)
340c88f93c3SSatish Balay    if self.mustExist and value and not os.path.isfile(value):
341c88f93c3SSatish Balay      raise ValueError('Nonexistent file: '+str(value)+' for key '+str(self.key))
342c88f93c3SSatish Balay    self.value = value
343c88f93c3SSatish Balay    return
344c88f93c3SSatish Balay
345c88f93c3SSatish Balayclass ArgFileList(Arg):
346c88f93c3SSatish Balay  '''Arguments that represent file lists'''
347c88f93c3SSatish Balay  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
348c88f93c3SSatish Balay    self.mustExist = mustExist
349c88f93c3SSatish Balay    Arg.__init__(self, key, value, help, isTemporary, deprecated)
350c88f93c3SSatish Balay    return
351c88f93c3SSatish Balay
352c88f93c3SSatish Balay  def getValue(self):
353c88f93c3SSatish Balay    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
354c88f93c3SSatish Balay    if not self.isValueSet():
355c88f93c3SSatish Balay      return Arg.getValue(self)
356c88f93c3SSatish Balay    return self.value
357c88f93c3SSatish Balay
358c88f93c3SSatish Balay  def setValue(self, value):
359c88f93c3SSatish Balay    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
360c88f93c3SSatish Balay    import os
361c88f93c3SSatish Balay    self.checkKey()
362c88f93c3SSatish Balay    if not isinstance(value, list):
363c88f93c3SSatish Balay      value = value.split(':')
364c88f93c3SSatish Balay    # Should check whether it is a well-formed path
365c88f93c3SSatish Balay    nvalue = []
366c88f93c3SSatish Balay    for file in value:
367c88f93c3SSatish Balay      if file:
368c88f93c3SSatish Balay        nvalue.append(os.path.expanduser(file))
369c88f93c3SSatish Balay    value = nvalue
370c88f93c3SSatish Balay    for file in value:
371c88f93c3SSatish Balay      if self.mustExist and not os.path.isfile(file):
372c88f93c3SSatish Balay        raise ValueError('Invalid file: '+str(file)+' for key '+str(self.key))
373c88f93c3SSatish Balay    self.value = value
374c88f93c3SSatish Balay    return
375c88f93c3SSatish Balay
376179860b2SJed Brownclass ArgLibrary(Arg):
377179860b2SJed Brown  '''Arguments that represent libraries'''
378179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
379179860b2SJed Brown    self.mustExist = mustExist
380179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
381179860b2SJed Brown    return
382179860b2SJed Brown
383179860b2SJed Brown  def getValue(self):
384179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
385179860b2SJed Brown    if not self.isValueSet():
386179860b2SJed Brown      return Arg.getValue(self)
387179860b2SJed Brown    return self.value
388179860b2SJed Brown
389179860b2SJed Brown  def setValue(self, value):
390179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
391179860b2SJed Brown    import os
392179860b2SJed Brown    self.checkKey()
393179860b2SJed Brown    # Should check whether it is a well-formed path and an archive or shared object
394179860b2SJed Brown    if self.mustExist:
395179860b2SJed Brown      if not isinstance(value, list):
396179860b2SJed Brown        value = value.split(' ')
397179860b2SJed Brown    self.value = value
398179860b2SJed Brown    return
399179860b2SJed Brown
400179860b2SJed Brownclass ArgExecutable(Arg):
401179860b2SJed Brown  '''Arguments that represent executables'''
402179860b2SJed Brown  def __init__(self, key, value = None, help = '', mustExist = 1, isTemporary = 0, deprecated = False):
403179860b2SJed Brown    self.mustExist = mustExist
404179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
405179860b2SJed Brown    return
406179860b2SJed Brown
407179860b2SJed Brown  def getValue(self):
408179860b2SJed Brown    '''Returns the value. SHOULD MAKE THIS A PROPERTY'''
409179860b2SJed Brown    if not self.isValueSet():
410179860b2SJed Brown      return Arg.getValue(self)
411179860b2SJed Brown    return self.value
412179860b2SJed Brown
413179860b2SJed Brown  def checkExecutable(self, dir, name):
414179860b2SJed Brown    import os
415179860b2SJed Brown    prog = os.path.join(dir, name)
416179860b2SJed Brown    return os.path.isfile(prog) and os.access(prog, os.X_OK)
417179860b2SJed Brown
418179860b2SJed Brown  def setValue(self, value):
419179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
420179860b2SJed Brown    import os
421179860b2SJed Brown    self.checkKey()
422179860b2SJed Brown    # Should check whether it is a well-formed path
423179860b2SJed Brown    if self.mustExist:
424179860b2SJed Brown      index = value.find(' ')
425179860b2SJed Brown      if index >= 0:
426179860b2SJed Brown        options = value[index:]
427179860b2SJed Brown        value   = value[:index]
428179860b2SJed Brown      else:
429179860b2SJed Brown        options = ''
430179860b2SJed Brown      found = self.checkExecutable('', value)
431179860b2SJed Brown      if not found:
432179860b2SJed Brown        for dir in os.environ['PATH'].split(os.path.pathsep):
433179860b2SJed Brown          if self.checkExecutable(dir, value):
434179860b2SJed Brown            found = 1
435179860b2SJed Brown            break
436179860b2SJed Brown      if not found:
437179860b2SJed Brown        raise ValueError('Invalid executable: '+str(value)+' for key '+str(self.key))
438179860b2SJed Brown    self.value = value+options
439179860b2SJed Brown    return
440179860b2SJed Brown
441179860b2SJed Brownclass ArgString(Arg):
442179860b2SJed Brown  '''Arguments that represent strings satisfying a given regular expression'''
443179860b2SJed Brown  def __init__(self, key, value = None, help = '', regExp = None, isTemporary = 0, deprecated = False):
444179860b2SJed Brown    self.regExp = regExp
445179860b2SJed Brown    if self.regExp:
446179860b2SJed Brown      import re
447179860b2SJed Brown      self.re = re.compile(self.regExp)
448179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
449179860b2SJed Brown    return
450179860b2SJed Brown
451179860b2SJed Brown  def setValue(self, value):
452179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
453179860b2SJed Brown    self.checkKey()
454179860b2SJed Brown    if self.regExp and not self.re.match(value):
455179860b2SJed Brown      raise ValueError('Invalid string '+str(value)+'. You must give a string satisfying "'+str(self.regExp)+'"'+' for key '+str(self.key))
456179860b2SJed Brown    self.value = value
457179860b2SJed Brown    return
458179860b2SJed Brown
459179860b2SJed Brownclass ArgDownload(Arg):
460179860b2SJed Brown  '''Arguments that represent software downloads'''
461179860b2SJed Brown  def __init__(self, key, value = None, help = '', isTemporary = 0, deprecated = False):
462179860b2SJed Brown    Arg.__init__(self, key, value, help, isTemporary, deprecated)
463179860b2SJed Brown    return
464179860b2SJed Brown
465179860b2SJed Brown  def valueName(self, value):
466179860b2SJed Brown    if value == 0:
467179860b2SJed Brown      return 'no'
468179860b2SJed Brown    elif value == 1:
469179860b2SJed Brown      return 'yes'
470179860b2SJed Brown    return str(value)
471179860b2SJed Brown
472179860b2SJed Brown  def __str__(self):
473179860b2SJed Brown    if not self.isValueSet():
474179860b2SJed Brown      return 'Empty '+str(self.__class__)
475179860b2SJed Brown    elif isinstance(self.value, list):
476179860b2SJed Brown      return str(map(self.valueName, self.value))
477179860b2SJed Brown    return self.valueName(self.value)
478179860b2SJed Brown
479179860b2SJed Brown  def setValue(self, value):
480179860b2SJed Brown    '''Set the value. SHOULD MAKE THIS A PROPERTY'''
481179860b2SJed Brown    import os
482179860b2SJed Brown    self.checkKey()
483179860b2SJed Brown    try:
484179860b2SJed Brown      if   value == '0':        value = 0
485179860b2SJed Brown      elif value == '1':        value = 1
486179860b2SJed Brown      elif value == 'no':       value = 0
487179860b2SJed Brown      elif value == 'yes':      value = 1
488179860b2SJed Brown      elif value == 'false':    value = 0
489179860b2SJed Brown      elif value == 'true':     value = 1
490179860b2SJed Brown      elif not isinstance(value, int):
491179860b2SJed Brown        value = str(value)
492179860b2SJed Brown    except:
493179860b2SJed Brown      raise TypeError('Invalid download value: '+str(value)+' for key '+str(self.key))
494179860b2SJed Brown    if isinstance(value, str):
495*df3bd252SSatish Balay      from urllib import parse as urlparse_local
496465d835dSVaclav Hapla      if not urlparse_local.urlparse(value)[0] and not os.path.exists(value):
497179860b2SJed Brown        raise ValueError('Invalid download location: '+str(value)+' for key '+str(self.key))
498179860b2SJed Brown    self.value = value
499179860b2SJed Brown    return
500