ariatosca-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From arthurbere...@apache.org
Subject [01/70] [partial] incubator-ariatosca-website git commit: Automatic Site Publish by Buildbot
Date Wed, 06 Sep 2017 17:48:10 GMT
Repository: incubator-ariatosca-website
Updated Branches:
  refs/heads/master aad88f7c2 -> 23d6ba769


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca-website/blob/d593b4ae/apache-ariatosca-0.1.1/aria/cli/core/aria.py
----------------------------------------------------------------------
diff --git a/apache-ariatosca-0.1.1/aria/cli/core/aria.py b/apache-ariatosca-0.1.1/aria/cli/core/aria.py
new file mode 100644
index 0000000..515c06a
--- /dev/null
+++ b/apache-ariatosca-0.1.1/aria/cli/core/aria.py
@@ -0,0 +1,501 @@
+# 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.
+
+"""
+Enhancements and ARIA-specific conveniences for `Click <http://click.pocoo.org>`__.
+"""
+
+import os
+import sys
+import difflib
+import traceback
+import inspect
+from functools import wraps
+
+import click
+
+from ..env import (
+    env,
+    logger
+)
+from .. import defaults
+from .. import helptexts
+from ..ascii_art import ARIA_ASCII_ART
+from ..inputs import inputs_to_dict
+from ... import __version__
+from ...utils.exceptions import get_exception_as_string
+
+
+CLICK_CONTEXT_SETTINGS = dict(
+    help_option_names=['-h', '--help'],
+    token_normalize_func=lambda param: param.lower())
+
+
+class MutuallyExclusiveOption(click.Option):
+    def __init__(self, *args, **kwargs):
+        self.mutually_exclusive = set(kwargs.pop('mutually_exclusive', tuple()))
+        self.mutuality_description = kwargs.pop('mutuality_description',
+                                                ', '.join(self.mutually_exclusive))
+        self.mutuality_error = kwargs.pop('mutuality_error',
+                                          helptexts.DEFAULT_MUTUALITY_ERROR_MESSAGE)
+        if self.mutually_exclusive:
+            help = kwargs.get('help', '')
+            kwargs['help'] = '{0}. {1}'.format(help, self._message)
+        super(MutuallyExclusiveOption, self).__init__(*args, **kwargs)
+
+    def handle_parse_result(self, ctx, opts, args):
+        if (self.name in opts) and self.mutually_exclusive.intersection(opts):
+            raise click.UsageError('Illegal usage: {0}'.format(self._message))
+        return super(MutuallyExclusiveOption, self).handle_parse_result(ctx, opts, args)
+
+    @property
+    def _message(self):
+        return '{0} be used together with {1} ({2}).'.format(
+            '{0} cannot'.format(', '.join(self.opts)) if hasattr(self, 'opts') else 'Cannot',
+            self.mutuality_description,
+            self.mutuality_error)
+
+
+def mutually_exclusive_option(*param_decls, **attrs):
+    """
+    Decorator for mutually exclusive options.
+
+    This decorator works similarly to `click.option`, but supports an extra ``mutually_exclusive``
+    argument, which is a list of argument names with which the option is mutually exclusive.
+
+    You can optionally also supply ``mutuality_description`` and ``mutuality_error`` to override
the
+    default messages.
+
+    NOTE: All mutually exclusive options must use this. It's not enough to use it in just
one of the
+    options.
+    """
+
+    # NOTE: This code is copied and slightly modified from click.decorators.option and
+    # click.decorators._param_memo. Unfortunately, using click's ``cls`` parameter support
does not
+    # work as is with extra decorator arguments.
+
+    def decorator(func):
+        if 'help' in attrs:
+            attrs['help'] = inspect.cleandoc(attrs['help'])
+        param = MutuallyExclusiveOption(param_decls, **attrs)
+        if not hasattr(func, '__click_params__'):
+            func.__click_params__ = []
+        func.__click_params__.append(param)
+        return func
+    return decorator
+
+
+def show_version(ctx, param, value):
+    if not value:
+        return
+
+    logger.info('{0} v{1}'.format(ARIA_ASCII_ART, __version__))
+    ctx.exit()
+
+
+def inputs_callback(ctx, param, value):
+    """
+    Allow to pass any inputs we provide to a command as processed inputs instead of having
to call
+    ``inputs_to_dict`` inside the command.
+
+    ``@aria.options.inputs`` already calls this callback so that every time you use the option
it
+    returns the inputs as a dictionary.
+    """
+    if not value:
+        return {}
+
+    return inputs_to_dict(value)
+
+
+def set_verbosity_level(ctx, param, value):
+    if not value:
+        return
+
+    env.logging.verbosity_level = value
+
+
+def set_cli_except_hook():
+    def recommend(possible_solutions):
+        logger.info('Possible solutions:')
+        for solution in possible_solutions:
+            logger.info('  - {0}'.format(solution))
+
+    def new_excepthook(tpe, value, trace):
+        if env.logging.is_high_verbose_level():
+            # log error including traceback
+            logger.error(get_exception_as_string(tpe, value, trace))
+        else:
+            # write the full error to the log file
+            with open(env.logging.log_file, 'a') as log_file:
+                traceback.print_exception(
+                    etype=tpe,
+                    value=value,
+                    tb=trace,
+                    file=log_file)
+            # print only the error message
+            print value
+
+        if hasattr(value, 'possible_solutions'):
+            recommend(getattr(value, 'possible_solutions'))
+
+    sys.excepthook = new_excepthook
+
+
+def pass_logger(func):
+    """
+    Simply passes the logger to a command.
+    """
+    # Wraps here makes sure the original docstring propagates to click
+    @wraps(func)
+    def wrapper(*args, **kwargs):
+        return func(logger=logger, *args, **kwargs)
+
+    return wrapper
+
+
+def pass_plugin_manager(func):
+    """
+    Simply passes the plugin manager to a command.
+    """
+    # Wraps here makes sure the original docstring propagates to click
+    @wraps(func)
+    def wrapper(*args, **kwargs):
+        return func(plugin_manager=env.plugin_manager, *args, **kwargs)
+
+    return wrapper
+
+
+def pass_model_storage(func):
+    """
+    Simply passes the model storage to a command.
+    """
+    # Wraps here makes sure the original docstring propagates to click
+    @wraps(func)
+    def wrapper(*args, **kwargs):
+        return func(model_storage=env.model_storage, *args, **kwargs)
+
+    return wrapper
+
+
+def pass_resource_storage(func):
+    """
+    Simply passes the resource storage to a command.
+    """
+    # Wraps here makes sure the original docstring propagates to click
+    @wraps(func)
+    def wrapper(*args, **kwargs):
+        return func(resource_storage=env.resource_storage, *args, **kwargs)
+
+    return wrapper
+
+
+def pass_context(func):
+    """
+    Make click context ARIA specific.
+
+    This exists purely for aesthetic reasons, otherwise some decorators are called
+    ``@click.something`` instead of ``@aria.something``.
+    """
+    return click.pass_context(func)
+
+
+class AliasedGroup(click.Group):
+    def __init__(self, *args, **kwargs):
+        self.max_suggestions = kwargs.pop("max_suggestions", 3)
+        self.cutoff = kwargs.pop("cutoff", 0.5)
+        super(AliasedGroup, self).__init__(*args, **kwargs)
+
+    def get_command(self, ctx, cmd_name):
+        cmd = click.Group.get_command(self, ctx, cmd_name)
+        if cmd is not None:
+            return cmd
+        matches = \
+            [x for x in self.list_commands(ctx) if x.startswith(cmd_name)]
+        if not matches:
+            return None
+        elif len(matches) == 1:
+            return click.Group.get_command(self, ctx, matches[0])
+        ctx.fail('Too many matches: {0}'.format(', '.join(sorted(matches))))
+
+    def resolve_command(self, ctx, args):
+        """
+        Override clicks ``resolve_command`` method and appends *Did you mean ...* suggestions
to the
+        raised exception message.
+        """
+        try:
+            return super(AliasedGroup, self).resolve_command(ctx, args)
+        except click.exceptions.UsageError as error:
+            error_msg = str(error)
+            original_cmd_name = click.utils.make_str(args[0])
+            matches = difflib.get_close_matches(
+                original_cmd_name,
+                self.list_commands(ctx),
+                self.max_suggestions,
+                self.cutoff)
+            if matches:
+                error_msg += '{0}{0}Did you mean one of these?{0}    {1}'.format(
+                    os.linesep,
+                    '{0}    '.format(os.linesep).join(matches, ))
+            raise click.exceptions.UsageError(error_msg, error.ctx)
+
+
+def group(name):
+    """
+    Allow to create a group with a default click context and a class for Click's ``didyoueamn``
+    without having to repeat it for every group.
+    """
+    return click.group(
+        name=name,
+        context_settings=CLICK_CONTEXT_SETTINGS,
+        cls=AliasedGroup)
+
+
+def command(*args, **kwargs):
+    """
+    Make Click commands ARIA specific.
+
+    This exists purely for aesthetic reasons, otherwise some decorators are called
+    ``@click.something`` instead of ``@aria.something``.
+    """
+    return click.command(*args, **kwargs)
+
+
+def argument(*args, **kwargs):
+    """
+    Make Click arguments specific to ARIA.
+
+    This exists purely for aesthetic reasons, otherwise some decorators are called
+    ``@click.something`` instead of ``@aria.something``
+    """
+    return click.argument(*args, **kwargs)
+
+
+class Options(object):
+    def __init__(self):
+        """
+        The options API is nicer when you use each option by calling ``@aria.options.some_option``
+        instead of ``@aria.some_option``.
+
+        Note that some options are attributes and some are static methods. The reason for
that is
+        that we want to be explicit regarding how a developer sees an option. If it can receive
+        arguments, it's a method - if not, it's an attribute.
+        """
+        self.version = click.option(
+            '--version',
+            is_flag=True,
+            callback=show_version,
+            expose_value=False,
+            is_eager=True,
+            help=helptexts.VERSION)
+
+        self.json_output = click.option(
+            '--json-output',
+            is_flag=True,
+            help=helptexts.JSON_OUTPUT)
+
+        self.dry_execution = click.option(
+            '--dry',
+            is_flag=True,
+            help=helptexts.DRY_EXECUTION)
+
+        self.reset_config = click.option(
+            '--reset-config',
+            is_flag=True,
+            help=helptexts.RESET_CONFIG)
+
+        self.descending = click.option(
+            '--descending',
+            required=False,
+            is_flag=True,
+            default=defaults.SORT_DESCENDING,
+            help=helptexts.DESCENDING)
+
+        self.service_template_filename = click.option(
+            '-n',
+            '--service-template-filename',
+            default=defaults.SERVICE_TEMPLATE_FILENAME,
+            help=helptexts.SERVICE_TEMPLATE_FILENAME)
+
+        self.service_template_mode_full = mutually_exclusive_option(
+            '-f',
+            '--full',
+            'mode_full',
+            mutually_exclusive=('mode_types',),
+            is_flag=True,
+            help=helptexts.SHOW_FULL,
+            mutuality_description='-t, --types',
+            mutuality_error=helptexts.MODE_MUTUALITY_ERROR_MESSAGE)
+
+        self.service_mode_full = mutually_exclusive_option(
+            '-f',
+            '--full',
+            'mode_full',
+            mutually_exclusive=('mode_graph',),
+            is_flag=True,
+            help=helptexts.SHOW_FULL,
+            mutuality_description='-g, --graph',
+            mutuality_error=helptexts.MODE_MUTUALITY_ERROR_MESSAGE)
+
+        self.mode_types = mutually_exclusive_option(
+            '-t',
+            '--types',
+            'mode_types',
+            mutually_exclusive=('mode_full',),
+            is_flag=True,
+            help=helptexts.SHOW_TYPES,
+            mutuality_description='-f, --full',
+            mutuality_error=helptexts.MODE_MUTUALITY_ERROR_MESSAGE)
+
+        self.mode_graph = mutually_exclusive_option(
+            '-g',
+            '--graph',
+            'mode_graph',
+            mutually_exclusive=('mode_full',),
+            is_flag=True,
+            help=helptexts.SHOW_GRAPH,
+            mutuality_description='-f, --full',
+            mutuality_error=helptexts.MODE_MUTUALITY_ERROR_MESSAGE)
+
+        self.format_json = mutually_exclusive_option(
+            '-j',
+            '--json',
+            'format_json',
+            mutually_exclusive=('format_yaml',),
+            is_flag=True,
+            help=helptexts.SHOW_JSON,
+            mutuality_description='-y, --yaml',
+            mutuality_error=helptexts.FORMAT_MUTUALITY_ERROR_MESSAGE)
+
+        self.format_yaml = mutually_exclusive_option(
+            '-y',
+            '--yaml',
+            'format_yaml',
+            mutually_exclusive=('format_json',),
+            is_flag=True,
+            help=helptexts.SHOW_YAML,
+            mutuality_description='-j, --json',
+            mutuality_error=helptexts.FORMAT_MUTUALITY_ERROR_MESSAGE)
+
+    @staticmethod
+    def verbose(expose_value=False):
+        return click.option(
+            '-v',
+            '--verbose',
+            count=True,
+            callback=set_verbosity_level,
+            expose_value=expose_value,
+            is_eager=True,
+            help=helptexts.VERBOSE)
+
+    @staticmethod
+    def inputs(help):
+        return click.option(
+            '-i',
+            '--inputs',
+            multiple=True,
+            callback=inputs_callback,
+            help=help)
+
+    @staticmethod
+    def force(help):
+        return click.option(
+            '-f',
+            '--force',
+            is_flag=True,
+            help=help)
+
+    @staticmethod
+    def task_max_attempts(default=defaults.TASK_MAX_ATTEMPTS):
+        return click.option(
+            '--task-max-attempts',
+            type=int,
+            default=default,
+            help=helptexts.TASK_MAX_ATTEMPTS.format(default))
+
+    @staticmethod
+    def sort_by(default='created_at'):
+        return click.option(
+            '--sort-by',
+            required=False,
+            default=default,
+            help=helptexts.SORT_BY)
+
+    @staticmethod
+    def task_retry_interval(default=defaults.TASK_RETRY_INTERVAL):
+        return click.option(
+            '--task-retry-interval',
+            type=int,
+            default=default,
+            help=helptexts.TASK_RETRY_INTERVAL.format(default))
+
+    @staticmethod
+    def service_id(required=False):
+        return click.option(
+            '-s',
+            '--service-id',
+            required=required,
+            help=helptexts.SERVICE_ID)
+
+    @staticmethod
+    def execution_id(required=False):
+        return click.option(
+            '-e',
+            '--execution-id',
+            required=required,
+            help=helptexts.EXECUTION_ID)
+
+    @staticmethod
+    def service_template_id(required=False):
+        return click.option(
+            '-t',
+            '--service-template-id',
+            required=required,
+            help=helptexts.SERVICE_TEMPLATE_ID)
+
+    @staticmethod
+    def service_template_path(required=False):
+        return click.option(
+            '-p',
+            '--service-template-path',
+            required=required,
+            type=click.Path(exists=True))
+
+    @staticmethod
+    def service_name(required=False):
+        return click.option(
+            '-s',
+            '--service-name',
+            required=required,
+            help=helptexts.SERVICE_ID)
+
+    @staticmethod
+    def service_template_name(required=False):
+        return click.option(
+            '-t',
+            '--service-template-name',
+            required=required,
+            help=helptexts.SERVICE_ID)
+
+    @staticmethod
+    def mark_pattern():
+        return click.option(
+            '-m',
+            '--mark-pattern',
+            help=helptexts.MARK_PATTERN,
+            type=str,
+            required=False
+        )
+
+options = Options()


Mime
View raw message