#-----------------------------------------------------------------||||||||||||--
# Name: argTools.py
# Purpose: arg tools, flags and command line args
#
# Authors: Christopher Ariza
#
# Copyright: (c) 2001-2006 Christopher Ariza
# License: GPL
#-----------------------------------------------------------------||||||||||||--
import types
from athenaCL.libATH import drawer
from athenaCL.libATH import typeset
_MOD = 'argTools.py'
#-----------------------------------------------------------------||||||||||||--
def parseFlags(argv, flags, posStart=1, spaceLimit=0):
"""read args flags into a list of flags
flags may all be 2 char '-f' like flags
longer flags are accepted, but second priority in searching
more than one of the same flag can be used
values con be attached to flag, or be the next arg
posStart is the index in the arg list to start (usually not 0)
spaceLimit: if args are spce delimited or flag delimited
if true, only one space will be allowed after a flag; and this
will end the accumlation of arg data; extra args
will be stored under None keys; if false, all data after the flag
until the next flag, will be accumlated under that flag
initial data (w/o flag) is stored uner None: difference is that w/
spaceLimt==1, there can be multipe None entries
flags that dont have values get a None
values that dont have flags:
after first flag, all values are gathered together until end
or next flag
return a list of flag, value pairs.
"""
# flags me be ref dict with doc vaules; check type
if isinstance(flags, types.DictionaryType):
flagTemp = []
for entry in flags.keys():
flagTemp = flagTemp + list(entry) #str, tuple convert to list
flags = flagTemp
#for flag in flags:
#assert len(flag) == 2 # all falgs must be 2 chars
parsedArgs = []
unflaged = [] # list of strings not flaged
if len(argv) > posStart: # the first is the name of module
i = posStart
while 1:
flagSymbol = None
flagValue = None
argRemainder = ''
extraData = []
arg = argv[i] # get text chunk from list of strings
# will check for 2 character flags first
if arg[:2] in flags: # session type
flagSymbol = arg[:2]
if arg[2:] != '':
extraData.append(arg[2:])
elif arg in flags: # full word arg
flagSymbol = arg
else: # not a flag; store under None
extraData.append(arg)
# accumate all data, if no spaceLimit, or if no flag found
if not spaceLimit or flagSymbol==None:
while 1: # check what follows, increment i
# if its not a flag, or doesnt start w/ a flag, append it
if (i+1 < len(argv) and argv[i+1] != '' and
argv[i+1][:2] not in flags and argv[i+1] not in flags):
# next arg not a flag
extraData.append(argv[i+1])
i = i + 1 # move forward one b/c it was value
else: break
else: # space limit, only check one in advance
if extraData == []: # have not found any data attached to flag
if (i+1 < len(argv) and argv[i+1] != '' and
argv[i+1][:2] not in flags and argv[i+1] not in flags):
extraData.append(argv[i+1])
i = i + 1
else: # already have some data w/ this flag, assume that is all
print 'spaceLimit, no data to add', flagSymbol
pass
flagValue = ' '.join(extraData) # put space between args
flagValue = flagValue.strip() # remove outer space
# remove trailing space
if flagValue == '':
flagValue = None
parsedArgs.append((flagSymbol, flagValue))
i = i + 1
if i >= len(argv):
break
return parsedArgs
#-----------------------------------------------------------------||||||||||||--
def strongType(usrArgs, argTypes, defaultArgs=[], argCountOffset=0):
"""checks raw arg type and number, one level deep
(does not recurse into list)
will supply defaults if missing args after last given and
self.defaultArgs defined
two arguments required, both lists:
args = a list of arguments, of proper python data types
argTypes = list of one-level deap types, specified w/ strings
'list', 'num', 'float', 'int', 'str'; see drawer.py
one optional args
defaultArgs = list of default args to substitute
returns: newArgs, ok, msg
"""
argCount = len(argTypes)
if len(usrArgs) < argCount:
# try to get from defaults
if len(defaultArgs) == argCount: # defaults exits (default is 0)
for retrieve in defaultArgs[len(usrArgs):]:
usrArgs.append(retrieve) # add missing to end
#print 'argTools.py: adding default', retrieve, defaultArgs
else: # nothing we can do: failure
msg = ('incorrect number of arguments; enter %i arguments.' %
(argCount + argCountOffset)) # add incase if name offset
return usrArgs, 0, msg
elif len(usrArgs) > argCount:
#print _MOD, len(usrArgs), argCount
msg = 'too many arguments; enter %i arguments.' % (argCount +
argCountOffset)
return usrArgs, 0, msg
for pos in range(0, argCount):
argTest = usrArgs[pos]
# can be [list, num, float, int, str]
typeCandidates = argTypes[pos]
if not drawer.isList(typeCandidates):
typeCandidates = [typeCandidates,] # add to list
for type in typeCandidates:
if type == 'list' and drawer.isList(argTest):
match = 1
break
elif type == 'num' and drawer.isNum(argTest):
match = 1
break
elif type == 'float' and drawer.isFloat(argTest):
match = 1
break
elif type == 'int' and drawer.isInt(argTest):
match = 1
break
elif type == 'str' and drawer.isStr(argTest):
match = 1
break
else: # dont break; need to through other possbilities
match = 0
# should covnert types to better strings
if match == 0:
msg = ('wrong type of data used as an argument. replace %s with a %s argument type.' % (repr(typeset.anyDataToStr(argTest)),
# provide 'or' to show that any type in candidate is good
drawer.typeListAsStr(typeCandidates, 'or')))
return usrArgs, 0, msg
# all good
return usrArgs, 1, ''
#-----------------------------------------------------------------||||||||||||--
class ArgOps:
"""object to handle parsing of commandline arguments
given w/o commas, space delimited, as used in Interpreter
this arg lists only use positional values; not flags are permitted
optional argument may follow required ones"""
def __init__(self, argStr, stripComma='noStrip'):
self.argStr = argStr.strip() # clear trailing white space
self.argList = argStr.split() # split w/ spces
# strip trailing comma
if stripComma != 'noStrip':
counter = 0
for entry in self.argList:
if entry[-1] == ',': # only remove comma of last line
self.argList[counter] = entry[:-1]
counter = counter + 1
def get(self, index, sumRange='single', evaluate='off', addSpace='noSpace'):
"""returns args as strings
sum range allowes gather all space-delimited arg positions into one arg
addSpace can be used to remove spaces (default) or keep
this is necessary when taking all values
if no arg exists for a given index, returns None on error or no arg
"""
if len(self.argList) == 0: return None
if index >= len(self.argList): return None
if sumRange == 'single':
output = self.argList[index]
elif sumRange == 'end':
output = []
for i in range(index, len(self.argList)):
output.append(self.argList[i])
if addSpace != 'noSpace': # add space
output = ' '.join(output)
else:
output = ''.join(output)
if evaluate == 'off':
return output
else:
try:
return eval(output)
except: # should report this error in a better fashion
return None
def list(self, index, sumRange='single', evaluate='off'):
"""returns args as a list of strings
index: arg number to start with
sumRange: either single (only the index given)
or end (from index to end of args)
evaluate: when on, evaluates each member of resultant list
"""
if len(self.argList) == 0:
return None
if index >= len(self.argList):
return None
if sumRange == 'single':
output = [self.argList[index],]
elif sumRange == 'end':
output = []
for i in range(index, len(self.argList)):
output.append(self.argList[i])
# final changes and returns
if evaluate == 'off':
return output
else: # evaluate each member of the list, not entire list
for i in range(0,len(output)):
try:
output[i] = eval(output[i])
except:
return None
return output
#-----------------------------------------------------------------||||||||||||--
# version object for checking
class Version:
"""simple object to handle checking and evaluating versions"""
def __init__(self, vStr):
"""split string, remove beta or other tags, place into local dict
a beta tag is not enough to distinguish versions; a beta should
evaluate the same as the normal version
date distinctions only evaluated if present in both objects"""
vList = vStr.split('.')
if len(vList) >= 3:
a, b, c = vList[0], vList[1], vList[2]
# c may have a -beta tag on it, must remove
cTest = c.split('-') # get first item before
if len(cTest) >= 2:
c, self.betaTag = cTest[0], cTest[1]
else:
c = cTest[0]
self.betaTag = None
# assign all to point
self.point = int(a), int(b), int(c)
# get date info
if len(vList) >= 6:
self.date = int(vList[3]), int(vList[4]), int(vList[5])
else:
self.date = None
def repr(self, format='dot', date=1):
if self.date != None:
vDate = '%s.%.2i.%.2i' % self.date
else:
vDate = None
if self.betaTag == None:
vPoint = '%s.%s.%s' % self.point
else: # add beta tage
vPoint = '%s.%s.%s-%s' % (self.point[0], self.point[1],
self.point[2], self.betaTag)
# check to see if date should be provided
if vDate != None and date == 1:
if format == 'dot':
return '%s.%s' % (vPoint, vDate)
elif format == 'human':
return '%s (%s)' % (vPoint, vDate)
else:
return vPoint
def __str__(self):
return self.repr() # get default
def __eq__(self, other):
"""only compare date if both have set date"""
if other == None: return 0
if self.date == None or other.date == None:
if self.point == other.point: return 1
else: return 0
else: # both have date
if self.point == other.point:
if self.date == other.date:
return 1
return 0
def __ne__(self, other):
"""only compare date if both have set date"""
if other == None: return 1
if self.date == None or other.date == None:
if self.point != other.point: return 1
else: return 0
else: # both have date
if self.point != other.point:
if self.date != other.date:
return 1
return 0
def __lt__(self, other):
"""only compare date if both have set date"""
if self.date == None or other.date == None:
if self.point < other.point: return 1
else: return 0
else:
if self.point <= other.point: # lt or equal
if self.date < other.date:
return 1
return 0
def __le__(self, other):
"""only compare date if both have set date"""
if self.date == None or other.date == None:
if self.point <= other.point: return 1
else: return 0
else:
if self.point <= other.point:
if self.date <= other.date:
return 1
return 0
def __gt__(self, other):
"""only compare date if both have set date"""
if self.date == None or other.date == None:
if self.point > other.point: return 1
else: return 0
else:
if self.point >= other.point: # gt or equal
if self.date > other.date:
return 1
return 0
def __ge__(self, other):
"""only compare date if both have set date"""
if self.date == None or other.date == None:
if self.point >= other.point: return 1
else: return 0
else:
if self.point >= other.point:
if self.date >= other.date:
return 1
return 0
|