command-line parser

Ben Wolfson rumjuggler at cryptarchy.org
Sun Jun 18 17:36:29 EDT 2000


"""
arglist.py

A utility for retrieving arguments passed via the command line.
"""

class Error(Exception):
    pass

    
class Arguments:
    """
Instantiate with tuples of acceptable options.  Tuples should have the form

    (short_form, long_form, accepts_value, default_value)

Either short_form or long_form can be None or a false value, if there is no
short
or long equivalent of the option, but not both (obviously).  If
accepts_value is true
and default_value is None, the instance will assume that a value is
necessary, and
raise Error if the option but no value is present.  Short_form and
long_form should
_not_ be passed with leading dashes.

__getattr__ is used to find out if an option is passed.  If the instance is
instantiated as

>>> arg = arglist.Arguments(
        ('h', 'help', None, None),
        ('p', 'port', 1, 5555),
        ('l', 'lalala', 1, None),
        ('a', 'anotheropt', 1, 21)
        )

and the command line options are --port -l --anotheropt=haha

>>> arg.process(['--port', '-l:2', '--anotheropt=haha'])

then the following should result:

>>> arg.h
>>> print arg.h
None
>>> arg.help
>>> print arg.help
None
>>> arg.port
5555
>>> arg.p
5555
>>> arg.l
'2'
>>> arg.lalala
'2'
>>> arg.a
'haha'
>>> arg.anotheropt
'haha'

It is possible to verify that arguments are a certain type using
__setattr__.
To verify that the argument to -a or --anotheropt is an int, you would do:

arg.a = int

This will raise a SystemExit exception if arg.a cannot be converted to an
int using the function int().
"""

    class Option:
        def __init__(self, opt):
            if '=' in opt:
                opt, self.arg = opt.split('=',2)
            elif ':' in opt:
                opt, self.arg = opt.split(':',2)
            else:
                self.arg = None
            if opt[:2] == '--':
                self.option = opt[2:]
            else:
                self.option = opt[1:]
                
    def __init__(self, *args):
        self.__dict__['dict'] = {}
        for short, long, hasvalue, default in args:
            if short and long:
                self.dict[short] = self.dict[long] = [hasvalue, default]
            elif short:
                self.dict[short] = [hasvalue, default]
            elif long:
                self.dict[long] = [hasvalue, default]
            else:
                raise Error, "Option must have either a short or a long
key"
        self.__dict__['nonopts'] = []
        
    def process(self, options):
        dict = self.dict
        for i in range(len(options)):
            if options[i][0] <> '-':
                self.nonopts.append(options[i])
                del options[i]
        for opt in map(Arguments.Option, options):
            option = opt.option
            if not self.dict.has_key(option):
                raise Error, "Unrecognized option %s" % option
            hasvalue, default = dict[option]
            if not hasvalue:
                dict[option][1] = default or 1
            else:
                if opt.arg is None:
                    if default is None:
                        raise Error, "Value must be provided for option %s"
% option
                    else:
                        dict[option][1] = default
                else:
                    dict[option][1] = opt.arg
    def get_nonopts(self):
        return self.nonopts
    def __getattr__(self, key):
        dict = self.dict
        if not dict.has_key(key):
            raise Error, 'No option %s' % key
        return dict[key][1]
    def __setattr__(self, key, _type):
        dict = self.dict
        if not dict.has_key(key):
            raise Error, 'No option %s' % key
        value = dict[key][1]
        try:
            _type(value)
        except ValueError:
            raise SystemExit
        except TypeError:
            raise SystemExit




More information about the Python-list mailing list