1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
'''Option parsing library for utilities'''
__revision__ = '$Revision$'
import getopt, os, sys, ConfigParser
# (option, env, cfpath, default value, option desc, boolean, arg desc)
# ((option, arg desc, opt desc), env, cfpath, default, boolean)
bootstrap = {'configfile': (('-C', '<configfile>', 'Path to config file'),
'BCFG2_CONF', False, '/etc/bcfg2.conf', False)}
class OptionFailure(Exception):
pass
class BasicOptionParser:
'''Basic OptionParser takes input from command line arguments, environment variables, and defaults'''
def __init__(self, name, optionspec, configfile=False, dogetopt=False):
self.name = name
self.dogetopt = dogetopt
self.configfile = configfile
self.optionspec = optionspec
if dogetopt:
self.shortopt = ''
self.helpmsg = ''
# longopts aren't yet supported
self.longopt = []
for option, info in optionspec.iteritems():
(opt, argd, optd) = info[0]
self.helpmsg += opt.ljust(3)
if opt.count('-') == 1:
self.shortopt += opt[1]
else:
print "unsupported option %s" % (opt)
continue
if info[4]:
self.helpmsg += 24 * ' '
else:
self.shortopt += ':'
self.helpmsg += "%-24s" % (argd)
self.helpmsg += "%s\n" % (optd)
def parse(self):
'''Parse options'''
ret = {}
if self.dogetopt:
try:
opts, args = getopt.getopt(sys.argv[1:], self.shortopt, self.longopt)
except getopt.GetoptError, err:
print err
print "%s Usage:" % (self.name)
print self.helpmsg
raise SystemExit, 1
if '-h' in sys.argv:
print "%s Usage:" % (self.name)
print self.helpmsg
raise SystemExit, 1
if self.configfile:
cf = ConfigParser.ConfigParser()
cf.read(self.configfile)
for key, (option, envvar, cfpath, default, boolean) in self.optionspec.iteritems():
if self.dogetopt:
optinfo = [opt[1] for opt in opts if opt[0] == option[0]]
if optinfo:
if boolean:
ret[key] = True
else:
ret[key] = optinfo[0]
continue
if option[0] in sys.argv:
if boolean:
ret[key] = True
else:
ret[key] = sys.argv[sys.argv.index(option[0]) + 1]
continue
elif envvar and os.environ.has_key(envvar):
ret[key] = os.environ[envvar]
continue
elif self.configfile and cfpath:
try:
value = apply(cf.get, cfpath)
ret[key] = value
continue
except:
pass
else:
ret[key] = default
continue
return ret
class OptionParser(BasicOptionParser):
'''OptionParser bootstraps option parsing, getting the value of the config file'''
def __init__(self, name, ospec):
# first find the cf file
cfpath = BasicOptionParser('bootstrap', bootstrap).parse()['configfile']
BasicOptionParser.__init__(self, name, ospec, cfpath, dogetopt=True)
|