Refactor command class hierarchy to remove an unnecessary intermediate base class Command.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
This commit is contained in:
Daniel Nephin 2015-10-05 15:48:35 -04:00
parent 19271898de
commit aefb7a44b2
3 changed files with 49 additions and 45 deletions

View File

@ -1,6 +1,7 @@
from __future__ import absolute_import
from __future__ import unicode_literals
import contextlib
import logging
import os
import re
@ -16,7 +17,6 @@ from .. import config
from ..project import Project
from ..service import ConfigError
from .docker_client import docker_client
from .docopt_command import DocoptCommand
from .utils import call_silently
from .utils import is_mac
from .utils import is_ubuntu
@ -24,40 +24,32 @@ from .utils import is_ubuntu
log = logging.getLogger(__name__)
class Command(DocoptCommand):
base_dir = '.'
def dispatch(self, *args, **kwargs):
try:
super(Command, self).dispatch(*args, **kwargs)
except SSLError as e:
raise errors.UserError('SSL error: %s' % e)
except ConnectionError:
if call_silently(['which', 'docker']) != 0:
if is_mac():
raise errors.DockerNotFoundMac()
elif is_ubuntu():
raise errors.DockerNotFoundUbuntu()
else:
raise errors.DockerNotFoundGeneric()
elif call_silently(['which', 'boot2docker']) == 0:
raise errors.ConnectionErrorDockerMachine()
@contextlib.contextmanager
def friendly_error_message():
try:
yield
except SSLError as e:
raise errors.UserError('SSL error: %s' % e)
except ConnectionError:
if call_silently(['which', 'docker']) != 0:
if is_mac():
raise errors.DockerNotFoundMac()
elif is_ubuntu():
raise errors.DockerNotFoundUbuntu()
else:
raise errors.ConnectionErrorGeneric(self.get_client().base_url)
raise errors.DockerNotFoundGeneric()
elif call_silently(['which', 'boot2docker']) == 0:
raise errors.ConnectionErrorDockerMachine()
else:
raise errors.ConnectionErrorGeneric(self.get_client().base_url)
def perform_command(self, options, handler, command_options):
if options['COMMAND'] in ('help', 'version'):
# Skip looking up the compose file.
handler(None, command_options)
return
project = get_project(
self.base_dir,
get_config_path(options.get('--file')),
project_name=options.get('--project-name'),
verbose=options.get('--verbose'))
handler(project, command_options)
def project_from_options(base_dir, options):
return get_project(
base_dir,
get_config_path(options.get('--file')),
project_name=options.get('--project-name'),
verbose=options.get('--verbose'))
def get_config_path(file_option):

View File

@ -25,9 +25,6 @@ class DocoptCommand(object):
def dispatch(self, argv, global_options):
self.perform_command(*self.parse(argv, global_options))
def perform_command(self, options, handler, command_options):
handler(command_options)
def parse(self, argv, global_options):
options = docopt_full_help(getdoc(self), argv, **self.docopt_options())
command = options['COMMAND']

View File

@ -23,7 +23,9 @@ from ..project import NoSuchService
from ..service import BuildError
from ..service import ConvergenceStrategy
from ..service import NeedsBuildError
from .command import Command
from .command import friendly_error_message
from .command import project_from_options
from .docopt_command import DocoptCommand
from .docopt_command import NoSuchCommand
from .errors import UserError
from .formatter import Formatter
@ -89,6 +91,15 @@ def setup_logging():
logging.getLogger("requests").propagate = False
def setup_console_handler(verbose):
if verbose:
console_handler.setFormatter(logging.Formatter('%(name)s.%(funcName)s: %(message)s'))
console_handler.setLevel(logging.DEBUG)
else:
console_handler.setFormatter(logging.Formatter())
console_handler.setLevel(logging.INFO)
# stolen from docopt master
def parse_doc_section(name, source):
pattern = re.compile('^([^\n]*' + name + '[^\n]*\n?(?:[ \t].*?(?:\n|$))*)',
@ -96,7 +107,7 @@ def parse_doc_section(name, source):
return [s.strip() for s in pattern.findall(source)]
class TopLevelCommand(Command):
class TopLevelCommand(DocoptCommand):
"""Define and run multi-container applications with Docker.
Usage:
@ -130,20 +141,24 @@ class TopLevelCommand(Command):
version Show the Docker-Compose version information
"""
base_dir = '.'
def docopt_options(self):
options = super(TopLevelCommand, self).docopt_options()
options['version'] = get_version_info('compose')
return options
def perform_command(self, options, *args, **kwargs):
if options.get('--verbose'):
console_handler.setFormatter(logging.Formatter('%(name)s.%(funcName)s: %(message)s'))
console_handler.setLevel(logging.DEBUG)
else:
console_handler.setFormatter(logging.Formatter())
console_handler.setLevel(logging.INFO)
def perform_command(self, options, handler, command_options):
setup_console_handler(options.get('--verbose'))
return super(TopLevelCommand, self).perform_command(options, *args, **kwargs)
if options['COMMAND'] in ('help', 'version'):
# Skip looking up the compose file.
handler(None, command_options)
return
project = project_from_options(self.base_dir, options)
with friendly_error_message():
handler(project, command_options)
def build(self, project, options):
"""