~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to utilities/script_commands.py

  • Committer: Aaron Bentley
  • Date: 2011-08-04 20:26:07 UTC
  • mto: This revision was merged to the branch mainline in revision 13619.
  • Revision ID: aaron@canonical.com-20110804202607-dudyffsvfhxb7evu
Switch to command-from-function approach.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
import inspect
 
2
from optparse import OptionParser
2
3
 
3
4
 
4
5
class UserError(Exception):
5
6
    pass
6
7
 
7
8
 
 
9
def add_dict(name, **kwargs):
 
10
    def decorator(func):
 
11
        setattr(func, name, kwargs)
 
12
        return func
 
13
    return decorator
 
14
 
 
15
 
 
16
def types(**kwargs):
 
17
    return add_dict('_types', **kwargs)
 
18
 
 
19
def helps(**kwargs):
 
20
    return add_dict('_helps', **kwargs)
 
21
 
 
22
 
 
23
 
 
24
def get_function_parser(function):
 
25
    parser = OptionParser()
 
26
    args, ignore, ignored, defaults = inspect.getargspec(function)
 
27
    for arg in args:
 
28
        arg_type = function._types.get(arg)
 
29
        if arg_type is None:
 
30
            continue
 
31
        arg_help = getattr(function, '_helps', {}).get(arg)
 
32
        if arg_help is not None:
 
33
            arg_help +=' Default: %default.'
 
34
        parser.add_option('--%s' % arg, type=arg_type, help=arg_help)
 
35
    if defaults is not None:
 
36
        defaults_dict = dict(zip(args, defaults))
 
37
        option_defaults = dict(
 
38
            (key, value) for key, value in defaults_dict.items()
 
39
            if parser.defaults.get(key, '') is None)
 
40
        parser.set_defaults(**option_defaults)
 
41
    return parser
 
42
 
 
43
 
8
44
class Command:
9
45
    """Base class for subcommands."""
10
46
 
11
47
    commands = {}
12
48
 
13
49
    @classmethod
14
 
    def parse_args(cls, args):
 
50
    def parse_args(cls, command, args):
15
51
        if len(args) != 0:
16
52
            raise UserError('Too many arguments.')
17
53
        return {}
18
54
 
19
55
    @classmethod
20
 
    def set_defaults(cls, parser):
21
 
        args, ignored, ignored, defaults = inspect.getargspec(cls.run)
22
 
        if defaults is None:
23
 
            return
24
 
        defaults_dict = dict(zip(args, defaults))
25
 
        option_defaults = dict(
26
 
            (key, value) for key, value in defaults_dict.items()
27
 
            if parser.defaults.get(key, '') is None)
28
 
        parser.set_defaults(**option_defaults)
29
 
 
30
 
    @classmethod
31
 
    def run_from_args(cls, cmd_args):
32
 
        parser = cls.get_parser()
33
 
        cls.set_defaults(parser)
 
56
    def run_from_args(cls, command, cmd_args):
 
57
        parser = get_function_parser(command)
34
58
        options, args = parser.parse_args(cmd_args)
35
 
        kwargs = cls.parse_args(args)
 
59
        kwargs = cls.parse_args(command, args)
36
60
        kwargs.update(options.__dict__)
37
 
        cls.run(**kwargs)
 
61
        command(**kwargs)
38
62
 
39
63
    @classmethod
40
64
    def run_subcommand(cls, argv):
46
70
        except KeyError:
47
71
            raise UserError('%s invalid.  Valid commands: %s.' %
48
72
                            (argv[0], ', '.join(cls.commands.keys())))
49
 
        command.run_from_args(argv[1:])
 
73
        cls.run_from_args(command, argv[1:])