#!/usr/bin/env python
# all about options (so may merge with afni_base)
# do we want all of the
import sys
import afni_base
# ---------------------------------------------------------------------------
# This class provides functionality for processing lists of comopt elements.
class OptionList:
def __init__(self, label):
self.label = label
self.olist = [] # list of comopt elements
self.trailers = 0 # for read_options: no trailing args allowed
# from read_options: say there were such args
def show(self, mesg = ''):
print "%sOptionList: %s (len %d)" % \
(mesg, self.label, len(self.olist))
for index in range(len(self.olist)):
str = "opt %d: " % index
self.olist[index].show(str)
def find_opt(self, name, nth=1): # find nth occurance of option label
"""return nth comopt where name=name, else None"""
index = 0
for com in self.olist:
if com.name == name:
index += 1
if index == nth: return com
return None
def count_opt(self, name):
"""return number of comopts where name=name"""
count = 0
for com in self.olist:
if com.name == name: count += 1
return count
def add_opt(self, name, npar, defpar, acplist=[], req=0, setpar=0):
com = afni_base.comopt(name, npar, defpar, acplist)
com.required = req
if setpar: com.parlist = com.deflist
self.olist.append(com)
def del_opt(self, name, nth=1): # delete nth occurance of option label
"""delete nth comopt where name=name, else None"""
count = 0
for index in range(len(self.olist)):
if self.olist[index].name == name:
count += 1
if count == nth:
del self.olist[index]
return 1
# ---------------------------------------------------------------------------
# read_options:
# given an argument list, and OptionList of acceptable options,
# return an OptionList of found options, or None on failure
def read_options(argv, oplist, verb = 1):
"""Input an OptionList element, containing a list of options, required
or not, and return an OptionList of options as they are found.
return: an OptionList element, or None on a terminal error
note: options may occur more than once
"""
OL = OptionList("read_options")
alen = len(argv)
if alen == 0: return OL
# prepare a dictionary counting uses of each user option
namelist = {}
for co in oplist.olist:
if co.name in namelist: # complain if input list contains repeats
print "** RO warning: option '%s' appears more than once", co.name
namelist[co.name] = 0
if verb > 1 : print "-d namelist: ", namelist
# parse the input arguments:
# for each arg, verify arg is option, then process params
# so ac increments by 1+num_params each time
ac = 1
while ac < alen:
com = oplist.find_opt(argv[ac])
if com:
namelist[argv[ac]] += 1 # increment dictionary count
if verb > 2: print "+d found option '%s'" % com.name
if verb > 3: print "-d remaining args: %s" % argv[ac:-1]
# create new return option
newopt = afni_base.comopt(com.name, com.n_exp, com.deflist)
newopt.i_name = ac # current index into argv
newopt.acceptlist = com.acceptlist
newopt.required = com.required
ac += 1 # now point to next argument
# create parlist of potential parameters
if newopt.n_exp > 0: # try to insert that number of args
if newopt.n_exp <= alen - ac:
if verb > 2: print "+d adding %d params" % newopt.n_exp
parlist = argv[ac:ac+newopt.n_exp]
else: # too few args
print "** error: arg #%d (%s) requires %d params" % \
(ac-1, newopt.name, newopt.n_exp)
return None
elif newopt.n_exp < 0: # grab everything, and truncate later
if verb > 2: print "+d start with all %d params" % (alen-ac)
parlist = argv[ac:]
else: parlist = [] # n_exp == 0
# truncate parlist if it contains an option
for pc in range(len(parlist)):
if parlist[pc] in namelist: # then we have pc 'good' params
parlist = parlist[:pc]
if verb > 1: print "-d truncate %s after %d of %d" % \
(newopt.name, pc, len(parlist))
break;
# now check parlist against acceptlist
if newopt.acceptlist:
for par in parlist:
# check against repr(list element), since par is a string
# (search slowly for older versions of python)
found = 0
for accpar in newopt.acceptlist:
if par == str(accpar): found = 1
if not found: # panic into error! aaas yoooou wiiiiish...
print "** option %s: param '%s' is not in: %s" % \
(newopt.name, par, newopt.acceptlist)
return None # what else can we do?
# so do we still have enough parameters?
if newopt.n_exp < 0: nreq = abs(newopt.n_exp)
else: nreq = newopt.n_exp
if len(parlist) < nreq:
print "** error: arg #%d (%s) requires %d params, found %d" % \
(ac-1, newopt.name, nreq, len(parlist))
return None
# success! insert the remaining list
newopt.parlist = parlist
newopt.n_found = len(parlist)
else: # we seem to be done with expected arguments
# there should not be any options in this final list
for arg in argv[ac:]:
if arg in namelist:
print "** error: option %s follows unknown arg #%d (%s)" % \
(arg, ac, argv[ac])
return None
if not oplist.trailers : # then trailers are not allowed
print "** error: trailing arguments found: %s" % argv[ac:]
return None
# insert remaining args as trailers
newopt = afni_base.comopt('trailers', -1, [])
newopt.n_found = alen - ac
newopt.parlist = argv[ac:]
OL.olist.append(newopt) # insert newopt into our return list
ac += newopt.n_found # and increment the argument counter
# now we have processed all of argv
# any unused comopt that has a deflist can be used (else error)
for co in oplist.olist:
if namelist[co.name] == 0: # may still be okay
if co.required:
print "** error: missing option %s" % co.name
return None
elif len(co.deflist) > 0: # use it
newopt = afni_base.comopt(co.name, len(co.deflist), co.deflist)
newopt.parlist = newopt.deflist
# leave n_found at -1, so calling function knows
OL.olist.append(newopt) # insert newopt into our return list
if verb > 1 :
print "-d namelist: ", namelist
print "-d clist: "
return OL
def test_comopts():
okopts = OptionList('for_input')
okopts.add_opt('-a', 1, ['4' ] )
okopts.add_opt('-dsets', -1, [ ] )
okopts.add_opt('-debug', 1, ['0' ], range(4) )
okopts.add_opt('-c', 2, ['21', '24'] )
okopts.add_opt('-d', -1, [ ] )
okopts.add_opt('-e', -2, ['21', '24', '265'] )
okopts.trailers = 1 # allow trailing args
okopts.show('------ possible input options ------ ')
found_opts = read_options(sys.argv, okopts)
if found_opts: found_opts.show('------ found options ------ ')
if __name__ == '__main__':
test_comopts()
syntax highlighted by Code2HTML, v. 0.9.1