import argparse import textwrap class CommandRegistry(type): commands = [] def __init__(cls, name, bases, dict): super().__init__(name, bases, dict) cls.subcommands = [] if 'parent' in dict: dict['parent'].subcommands.append(cls) elif 'name' in dict: CommandRegistry.commands.append(cls) class Command(metaclass=CommandRegistry): arguments = () usage = None help = "" epilog = "" def __init__(self, manager): self.manager = manager self.api = manager.api self.config = manager.config self.db = manager.db def create_parser(self, subparser, parents): doc = self.__doc__ or "" description = textwrap.dedent(doc.strip("\n") or self.help) epilog = textwrap.dedent(self.epilog.strip("\n")) help = self.help or (description and description.splitlines()[0]) command_parser = argparse.ArgumentParser(add_help=False) group = command_parser.add_argument_group("%s options" % self.name) for args, kwargs in self.arguments: group.add_argument(*args, **kwargs) subcommands_parser = argparse.ArgumentParser( add_help=False, usage="%(prog)s " + self.name ) if self.subcommands: subcommand_parser = subcommands_parser.add_subparsers( metavar='SUBCOMMAND', title=None, ) for subcommand_class in self.subcommands: subcommand = subcommand_class(self.manager) subcommand.create_parser(subcommand_parser, [command_parser] + parents) self.parser = subparser.add_parser( self.name, usage=self.usage, help=help, description=description, epilog=epilog, parents=[subcommands_parser, command_parser] + parents, add_help=False, formatter_class=argparse.RawDescriptionHelpFormatter, ) self.parser.set_defaults(run=self.run) def run(self, args): self.parser.print_help() def Arg(*args, **kwargs): return args, kwargs