fancyopts.py
author Alexander Solovyov <piranha@piranha.org.ua>
Sun, 31 May 2009 15:04:40 +0300
changeset 0 cbb132cade5c
child 1 64bd6c430858
permissions -rw-r--r--
fancyopts option parser, first iteration

# (c) Alexander Solovyov, 2009, under terms of the new BSD License
'''Fancy option parser
'''

import getopt, types

def fancyopts(args, options):
    '''
    >>> opts = [('l', 'listen', 'localhost',
    ...          'ip to listen on (default: localhost)'),
    ...         ('p', 'port', 8000,
    ...          'port to listen on (default: 8000)'),
    ...         ('d', 'daemonize', False,
    ...          'daemonize process'),
    ...         ('', 'pid-file', '',
    ...          'name of file to write process ID to')]
    >>> print fancyopts(['-l', '0.0.0.0', '--pi', 'test', 'all'], opts)
    ({'pid_file': 'test', 'daemonize': False, 'port': 8000, 'listen': '0.0.0.0'}, ['all'])

    '''
    argmap = {}
    state = {}
    shortlist = ''
    namelist = []

    for short, oname, default, comment in options:
        # change name to match Python styling
        name = oname.replace('-', '_')
        argmap['-' + short] = argmap['--' + oname] = name
        state[name] = default

        # it takes a parameter
        if default not in (None, True, False):
            if short: short += ':'
            if oname: oname += '='
        if short:
            shortlist += short
        if name:
            namelist.append(oname)

    opts, args = getopt.gnu_getopt(args, shortlist, namelist)

    # transfer result to state
    for opt, val in opts:
        name = argmap[opt]
        t = type(state[name])
        if t is types.FunctionType:
            state[name] = state[name](val)
        elif t is types.IntType:
            state[name] = int(val)
        elif t is types.StringType:
            state[name] = val
        elif t is types.ListType:
            state[name].append(val)
        elif t in (types.NoneType, types.BooleanType):
            state[name] = not state[name]

    return state, args

if __name__ == '__main__':
    import doctest
    doctest.testmod()