소스 검색

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

Signed-off-by: Daniel Nephin <[email protected]>
Daniel Nephin 10 년 전
부모
커밋
aefb7a44b2
3개의 변경된 파일51개의 추가작업 그리고 47개의 파일을 삭제
  1. 26 34
      compose/cli/command.py
  2. 0 3
      compose/cli/docopt_command.py
  3. 25 10
      compose/cli/main.py

+ 26 - 34
compose/cli/command.py

@@ -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()
[email protected]
+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)
-
-    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)
+                raise errors.DockerNotFoundGeneric()
+        elif call_silently(['which', 'boot2docker']) == 0:
+            raise errors.ConnectionErrorDockerMachine()
+        else:
+            raise errors.ConnectionErrorGeneric(self.get_client().base_url)
+
+
+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):

+ 0 - 3
compose/cli/docopt_command.py

@@ -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']

+ 25 - 10
compose/cli/main.py

@@ -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'))
+
+        if options['COMMAND'] in ('help', 'version'):
+            # Skip looking up the compose file.
+            handler(None, command_options)
+            return
 
-        return super(TopLevelCommand, self).perform_command(options, *args, **kwargs)
+        project = project_from_options(self.base_dir, options)
+        with friendly_error_message():
+            handler(project, command_options)
 
     def build(self, project, options):
         """