|
@@ -7,6 +7,7 @@ from collections import namedtuple |
|
|
|
|
|
|
|
|
__all__ = [ |
|
|
__all__ = [ |
|
|
'command', |
|
|
'command', |
|
|
|
|
|
'subcommand', |
|
|
'param', |
|
|
'param', |
|
|
'Application' |
|
|
'Application' |
|
|
] |
|
|
] |
|
@@ -15,33 +16,35 @@ class CommandLine(type): |
|
|
""" |
|
|
""" |
|
|
Meta class that enables declarative command definitions |
|
|
Meta class that enables declarative command definitions |
|
|
""" |
|
|
""" |
|
|
def __new__(cls, name, bases, attrs): |
|
|
|
|
|
instance = super(CommandLine, cls).__new__(cls, name, bases, attrs) |
|
|
|
|
|
|
|
|
def __new__(mcs, name, bases, attrs): |
|
|
|
|
|
instance = super(CommandLine, mcs).__new__(mcs, name, bases, attrs) |
|
|
subcommands = [] |
|
|
subcommands = [] |
|
|
main_command = None |
|
|
main_command = None |
|
|
for name, member in attrs.iteritems(): |
|
|
for name, member in attrs.iteritems(): |
|
|
if hasattr(member, "command"): |
|
|
if hasattr(member, "command"): |
|
|
main_command = member |
|
|
main_command = member |
|
|
# else if member.params: |
|
|
|
|
|
# subcommands.append(member) |
|
|
|
|
|
parser = None |
|
|
|
|
|
|
|
|
elif hasattr(member, "subcommand"): |
|
|
|
|
|
subcommands.append(member) |
|
|
|
|
|
main_parser = None |
|
|
|
|
|
def add_arguments(parser, params): |
|
|
|
|
|
""" |
|
|
|
|
|
Adds parameters to the parser |
|
|
|
|
|
""" |
|
|
|
|
|
for parameter in params: |
|
|
|
|
|
parser.add_argument(*parameter.args, **parameter.kwargs) |
|
|
if main_command: |
|
|
if main_command: |
|
|
parser = ArgumentParser(*main_command.command.args, **main_command.command.kwargs) |
|
|
|
|
|
for param in main_command.params: |
|
|
|
|
|
parser.add_argument(*param.args, **param.kwargs) |
|
|
|
|
|
|
|
|
main_parser = ArgumentParser(*main_command.command.args, **main_command.command.kwargs) |
|
|
|
|
|
add_arguments(main_parser, main_command.params) |
|
|
|
|
|
subparsers = None |
|
|
|
|
|
if len(subcommands): |
|
|
|
|
|
subparsers = main_parser.add_subparsers() |
|
|
|
|
|
for sub in subcommands: |
|
|
|
|
|
parser = subparsers.add_parser(*sub.subcommand.args, **sub.subcommand.kwargs) |
|
|
|
|
|
parser.set_defaults(run=sub) |
|
|
|
|
|
add_arguments(parser, sub.params) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# subparsers = None |
|
|
|
|
|
# if subcommands.length: |
|
|
|
|
|
# subparsers = parser.add_subparsers() |
|
|
|
|
|
# |
|
|
|
|
|
# for command in subcommands: |
|
|
|
|
|
# |
|
|
|
|
|
# for param in main_command.params: |
|
|
|
|
|
# parser.add_argument(*param.args, **param.kwargs) |
|
|
|
|
|
|
|
|
|
|
|
instance.parser = parser |
|
|
|
|
|
instance.main = main_command |
|
|
|
|
|
|
|
|
instance.__parser__ = main_parser |
|
|
|
|
|
instance.__main__ = main_command |
|
|
return instance |
|
|
return instance |
|
|
|
|
|
|
|
|
values = namedtuple('__meta_values', 'args, kwargs') |
|
|
values = namedtuple('__meta_values', 'args, kwargs') |
|
@@ -53,29 +56,39 @@ class metarator(object): |
|
|
def __init__(self, *args, **kwargs): |
|
|
def __init__(self, *args, **kwargs): |
|
|
self.values = values._make((args, kwargs)) |
|
|
self.values = values._make((args, kwargs)) |
|
|
|
|
|
|
|
|
def metarate(self, f, name='values'): |
|
|
|
|
|
setattr(f, name, self.values) |
|
|
|
|
|
return f |
|
|
|
|
|
|
|
|
def metarate(self, func, name='values'): |
|
|
|
|
|
""" |
|
|
|
|
|
Set the values object to the function object's namespace |
|
|
|
|
|
""" |
|
|
|
|
|
setattr(func, name, self.values) |
|
|
|
|
|
return func |
|
|
|
|
|
|
|
|
def __call__(self, f): |
|
|
|
|
|
return self.metarate(f) |
|
|
|
|
|
|
|
|
def __call__(self, func): |
|
|
|
|
|
return self.metarate(func) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class command(metarator): |
|
|
class command(metarator): |
|
|
""" |
|
|
""" |
|
|
Used to decorate the main entry point |
|
|
Used to decorate the main entry point |
|
|
""" |
|
|
""" |
|
|
def __call__(self, f): |
|
|
|
|
|
return self.metarate(f, name='command') |
|
|
|
|
|
|
|
|
def __call__(self, func): |
|
|
|
|
|
return self.metarate(func, name='command') |
|
|
|
|
|
|
|
|
|
|
|
class subcommand(metarator): |
|
|
|
|
|
""" |
|
|
|
|
|
Used to decorate the subcommands |
|
|
|
|
|
""" |
|
|
|
|
|
def __call__(self, func): |
|
|
|
|
|
return self.metarate(func, name='subcommand') |
|
|
|
|
|
|
|
|
class param(metarator): |
|
|
class param(metarator): |
|
|
""" |
|
|
""" |
|
|
Use this decorator instead of `ArgumentParser.add_argument`. |
|
|
Use this decorator instead of `ArgumentParser.add_argument`. |
|
|
""" |
|
|
""" |
|
|
def __call__(self, f): |
|
|
|
|
|
f.params = f.params if hasattr(f, 'params') else [] |
|
|
|
|
|
f.params.append(self.values) |
|
|
|
|
|
return f |
|
|
|
|
|
|
|
|
def __call__(self, func): |
|
|
|
|
|
func.params = func.params if hasattr(func, 'params') else [] |
|
|
|
|
|
func.params.append(self.values) |
|
|
|
|
|
return func |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Application(object): |
|
|
class Application(object): |
|
@@ -86,10 +99,16 @@ class Application(object): |
|
|
__metaclass__ = CommandLine |
|
|
__metaclass__ = CommandLine |
|
|
|
|
|
|
|
|
def parse(self, argv): |
|
|
def parse(self, argv): |
|
|
return self.parser.parse_args(argv) |
|
|
|
|
|
|
|
|
""" |
|
|
|
|
|
Simple method that delegates to the ArgumentParser |
|
|
|
|
|
""" |
|
|
|
|
|
return self.__parser__.parse_args(argv) |
|
|
|
|
|
|
|
|
def run(self, args): |
|
|
def run(self, args): |
|
|
|
|
|
""" |
|
|
|
|
|
Runs the main command or sub command based on user input |
|
|
|
|
|
""" |
|
|
if hasattr(args, 'run'): |
|
|
if hasattr(args, 'run'): |
|
|
args.run(args) |
|
|
|
|
|
|
|
|
args.run(self, args) |
|
|
else: |
|
|
else: |
|
|
self.main(args) |
|
|
|
|
|
|
|
|
self.__main__(args) |