1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- from inspect import getdoc
- from docopt import docopt
- from docopt import DocoptExit
- def docopt_full_help(docstring, *args, **kwargs):
- try:
- return docopt(docstring, *args, **kwargs)
- except DocoptExit:
- raise SystemExit(docstring)
- class DocoptDispatcher(object):
- def __init__(self, command_class, options):
- self.command_class = command_class
- self.options = options
- def parse(self, argv):
- command_help = getdoc(self.command_class)
- options = docopt_full_help(command_help, argv, **self.options)
- command = options['COMMAND']
- if command is None:
- raise SystemExit(command_help)
- handler = get_handler(self.command_class, command)
- docstring = getdoc(handler)
- if docstring is None:
- raise NoSuchCommand(command, self)
- command_options = docopt_full_help(docstring, options['ARGS'], options_first=True)
- return options, handler, command_options
- def get_handler(command_class, command):
- command = command.replace('-', '_')
- # we certainly want to have "exec" command, since that's what docker client has
- # but in python exec is a keyword
- if command == "exec":
- command = "exec_command"
- if not hasattr(command_class, command):
- raise NoSuchCommand(command, command_class)
- return getattr(command_class, command)
- class NoSuchCommand(Exception):
- def __init__(self, command, supercommand):
- super(NoSuchCommand, self).__init__("No such command: %s" % command)
- self.command = command
- self.supercommand = supercommand
|