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:])
|