mirror of https://github.com/docker/docs.git
60 lines
1.7 KiB
Python
60 lines
1.7 KiB
Python
from __future__ import absolute_import
|
|
from __future__ import unicode_literals
|
|
|
|
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
|