Commit 5bb94eca authored by Jonathan Jenkins's avatar Jonathan Jenkins

command line options for substituting, for use in shell scripts

parent f35597e8
......@@ -15,7 +15,7 @@ def main():
# load the module
mod = import_from(args.substitute_py)
# checks - make sure cfields is set and is the correct type
if "cfields" not in mod.__dict__:
raise TypeError("Expected cfields to be defined in " + args.substitute_py)
......@@ -24,14 +24,32 @@ def main():
isinstance(mod.cfields[0][0], str) and \
isinstance(mod.cfields[0][1], Sequence)):
raise TypeError("cfields in incorrect format, see usage")
num_fields = len(mod.cfields)
# get list of iterators, replacement input, and output labels
labels = [ k[0] for k in mod.cfields]
iterables = [ k[1].__iter__() for k in mod.cfields]
# use two dicts to maintain type information when printing (don't want
# quotes to appear in log file)
replace_map = { k[0] : None for k in mod.cfields }
# process the command line token replacements, adding to labels
# and replace_map, but not to iterables
if len(args.token_pairs) % 2 != 0:
raise ValueError("token pairs must come in twos")
elif len(args.token_pairs) > 0:
for i in range(0, len(args.token_pairs), 2):
k,vstr = args.token_pairs[i],args.token_pairs[i+1]
# try making v numeric - fall back to string
v = try_num(vstr)
if v == None:
v = vstr
# add pair to replace map and labels (but not iterables!)
if k in replace_map:
raise ValueError("token " + k + " of token_pairs matches a token "
"given by the substitution py file")
else:
replace_map[k] = v
labels.append(k)
# print the header to the log
if args.log != None:
flog = open(args.log, "w")
......@@ -43,9 +61,9 @@ def main():
flog.write("\n")
# generate initial configuration
for i,k in enumerate(labels):
for i in range(0,num_fields):
v = iterables[i].next()
replace_map[k] = v
replace_map[labels[i]] = v
# main loop
ct = 0
......@@ -59,27 +77,27 @@ def main():
# print the configuration to the log
flog.write(str(ct))
for i,k in enumerate(labels):
if isinstance(replace_map[k], str):
flog.write(' "' + replace_map[k] + '"')
for l in labels:
if isinstance(replace_map[l], str):
flog.write(' "' + replace_map[l] + '"')
else:
flog.write(" " + str(replace_map[k]))
flog.write(" " + str(replace_map[l]))
else:
flog.write('\n')
# generate the next config
for i,k in enumerate(labels):
for i in range(0,num_fields):
try:
# update current iterable and finish
v = iterables[i].next()
replace_map[k] = v
replace_map[labels[i]] = v
ct += 1
break
except StopIteration:
# reset the current iterable and set to first element
iterables[i] = mod.cfields[i][1].__iter__()
v = iterables[i].next()
replace_map[k] = v
replace_map[labels[i]] = v
else:
# last iterable has finished, have generated full set
break
......@@ -118,19 +136,36 @@ def replace_many(st, kv_pairs):
return pat.sub(lambda match: rep_dict[match.group(0)], st)
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument("template",\
parser = argparse.ArgumentParser(\
description="generate set of configuration files based on template "
"file and replacement tokens")
parser.add_argument("template",
help="template file with replace tokens")
parser.add_argument("substitute_py",\
help='python file defining "cfields" variable consisting of'\
' elements of the form ( replacement_token, [replacements...])')
parser.add_argument("-l", "--log",\
help="log file to write parameterizations to")
parser.add_argument("-o", "--output_prefix",\
parser.add_argument("substitute_py",
help='python file defining "cfields" variable consisting of '
'elements of the form '
'( replacement_token, [replacements...])')
parser.add_argument("token_pairs",
nargs='*',
help="a list of whitespace-separated token, replace pairs for "
"command-line-driven replacement (useful in shell scripts "
"for generating sets of configuration files with a distinct "
"parameter or for special casing fields)")
parser.add_argument("-l", "--log",
help="log file to write parameterizations to")
parser.add_argument("-o", "--output_prefix",
help="prefix to output generated configuration files to "
"(default: the configuration index appended to the template name)")
return parser.parse_args()
def try_num(s):
try:
return int(s)
except ValueError:
try:
return float(s)
except ValueError:
return None
if __name__ == "__main__":
main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment