~launchpad-pqm/launchpad/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import inspect
from optparse import OptionParser


class UserError(Exception):
    pass


def add_dict(name, **kwargs):
    def decorator(func):
        setattr(func, name, kwargs)
        return func
    return decorator


def types(**kwargs):
    return add_dict('_types', **kwargs)

def helps(**kwargs):
    return add_dict('_helps', **kwargs)


def get_function_parser(function):
    """Generate an OptionParser for a function.

    Defaults come from the parameter defaults.
    For every permitted to provide as an option, the type must be specified,
    using the types decorator.
    Help may be specified using the helps decorator.
    """
    parser = OptionParser()
    args, ignore, ignored, defaults = inspect.getargspec(function)
    for arg in args:
        arg_type = function._types.get(arg)
        if arg_type is None:
            continue
        arg_help = getattr(function, '_helps', {}).get(arg)
        if arg_help is not None:
            arg_help +=' Default: %default.'
        parser.add_option('--%s' % arg, type=arg_type, help=arg_help)
    if defaults is not None:
        defaults_dict = dict(zip(args, defaults))
        option_defaults = dict(
            (key, value) for key, value in defaults_dict.items()
            if parser.defaults.get(key, '') is None)
        parser.set_defaults(**option_defaults)
    return parser


def parse_args(command, args):
    """Return the positional arguments as a dict."""
    # TODO: implement!
    if len(args) != 0:
        raise UserError('Too many arguments.')
    return {}


def run_from_args(command, cmd_args):
    """Run a command function using the specified commandline arguments."""
    parser = get_function_parser(command)
    options, args = parser.parse_args(cmd_args)
    kwargs = parse_args(command, args)
    kwargs.update(options.__dict__)
    command(**kwargs)


def run_subcommand(subcommands, argv):
    """Run a subcommand as specified by argv."""
    if len(argv) < 1:
        raise UserError('Must supply a command: %s.' %
                        ', '.join(subcommands.keys()))
    try:
        command = subcommands[argv[0]]
    except KeyError:
        raise UserError('%s invalid.  Valid commands: %s.' %
                        (argv[0], ', '.join(subcommands.keys())))
    run_from_args(command, argv[1:])