Repository: mesos
Updated Branches:
  refs/heads/master 5d77c5bcb -> 1cdd962bc


CLI: Renamed `lib/mesos` directory to `lib/cli`.

This renames the `src/cli_new/lib/mesos` directory in order to avoid
name clashes with the Python Scheduler/Executor module.  Currently
both modules are imported as `mesos`.  This changes the CLI's
name to `cli` instead.

This will eventually allow the two modules to be merged into one.

Review: https://reviews.apache.org/r/58248/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/f130a567
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/f130a567
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/f130a567

Branch: refs/heads/master
Commit: f130a567d89cd1147d8c75d15963f88d3bb964e6
Parents: 5d77c5b
Author: Eric Chung <[email protected]>
Authored: Thu Apr 6 17:42:35 2017 -0700
Committer: Joseph Wu <[email protected]>
Committed: Thu Apr 6 17:56:47 2017 -0700

----------------------------------------------------------------------
 src/cli_new/bin/config.py                 |   2 +-
 src/cli_new/bin/main.py                   |  22 ++--
 src/cli_new/lib/cli/__init__.py           |  23 ++++
 src/cli_new/lib/cli/docopt.py             |  90 +++++++++++++
 src/cli_new/lib/cli/exceptions.py         |  25 ++++
 src/cli_new/lib/cli/plugins/__init__.py   |  22 ++++
 src/cli_new/lib/cli/plugins/base.py       | 176 +++++++++++++++++++++++++
 src/cli_new/lib/cli/util.py               | 151 +++++++++++++++++++++
 src/cli_new/lib/mesos/__init__.py         |  23 ----
 src/cli_new/lib/mesos/docopt.py           |  90 -------------
 src/cli_new/lib/mesos/exceptions.py       |  25 ----
 src/cli_new/lib/mesos/plugins/__init__.py |  22 ----
 src/cli_new/lib/mesos/plugins/base.py     | 176 -------------------------
 src/cli_new/lib/mesos/util.py             | 151 ---------------------
 14 files changed, 499 insertions(+), 499 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/f130a567/src/cli_new/bin/config.py
----------------------------------------------------------------------
diff --git a/src/cli_new/bin/config.py b/src/cli_new/bin/config.py
index 274f8c6..2f77dc4 100644
--- a/src/cli_new/bin/config.py
+++ b/src/cli_new/bin/config.py
@@ -24,7 +24,7 @@ import json
 import os
 import sys
 
-from mesos.exceptions import CLIException
+from cli.exceptions import CLIException
 
 
 # There is no version module included in this package. However,

http://git-wip-us.apache.org/repos/asf/mesos/blob/f130a567/src/cli_new/bin/main.py
----------------------------------------------------------------------
diff --git a/src/cli_new/bin/main.py b/src/cli_new/bin/main.py
index bbfb52c..efeca6e 100644
--- a/src/cli_new/bin/main.py
+++ b/src/cli_new/bin/main.py
@@ -21,10 +21,10 @@ This is the main executable of the mesos-cli.
 import sys
 
 import config
-import mesos
+import cli
 
-from mesos.docopt import docopt
-from mesos.exceptions import CLIException
+from cli.docopt import docopt
+from cli.exceptions import CLIException
 
 
 VERSION = "Mesos " + config.VERSION + " CLI"
@@ -63,11 +63,11 @@ def autocomplete(cmds, plugins, current_word, argv):
         argv = argv[1:]
 
     comp_words = list(cmds.keys()) + ["help"]
-    comp_words = mesos.util.completions(comp_words, current_word, argv)
+    comp_words = cli.util.completions(comp_words, current_word, argv)
     if comp_words != None:
         return (option, comp_words)
 
-    plugin = mesos.util.get_module(plugins, argv[0])
+    plugin = cli.util.get_module(plugins, argv[0])
     plugin_class = getattr(plugin, plugin.PLUGIN_CLASS)
 
     return plugin_class(config).__autocomplete_base__(current_word, argv[1:])
@@ -79,18 +79,18 @@ def main(argv):
     """
 
     # Initialize the various plugins.
-    plugins = mesos.util.import_modules(config.PLUGINS, "plugins")
+    plugins = cli.util.import_modules(config.PLUGINS, "plugins")
 
     cmds = {
-        mesos.util.get_module(plugins, plugin).PLUGIN_NAME:
-        mesos.util.get_module(plugins, plugin).SHORT_HELP
+        cli.util.get_module(plugins, plugin).PLUGIN_NAME:
+        cli.util.get_module(plugins, plugin).SHORT_HELP
         for plugin in plugins.keys()
     }
 
     # Parse all incoming arguments using docopt.
     command_strings = ""
     if cmds != {}:
-        command_strings = mesos.util.format_commands_help(cmds)
+        command_strings = cli.util.format_commands_help(cmds)
     usage = USAGE.format(commands=command_strings)
 
     arguments = docopt(usage, argv=argv, version=VERSION, options_first=True)
@@ -123,7 +123,7 @@ def main(argv):
     # supplied command and its subcommands.
     elif cmd == "help":
         if len(argv) > 0 and argv[0] in cmds:
-            plugin = mesos.util.get_module(plugins, argv[0])
+            plugin = cli.util.get_module(plugins, argv[0])
             plugin_class = getattr(plugin, plugin.PLUGIN_CLASS)
             plugin_class(config).main(argv[1:] + ["--help"])
         else:
@@ -131,7 +131,7 @@ def main(argv):
 
     # Run the command through its plugin.
     elif cmd in cmds.keys():
-        plugin = mesos.util.get_module(plugins, cmd)
+        plugin = cli.util.get_module(plugins, cmd)
         plugin_class = getattr(plugin, plugin.PLUGIN_CLASS)
         plugin_class(config).main(argv)
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/f130a567/src/cli_new/lib/cli/__init__.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/__init__.py b/src/cli_new/lib/cli/__init__.py
new file mode 100644
index 0000000..f4fc3f1
--- /dev/null
+++ b/src/cli_new/lib/cli/__init__.py
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Mesos Module
+"""
+
+from . import exceptions
+from . import plugins
+from . import util

http://git-wip-us.apache.org/repos/asf/mesos/blob/f130a567/src/cli_new/lib/cli/docopt.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/docopt.py b/src/cli_new/lib/cli/docopt.py
new file mode 100644
index 0000000..86a4e9c
--- /dev/null
+++ b/src/cli_new/lib/cli/docopt.py
@@ -0,0 +1,90 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Unfortunately, docopt doesn't support multi-word commands.  This is
+important for supporting things like:
+
+mesos cluster ps <args>...
+
+However, it looks like some plans are in place for supporting it in the
+future: https://github.com/docopt/docopt/issues/41
+
+The proposal is to add a "program" keyword argument to docopt to specify the
+full set of words used to represent the command. Since this is not yet
+supported officially, we include the hack below to make it work for us. We
+essentially intercept the call to docopt and make it work with such a "program"
+argument.
+
+To make it work, we inspect the value of "program" and search and replace all
+instances of it in the usage string with a transformed version of it to make it
+a single word (i.e. we replace all spaces with dashes: echo $program | s/
+/-/g). This essentially turns all multi-word commands in the usage string into
+dash-separated single words (e.g., s/mesos cluster ps/mesos-cluster-ps/g). With
+this in place, we then pass this usage string to the original docopt for
+parsing.
+
+Unfortunately, doing things this way means that docopt (by default) will print
+the usage string containing the dashes. To avoid this, we intercept all paths
+where docopt does the printing itself, and transform the usage string back to
+its original form.
+
+Hopefully we can remove this brutal hack at some point in the future
+once docopt supports the "program" argument natively.
+"""
+
+from __future__ import absolute_import
+import os
+import sys
+
+# pylint: disable=F0401
+from docopt import docopt as real_docopt, DocoptExit
+
+
+def docopt(usage, **keywords):
+    """ A wrapper around the real docopt parser. """
+    new_usage = usage
+
+    if "program" in keywords:
+        program = keywords.pop("program")
+        new_usage = usage.replace(program, program.replace(" ", "-"))
+
+    try:
+        stdout = sys.stdout
+
+        with open(os.devnull, 'w') as nullfile:
+            sys.stdout = nullfile
+            arguments = real_docopt(new_usage, **keywords)
+            sys.stdout = stdout
+
+        return arguments
+
+    except DocoptExit:
+        sys.stdout = stdout
+        print >> sys.stderr, usage.strip()
+        sys.exit(1)
+
+    except SystemExit:
+        sys.stdout = stdout
+
+        if "argv" in keywords and any(h in ("-h", "--help")
+                                      for h in keywords["argv"]):
+            print usage.strip()
+        elif "version" in keywords and any(v in ("--version")
+                                           for v in keywords["argv"]):
+            print keywords["version"].strip()
+
+        sys.exit()

http://git-wip-us.apache.org/repos/asf/mesos/blob/f130a567/src/cli_new/lib/cli/exceptions.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/exceptions.py 
b/src/cli_new/lib/cli/exceptions.py
new file mode 100644
index 0000000..c78f4a9
--- /dev/null
+++ b/src/cli_new/lib/cli/exceptions.py
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+CLIException Class
+"""
+
+class CLIException(Exception):
+    """
+    Exceptions class to handle all CLI errors.
+    """
+    pass

http://git-wip-us.apache.org/repos/asf/mesos/blob/f130a567/src/cli_new/lib/cli/plugins/__init__.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/plugins/__init__.py 
b/src/cli_new/lib/cli/plugins/__init__.py
new file mode 100644
index 0000000..e743772
--- /dev/null
+++ b/src/cli_new/lib/cli/plugins/__init__.py
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Plugins Module
+"""
+
+# pylint: disable=W0401
+from .base import *

http://git-wip-us.apache.org/repos/asf/mesos/blob/f130a567/src/cli_new/lib/cli/plugins/base.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/plugins/base.py 
b/src/cli_new/lib/cli/plugins/base.py
new file mode 100644
index 0000000..c10d70f
--- /dev/null
+++ b/src/cli_new/lib/cli/plugins/base.py
@@ -0,0 +1,176 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Plugin's Base Class
+"""
+
+import sys
+
+import cli
+
+from cli.docopt import docopt
+
+
+PLUGIN_NAME = "base-plugin"
+PLUGIN_CLASS = "PluginBase"
+
+VERSION = "Mesos Plugin Base 1.0"
+
+SHORT_HELP = "This is the base plugin from which all other plugins inherit."
+
+USAGE = \
+"""
+{short_help}
+
+Usage:
+  mesos {plugin} (-h | --help)
+  mesos {plugin} --version
+  mesos {plugin} <command> (-h | --help)
+  mesos {plugin} <command> [<args>...] [options]
+
+Options:
+  -h --help  Show this screen.
+  --version  Show version info.
+
+Commands:
+{commands}
+"""
+
+SUBCOMMAND_USAGE = \
+"""{short_help}
+
+Usage:
+  mesos {plugin} {command} (-h | --help)
+  mesos {plugin} {command} --version
+  mesos {plugin} {command} {arguments} [options]
+
+Options:
+{flags}
+
+Description:
+{long_help}
+"""
+
+
+class PluginBase(object):
+    """
+    Base class from which all CLI plugins should inherit.
+    """
+    # pylint: disable=R0903
+    COMMANDS = {}
+
+    def __setup__(self, command, argv):
+        pass
+
+    def __module_reference__(self):
+        return sys.modules[self.__module__]
+
+    def __init__(self, config):
+        # pylint: disable=C0103
+        self.PLUGIN_NAME = PLUGIN_NAME
+        self.PLUGIN_CLASS = PLUGIN_CLASS
+        self.VERSION = VERSION
+        self.SHORT_HELP = SHORT_HELP
+        self.USAGE = USAGE
+
+        module = self.__module_reference__()
+        if hasattr(module, "PLUGIN_NAME"):
+            self.PLUGIN_NAME = getattr(module, "PLUGIN_NAME")
+        if hasattr(module, "PLUGIN_CLASS"):
+            self.PLUGIN_CLASS = getattr(module, "PLUGIN_CLASS")
+        if hasattr(module, "VERSION"):
+            self.VERSION = getattr(module, "VERSION")
+        if hasattr(module, "SHORT_HELP"):
+            self.SHORT_HELP = getattr(module, "SHORT_HELP")
+        if hasattr(module, "USAGE"):
+            self.USAGE = getattr(module, "USAGE")
+
+        self.config = config
+
+    def __autocomplete__(self, command, current_word, argv):
+        # pylint: disable=W0612,W0613,R0201
+        return ("default", [])
+
+    def __autocomplete_base__(self, current_word, argv):
+        option = "default"
+
+        # <command>
+        comp_words = list(self.COMMANDS.keys())
+        comp_words = cli.util.completions(comp_words, current_word, argv)
+        if comp_words != None:
+            return (option, comp_words)
+
+        # <args>...
+        # pylint: disable=R0204
+        comp_words = self.__autocomplete__(argv[0], current_word, argv[1:])
+
+        # In general, we expect a tuple to be returned from __autocomplete__,
+        # with the first element being a valid autocomplete option, and the
+        # second being a list of completion words. However, in the common
+        # case we usually use the default option, so it's OK for a plugin to
+        # just return a list. We will add the "default" option for them.
+        if isinstance(comp_words, tuple):
+            option, comp_words = comp_words
+
+        return (option, comp_words)
+
+    def main(self, argv):
+        """
+        Main method takes argument from top level mesos and parses them
+        to call the appropriate method.
+        """
+        command_strings = cli.util.format_commands_help(self.COMMANDS)
+
+        usage = self.USAGE.format(
+            plugin=self.PLUGIN_NAME,
+            short_help=self.SHORT_HELP,
+            commands=command_strings)
+
+        arguments = docopt(
+            usage,
+            argv=argv,
+            version=self.VERSION,
+            program="mesos " + self.PLUGIN_NAME,
+            options_first=True)
+
+        cmd = arguments["<command>"]
+        argv = arguments["<args>"]
+
+        if cmd in self.COMMANDS.keys():
+            if "external" not in self.COMMANDS[cmd]:
+                argument_format, short_help, long_help, flag_format = \
+                    cli.util.format_subcommands_help(self.COMMANDS[cmd])
+
+                usage = SUBCOMMAND_USAGE.format(
+                    plugin=self.PLUGIN_NAME,
+                    command=cmd,
+                    arguments=argument_format,
+                    flags=flag_format,
+                    short_help=short_help,
+                    long_help=long_help)
+
+                arguments = docopt(
+                    usage,
+                    argv=argv,
+                    program="mesos " + self.PLUGIN_NAME + " " + cmd,
+                    version=self.VERSION,
+                    options_first=True)
+
+            self.__setup__(cmd, argv)
+            getattr(self, cmd.replace("-", "_"))(arguments)
+        else:
+            self.main(["--help"])

http://git-wip-us.apache.org/repos/asf/mesos/blob/f130a567/src/cli_new/lib/cli/util.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/cli/util.py b/src/cli_new/lib/cli/util.py
new file mode 100644
index 0000000..ace07fb
--- /dev/null
+++ b/src/cli_new/lib/cli/util.py
@@ -0,0 +1,151 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+A collection of helper functions used by the CLI and its Plugins.
+"""
+
+import imp
+import importlib
+import os
+import textwrap
+
+from cli.exceptions import CLIException
+
+
+def import_modules(package_paths, module_type):
+    """
+    Looks for python packages under `package_paths` and imports
+    them as modules. Returns a dictionary of the basename of the
+    `package_paths` to the imported modules.
+    """
+    modules = {}
+    for package_path in package_paths:
+        # We put the imported module into the namespace of
+        # "mesos.<module_type>.<>" to keep it from cluttering up
+        # the import namespace elsewhere.
+        package_name = os.path.basename(package_path)
+        package_dir = os.path.dirname(package_path)
+        module_name = "cli." + module_type + "." + package_name
+        try:
+            module = importlib.import_module(module_name)
+        except Exception:
+            obj, filename, data = imp.find_module(package_name, [package_dir])
+            module = imp.load_module(module_name, obj, filename, data)
+        modules[package_name] = module
+
+    return modules
+
+
+def get_module(modules, import_path):
+    """
+    Given a modules dictionary returned by `import_modules()`,
+    return a reference to the module at `import_path` relative
+    to the base module. For example, get_module(modules, "example.stuff")
+    will return a reference to the "stuff" module inside the
+    imported "example" plugin.
+    """
+    import_path = import_path.split('.')
+    try:
+        module = modules[import_path[0]]
+        if len(import_path) > 1:
+            module = getattr(module, ".".join(import_path[1:]))
+    except Exception as exception:
+        raise CLIException("Unable to get module: {error}"
+                           .format(error=str(exception)))
+
+    return module
+
+
+def completions(comp_words, current_word, argv):
+    """
+    Helps autocomplete by returning the appropriate
+    completion words under three conditions.
+
+    1) Returns `comp_words` if the completion word is
+       potentially in that list.
+    2) Returns an empty list if there is no possible
+       completion.
+    3) Returns `None` if the autocomplete is already done.
+    """
+    comp_words += ["-h", "--help", "--version"]
+
+    if len(argv) == 0:
+        return comp_words
+
+    if len(argv) == 1:
+        if argv[0] not in comp_words and current_word:
+            return comp_words
+
+        if argv[0] in comp_words and current_word:
+            return comp_words
+
+        if argv[0] not in comp_words and not current_word:
+            return []
+
+        if argv[0] in comp_words and not current_word:
+            return None
+
+    if len(argv) > 1 and argv[0] not in comp_words:
+        return []
+
+    if len(argv) > 1 and argv[0] in comp_words:
+        return None
+
+    raise CLIException("Unreachable")
+
+
+def format_commands_help(cmds):
+    """
+    Helps format plugin commands for display.
+    """
+    longest_cmd_name = max(cmds.keys(), key=len)
+
+    help_string = ""
+    for cmd in sorted(cmds.keys()):
+        # For the top-level entry point, `cmds` is a single-level
+        # dictionary with `short_help` as the values. For plugins,
+        # `cmds` is a two-level dictionary, where `short_help` is a
+        # field in each sub-dictionary.
+        short_help = cmds[cmd]
+        if isinstance(short_help, dict):
+            short_help = short_help["short_help"]
+
+        num_spaces = len(longest_cmd_name) - len(cmd) + 2
+        help_string += "  %s%s%s\n" % (cmd, " " * num_spaces, short_help)
+
+    return help_string
+
+
+def format_subcommands_help(cmd):
+    """
+    Helps format plugin subcommands for display.
+    """
+    arguments = " ".join(cmd["arguments"])
+    short_help = cmd["short_help"]
+    long_help = textwrap.dedent(cmd["long_help"].rstrip())
+    long_help = "  " + "\n  ".join(long_help.split('\n'))
+    flags = cmd["flags"]
+    flags["-h --help"] = "Show this screen."
+    flag_string = ""
+
+    if len(flags.keys()) != 0:
+        longest_flag_name = max(flags.keys(), key=len)
+        for flag in sorted(flags.keys()):
+            num_spaces = len(longest_flag_name) - len(flag) + 2
+            flag_string += "  %s%s%s\n" % (flag, " " * num_spaces, flags[flag])
+
+    return (arguments, short_help, long_help, flag_string)

http://git-wip-us.apache.org/repos/asf/mesos/blob/f130a567/src/cli_new/lib/mesos/__init__.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/mesos/__init__.py 
b/src/cli_new/lib/mesos/__init__.py
deleted file mode 100644
index f4fc3f1..0000000
--- a/src/cli_new/lib/mesos/__init__.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Mesos Module
-"""
-
-from . import exceptions
-from . import plugins
-from . import util

http://git-wip-us.apache.org/repos/asf/mesos/blob/f130a567/src/cli_new/lib/mesos/docopt.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/mesos/docopt.py b/src/cli_new/lib/mesos/docopt.py
deleted file mode 100644
index 86a4e9c..0000000
--- a/src/cli_new/lib/mesos/docopt.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Unfortunately, docopt doesn't support multi-word commands.  This is
-important for supporting things like:
-
-mesos cluster ps <args>...
-
-However, it looks like some plans are in place for supporting it in the
-future: https://github.com/docopt/docopt/issues/41
-
-The proposal is to add a "program" keyword argument to docopt to specify the
-full set of words used to represent the command. Since this is not yet
-supported officially, we include the hack below to make it work for us. We
-essentially intercept the call to docopt and make it work with such a "program"
-argument.
-
-To make it work, we inspect the value of "program" and search and replace all
-instances of it in the usage string with a transformed version of it to make it
-a single word (i.e. we replace all spaces with dashes: echo $program | s/
-/-/g). This essentially turns all multi-word commands in the usage string into
-dash-separated single words (e.g., s/mesos cluster ps/mesos-cluster-ps/g). With
-this in place, we then pass this usage string to the original docopt for
-parsing.
-
-Unfortunately, doing things this way means that docopt (by default) will print
-the usage string containing the dashes. To avoid this, we intercept all paths
-where docopt does the printing itself, and transform the usage string back to
-its original form.
-
-Hopefully we can remove this brutal hack at some point in the future
-once docopt supports the "program" argument natively.
-"""
-
-from __future__ import absolute_import
-import os
-import sys
-
-# pylint: disable=F0401
-from docopt import docopt as real_docopt, DocoptExit
-
-
-def docopt(usage, **keywords):
-    """ A wrapper around the real docopt parser. """
-    new_usage = usage
-
-    if "program" in keywords:
-        program = keywords.pop("program")
-        new_usage = usage.replace(program, program.replace(" ", "-"))
-
-    try:
-        stdout = sys.stdout
-
-        with open(os.devnull, 'w') as nullfile:
-            sys.stdout = nullfile
-            arguments = real_docopt(new_usage, **keywords)
-            sys.stdout = stdout
-
-        return arguments
-
-    except DocoptExit:
-        sys.stdout = stdout
-        print >> sys.stderr, usage.strip()
-        sys.exit(1)
-
-    except SystemExit:
-        sys.stdout = stdout
-
-        if "argv" in keywords and any(h in ("-h", "--help")
-                                      for h in keywords["argv"]):
-            print usage.strip()
-        elif "version" in keywords and any(v in ("--version")
-                                           for v in keywords["argv"]):
-            print keywords["version"].strip()
-
-        sys.exit()

http://git-wip-us.apache.org/repos/asf/mesos/blob/f130a567/src/cli_new/lib/mesos/exceptions.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/mesos/exceptions.py 
b/src/cli_new/lib/mesos/exceptions.py
deleted file mode 100644
index c78f4a9..0000000
--- a/src/cli_new/lib/mesos/exceptions.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-CLIException Class
-"""
-
-class CLIException(Exception):
-    """
-    Exceptions class to handle all CLI errors.
-    """
-    pass

http://git-wip-us.apache.org/repos/asf/mesos/blob/f130a567/src/cli_new/lib/mesos/plugins/__init__.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/mesos/plugins/__init__.py 
b/src/cli_new/lib/mesos/plugins/__init__.py
deleted file mode 100644
index e743772..0000000
--- a/src/cli_new/lib/mesos/plugins/__init__.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Plugins Module
-"""
-
-# pylint: disable=W0401
-from .base import *

http://git-wip-us.apache.org/repos/asf/mesos/blob/f130a567/src/cli_new/lib/mesos/plugins/base.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/mesos/plugins/base.py 
b/src/cli_new/lib/mesos/plugins/base.py
deleted file mode 100644
index 61b1542..0000000
--- a/src/cli_new/lib/mesos/plugins/base.py
+++ /dev/null
@@ -1,176 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Plugin's Base Class
-"""
-
-import sys
-
-import mesos
-
-from mesos.docopt import docopt
-
-
-PLUGIN_NAME = "base-plugin"
-PLUGIN_CLASS = "PluginBase"
-
-VERSION = "Mesos Plugin Base 1.0"
-
-SHORT_HELP = "This is the base plugin from which all other plugins inherit."
-
-USAGE = \
-"""
-{short_help}
-
-Usage:
-  mesos {plugin} (-h | --help)
-  mesos {plugin} --version
-  mesos {plugin} <command> (-h | --help)
-  mesos {plugin} <command> [<args>...] [options]
-
-Options:
-  -h --help  Show this screen.
-  --version  Show version info.
-
-Commands:
-{commands}
-"""
-
-SUBCOMMAND_USAGE = \
-"""{short_help}
-
-Usage:
-  mesos {plugin} {command} (-h | --help)
-  mesos {plugin} {command} --version
-  mesos {plugin} {command} {arguments} [options]
-
-Options:
-{flags}
-
-Description:
-{long_help}
-"""
-
-
-class PluginBase(object):
-    """
-    Base class from which all CLI plugins should inherit.
-    """
-    # pylint: disable=R0903
-    COMMANDS = {}
-
-    def __setup__(self, command, argv):
-        pass
-
-    def __module_reference__(self):
-        return sys.modules[self.__module__]
-
-    def __init__(self, config):
-        # pylint: disable=C0103
-        self.PLUGIN_NAME = PLUGIN_NAME
-        self.PLUGIN_CLASS = PLUGIN_CLASS
-        self.VERSION = VERSION
-        self.SHORT_HELP = SHORT_HELP
-        self.USAGE = USAGE
-
-        module = self.__module_reference__()
-        if hasattr(module, "PLUGIN_NAME"):
-            self.PLUGIN_NAME = getattr(module, "PLUGIN_NAME")
-        if hasattr(module, "PLUGIN_CLASS"):
-            self.PLUGIN_CLASS = getattr(module, "PLUGIN_CLASS")
-        if hasattr(module, "VERSION"):
-            self.VERSION = getattr(module, "VERSION")
-        if hasattr(module, "SHORT_HELP"):
-            self.SHORT_HELP = getattr(module, "SHORT_HELP")
-        if hasattr(module, "USAGE"):
-            self.USAGE = getattr(module, "USAGE")
-
-        self.config = config
-
-    def __autocomplete__(self, command, current_word, argv):
-        # pylint: disable=W0612,W0613,R0201
-        return ("default", [])
-
-    def __autocomplete_base__(self, current_word, argv):
-        option = "default"
-
-        # <command>
-        comp_words = list(self.COMMANDS.keys())
-        comp_words = mesos.util.completions(comp_words, current_word, argv)
-        if comp_words != None:
-            return (option, comp_words)
-
-        # <args>...
-        # pylint: disable=R0204
-        comp_words = self.__autocomplete__(argv[0], current_word, argv[1:])
-
-        # In general, we expect a tuple to be returned from __autocomplete__,
-        # with the first element being a valid autocomplete option, and the
-        # second being a list of completion words. However, in the common
-        # case we usually use the default option, so it's OK for a plugin to
-        # just return a list. We will add the "default" option for them.
-        if isinstance(comp_words, tuple):
-            option, comp_words = comp_words
-
-        return (option, comp_words)
-
-    def main(self, argv):
-        """
-        Main method takes argument from top level mesos and parses them
-        to call the appropriate method.
-        """
-        command_strings = mesos.util.format_commands_help(self.COMMANDS)
-
-        usage = self.USAGE.format(
-            plugin=self.PLUGIN_NAME,
-            short_help=self.SHORT_HELP,
-            commands=command_strings)
-
-        arguments = docopt(
-            usage,
-            argv=argv,
-            version=self.VERSION,
-            program="mesos " + self.PLUGIN_NAME,
-            options_first=True)
-
-        cmd = arguments["<command>"]
-        argv = arguments["<args>"]
-
-        if cmd in self.COMMANDS.keys():
-            if "external" not in self.COMMANDS[cmd]:
-                argument_format, short_help, long_help, flag_format = \
-                    mesos.util.format_subcommands_help(self.COMMANDS[cmd])
-
-                usage = SUBCOMMAND_USAGE.format(
-                    plugin=self.PLUGIN_NAME,
-                    command=cmd,
-                    arguments=argument_format,
-                    flags=flag_format,
-                    short_help=short_help,
-                    long_help=long_help)
-
-                arguments = docopt(
-                    usage,
-                    argv=argv,
-                    program="mesos " + self.PLUGIN_NAME + " " + cmd,
-                    version=self.VERSION,
-                    options_first=True)
-
-            self.__setup__(cmd, argv)
-            getattr(self, cmd.replace("-", "_"))(arguments)
-        else:
-            self.main(["--help"])

http://git-wip-us.apache.org/repos/asf/mesos/blob/f130a567/src/cli_new/lib/mesos/util.py
----------------------------------------------------------------------
diff --git a/src/cli_new/lib/mesos/util.py b/src/cli_new/lib/mesos/util.py
deleted file mode 100644
index 87d2a65..0000000
--- a/src/cli_new/lib/mesos/util.py
+++ /dev/null
@@ -1,151 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-A collection of helper functions used by the CLI and its Plugins.
-"""
-
-import imp
-import importlib
-import os
-import textwrap
-
-from mesos.exceptions import CLIException
-
-
-def import_modules(package_paths, module_type):
-    """
-    Looks for python packages under `package_paths` and imports
-    them as modules. Returns a dictionary of the basename of the
-    `package_paths` to the imported modules.
-    """
-    modules = {}
-    for package_path in package_paths:
-        # We put the imported module into the namespace of
-        # "mesos.<module_type>.<>" to keep it from cluttering up
-        # the import namespace elsewhere.
-        package_name = os.path.basename(package_path)
-        package_dir = os.path.dirname(package_path)
-        module_name = "mesos." + module_type + "." + package_name
-        try:
-            module = importlib.import_module(module_name)
-        except Exception:
-            obj, filename, data = imp.find_module(package_name, [package_dir])
-            module = imp.load_module(module_name, obj, filename, data)
-        modules[package_name] = module
-
-    return modules
-
-
-def get_module(modules, import_path):
-    """
-    Given a modules dictionary returned by `import_modules()`,
-    return a reference to the module at `import_path` relative
-    to the base module. For example, get_module(modules, "example.stuff")
-    will return a reference to the "stuff" module inside the
-    imported "example" plugin.
-    """
-    import_path = import_path.split('.')
-    try:
-        module = modules[import_path[0]]
-        if len(import_path) > 1:
-            module = getattr(module, ".".join(import_path[1:]))
-    except Exception as exception:
-        raise CLIException("Unable to get module: {error}"
-                           .format(error=str(exception)))
-
-    return module
-
-
-def completions(comp_words, current_word, argv):
-    """
-    Helps autocomplete by returning the appropriate
-    completion words under three conditions.
-
-    1) Returns `comp_words` if the completion word is
-       potentially in that list.
-    2) Returns an empty list if there is no possible
-       completion.
-    3) Returns `None` if the autocomplete is already done.
-    """
-    comp_words += ["-h", "--help", "--version"]
-
-    if len(argv) == 0:
-        return comp_words
-
-    if len(argv) == 1:
-        if argv[0] not in comp_words and current_word:
-            return comp_words
-
-        if argv[0] in comp_words and current_word:
-            return comp_words
-
-        if argv[0] not in comp_words and not current_word:
-            return []
-
-        if argv[0] in comp_words and not current_word:
-            return None
-
-    if len(argv) > 1 and argv[0] not in comp_words:
-        return []
-
-    if len(argv) > 1 and argv[0] in comp_words:
-        return None
-
-    raise CLIException("Unreachable")
-
-
-def format_commands_help(cmds):
-    """
-    Helps format plugin commands for display.
-    """
-    longest_cmd_name = max(cmds.keys(), key=len)
-
-    help_string = ""
-    for cmd in sorted(cmds.keys()):
-        # For the top-level entry point, `cmds` is a single-level
-        # dictionary with `short_help` as the values. For plugins,
-        # `cmds` is a two-level dictionary, where `short_help` is a
-        # field in each sub-dictionary.
-        short_help = cmds[cmd]
-        if isinstance(short_help, dict):
-            short_help = short_help["short_help"]
-
-        num_spaces = len(longest_cmd_name) - len(cmd) + 2
-        help_string += "  %s%s%s\n" % (cmd, " " * num_spaces, short_help)
-
-    return help_string
-
-
-def format_subcommands_help(cmd):
-    """
-    Helps format plugin subcommands for display.
-    """
-    arguments = " ".join(cmd["arguments"])
-    short_help = cmd["short_help"]
-    long_help = textwrap.dedent(cmd["long_help"].rstrip())
-    long_help = "  " + "\n  ".join(long_help.split('\n'))
-    flags = cmd["flags"]
-    flags["-h --help"] = "Show this screen."
-    flag_string = ""
-
-    if len(flags.keys()) != 0:
-        longest_flag_name = max(flags.keys(), key=len)
-        for flag in sorted(flags.keys()):
-            num_spaces = len(longest_flag_name) - len(flag) + 2
-            flag_string += "  %s%s%s\n" % (flag, " " * num_spaces, flags[flag])
-
-    return (arguments, short_help, long_help, flag_string)

Reply via email to