# -*- coding: utf-8 -*- """DPyGetOpt -- Demiurge Python GetOptions Module $Id: DPyGetOpt.py 958 2005-12-27 23:17:51Z fperez $ This module is modeled after perl's Getopt::Long module-- which is, in turn, modeled after GNU's extended getopt() function. Upon instantiation, the option specification should be a sequence (list) of option definitions. Options that take no arguments should simply contain the name of the option. If a ! is post-pended, the option can be negated by prepending 'no'; ie 'debug!' specifies that -debug and -nodebug should be accepted. Mandatory arguments to options are specified using a postpended '=' + a type specifier. '=s' specifies a mandatory string argument, '=i' specifies a mandatory integer argument, and '=f' specifies a mandatory real number. In all cases, the '=' can be substituted with ':' to specify that the argument is optional. Dashes '-' in option names are allowed. If an option has the character '@' postpended (after the argumentation specification), it can appear multiple times within each argument list that is processed. The results will be stored in a list. The option name can actually be a list of names separated by '|' characters; ie-- 'foo|bar|baz=f@' specifies that all -foo, -bar, and -baz options that appear on within the parsed argument list must have a real number argument and that the accumulated list of values will be available under the name 'foo' $Id: DPyGetOpt.py 958 2005-12-27 23:17:51Z fperez $""" #***************************************************************************** # # Copyright (c) 2001 Bill Bumgarner # # # Published under the terms of the MIT license, hereby reproduced: # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. # #***************************************************************************** __author__ = 'Bill Bumgarner ' __license__ = 'MIT' __version__ = '1.2' # Modified to use re instead of regex and regsub modules. # 2001/5/7, Jonathan Hogg import re import string import sys import types arg_error = 'DPyGetOpt Argument Error' spec_error = 'DPyGetOpt Specification Error' term_error = 'DPyGetOpt Termination Error' specificationExpr = re.compile('(?P.)(?P.)(?P@?)') ArgRequired = 'Requires an Argument' ArgOptional = 'Argument Optional' # The types modules is not used for these identifiers because there # is no identifier for 'boolean' or 'generic' StringArgType = 'String Argument Type' IntegerArgType = 'Integer Argument Type' RealArgType = 'Real Argument Type' BooleanArgType = 'Boolean Argument Type' GenericArgType = 'Generic Argument Type' # dictionary of conversion functions-- boolean and generic options # do not accept arguments and do not need conversion functions; # the identity function is used purely for convenience. ConversionFunctions = { StringArgType : lambda x: x, IntegerArgType : string.atoi, RealArgType : string.atof, BooleanArgType : lambda x: x, GenericArgType : lambda x: x, } class DPyGetOpt: def __init__(self, spec = None, terminators = ['--']): """ Declare and intialize instance variables Yes, declaration is not necessary... but one of the things I sorely miss from C/Obj-C is the concept of having an interface definition that clearly declares all instance variables and methods without providing any implementation details. it is a useful reference! all instance variables are initialized to 0/Null/None of the appropriate type-- not even the default value... """ # sys.stderr.write(string.join(spec) + "\n") self.allowAbbreviations = 1 # boolean, 1 if abbreviations will # be expanded self.freeValues = [] # list, contains free values self.ignoreCase = 0 # boolean, YES if ignoring case self.needsParse = 0 # boolean, YES if need to reparse parameter spec self.optionNames = {} # dict, all option names-- value is index of tuple self.optionStartExpr = None # regexp defining the start of an option (ie; '-', '--') self.optionTuples = [] # list o' tuples containing defn of options AND aliases self.optionValues = {} # dict, option names (after alias expansion) -> option value(s) self.orderMixed = 0 # boolean, YES if options can be mixed with args self.posixCompliance = 0 # boolean, YES indicates posix like behaviour self.spec = [] # list, raw specs (in case it must be reparsed) self.terminators = terminators # list, strings that terminate argument processing self.termValues = [] # list, values after terminator self.terminator = None # full name of terminator that ended # option processing # set up defaults self.setPosixCompliance() self.setIgnoreCase() self.setAllowAbbreviations() # parse spec-- if present if spec: self.parseConfiguration(spec) def setPosixCompliance(self, aFlag = 0): """ Enables and disables posix compliance. When enabled, '+' can be used as an option prefix and free values can be mixed with options. """ self.posixCompliance = aFlag self.needsParse = 1 if self.posixCompliance: self.optionStartExpr = re.compile('(--|-)(?P