# Copyright 2011 Canonical Ltd. # # This file is part of u1db. # # u1db is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation. # # u1db is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with u1db. If not, see . """Command infrastructure for u1db""" import argparse import inspect class CommandGroup(object): """A collection of commands.""" def __init__(self, description=None): self.commands = {} self.description = description def register(self, cmd): """Register a new command to be incorporated with this group.""" self.commands[cmd.name] = cmd def make_argparser(self): """Create an argparse.ArgumentParser""" parser = argparse.ArgumentParser(description=self.description) subs = parser.add_subparsers(title='commands') for name, cmd in sorted(self.commands.iteritems()): sub = subs.add_parser(name, help=cmd.__doc__) sub.set_defaults(subcommand=cmd) cmd._populate_subparser(sub) return parser def run_argv(self, argv, stdin, stdout, stderr): """Run a command, from a sys.argv[1:] style input.""" parser = self.make_argparser() args = parser.parse_args(argv) cmd = args.subcommand(stdin, stdout, stderr) params, _, _, _ = inspect.getargspec(cmd.run) vals = [] for param in params[1:]: vals.append(getattr(args, param)) return cmd.run(*vals) class Command(object): """Definition of a Command that can be run. :cvar name: The name of the command, so that you can run 'u1db-client '. """ name = None def __init__(self, stdin, stdout, stderr): self.stdin = stdin self.stdout = stdout self.stderr = stderr @classmethod def _populate_subparser(cls, parser): """Child classes should override this to provide their arguments.""" raise NotImplementedError(cls._populate_subparser) def run(self, *args): """This is where the magic happens. Subclasses should implement this, requesting their specific arguments. """ raise NotImplementedError(self.run)