# HG changeset patch # User Daniele Nicolodi # Date 1321572211 -3600 # Node ID 421bcbd15282de861376edf80ac802eae0c2d3db # Parent 5b1649631ceea5bd2c7a6c699542dd59f83450ef Improve command line interface. diff -r 5b1649631cee -r 421bcbd15282 src/ltpdarepo/admin.py --- a/src/ltpdarepo/admin.py Thu Nov 17 14:32:56 2011 +0100 +++ b/src/ltpdarepo/admin.py Fri Nov 18 00:23:31 2011 +0100 @@ -28,13 +28,6 @@ HAS_SQL_ALCHEMY = False -class verbosity(argparse.Action): - def __call__(self, *args, **kwargs): - # increse logging level - logger = logging.getLogger('ltpdarepo') - logger.setLevel(logger.level - 10) - - def _bool(value): # parse string into boolean value if value not in ('yes', 'no', 'true', 'false'): @@ -42,44 +35,64 @@ return value in ('yes', 'true') +class ArgumentParser(argparse.ArgumentParser): + def _check_value(self, action, value): + if action.choices is not None and value not in action.choices: + self.error("unknown command %s" % value) + + def print_help(self, name=None, out=sys.stdout): + + commands = self._subparsers._group_actions[0].choices + options = self._action_groups[1]._group_actions + + if name is not None: + command = commands.get(name, None) + if command is None: + commands['help'].error("unknown command %s" % name) + print >>out, commands[name].format_help().strip() + return + + print >>out, self.description + print >>out, self.format_usage().strip() + print >>out, "" + print >>out, "commands:" + for name, cmd in sorted(commands.iteritems()): + doc = '' + if cmd.description: + doc = cmd.description.splitlines()[0] + print >>out, " %-13s %s" % (name, doc) + print >>out, "" + print >>out, "options:" + for opt in options: + print >>out, " %-13s %s" % (", ".join(opt.option_strings), opt.help) + print >>out, "" + + class Commands(object): def __init__(self): - self.parser = argparse.ArgumentParser(add_help=False) - self.commands = self.parser.add_subparsers(metavar='command') - options = self.parser.add_argument_group('options') - options.add_argument('-v', '--verbose', action=verbosity, - nargs=0, dest=argparse.SUPPRESS, - help='increase verbosity') + self.parser = ArgumentParser(add_help=False, + description='LTPDA Repository administration tool') + self.commands = self.parser.add_subparsers(metavar='command', + parser_class=argparse.ArgumentParser) + + self.parser.add_argument('-v', '--verbose', action='count', + dest='verbosity', + help='increase verbosity. may be specified multiple times') - def add(self, func, name=None): + self.parser.add_argument('-h', '--help', action='help', + help='show this help message') + + def add(self, func, name=None, help=None): name = name or func.__name__ - desc = func.__doc__ or ' ' - parser = self.commands.add_parser(name, - help=desc.splitlines()[0], - description=desc, - add_help=False) - parser.set_defaults(command=func) + desc = help or func.__doc__ + parser = self.commands.add_parser(name, help=help, + description=desc, add_help=False) + parser.set_defaults(_command=func) return parser def parse(self, *args): return self.parser.parse_args(*args) - def dispatch(self): - args = vars(self.parser.parse_args()) - command = args.pop('command') - try: - command(**args) - except Exception: - import traceback - sys.stderr.write(traceback.format_exc()) - sys.exit(1) - - def __iter__(self): - return iter(sorted(self.commands.choices.keys())) - - def __getitem__(self, name): - return self.commands.choices[name] - class Application(ltpdarepo.Application): @@ -98,7 +111,7 @@ def __getattr__(self, name): if name in self.config: return self.config[name] - return self[name] + return self.__dict__[name] def connect(self, **kwargs): # open connection to the database @@ -122,6 +135,12 @@ def dispatch(self): args = vars(self.commands.parser.parse_args()) + # verbosity + verbosity = args.pop('verbosity') + if verbosity: + logger = logging.getLogger('ltpdarepo') + logger.setLevel(logger.level - 10 * verbosity) + # common parameters username = args.pop('_username', None) if username: @@ -131,31 +150,17 @@ self._password = password # run command - command = args.pop('command') + command = args.pop('_command') command(self, **args) - def help(self, name=None, out=sys.stderr): - """provide commands help""" - - if name is not None: - print >>out, self.commands[name].format_help().strip() - return - - print >>out, "LTPDA Repository administration tool" - print >>out, self.commands.parser.format_usage().strip() - print >>out, "" - print >>out, "commands:" - for cmd in self.commands: - doc = self.commands[cmd].description or ' ' - print >>out, " %-15s %s" % (cmd, doc.splitlines()[0]) - print >>out, "" - print >>out, "options:" - print >>out, " %-15s %s" % ("-v, --verbose", "increase verbosity. may be specified multiple times") - print >>out, "" + def help(self, command=None): + """show this help message or given command help """ + self.commands.parser.print_help(command) + self.commands.parser.exit() cmd = commands.add(help) - cmd.add_argument('name', nargs='?', help='command', metavar='NAME') + cmd.add_argument('command', nargs='?', metavar='COMMAND') def user(self, username):