Example #1
0
 def _list_command_paths(self, parent):
     if isinstance(parent, config.main_command.__class__):
         return [a for a in config.get_settings('alias').keys()]
     else:
         return [
             a for a in config.get_settings('alias').keys()
             if a.startswith(parent.path +
                             ".") and a[len(parent.path) + 1:] != 0
         ]
Example #2
0
 def getchoice(self, ctx):
     from click_project.plugins import plugins
     choice = {plugin_name(plugin) for plugin in plugins.list_plugins()}
     if self.disabled:
         choice &= set(
             config.get_settings('plugins').get("disabled_plugins", []))
     if self.enabled:
         choice -= set(
             config.get_settings('plugins').get("disabled_plugins", []))
     return choice
Example #3
0
def load_plugins():
    plugindirs = []
    if config.local_profile and config.local_profile.pluginsdir:
        plugindirs.append(config.local_profile.pluginsdir)
    if config.global_profile.pluginsdir:
        plugindirs.append(config.global_profile.pluginsdir)
    for recipe in config.all_enabled_recipes:
        plugindirs.append(recipe.pluginsdir)
    plugindirs.extend(config.plugindirs)
    global plugins
    if plugins is None:
        plugins = plugin_base.make_plugin_source(searchpath=plugindirs)
    disabled_plugins = {
        plugin.replace("/", "_")
        for plugin in config.get_settings('plugins').get(
            "disabled_plugins", [])
    }
    plugins.persist = True
    for plugin in set(
            plugins.list_plugins()) - disabled_plugins - plugins_cache:
        try:
            before = datetime.now()
            mod = plugins.load_plugin(plugin)
            if hasattr(mod, 'load_plugin'):
                mod.load_plugin()
            after = datetime.now()
            spent_time = (after - before).total_seconds()
            LOGGER.develop("Plugin {} loaded in {} seconds".format(
                plugin, spent_time))
            threshold = 0.1
            if spent_time > threshold:
                LOGGER.debug(
                    "Plugin {} took more than {} seconds to load ({})."
                    " You might consider disabling the plugin when you don't use it."
                    " Or contribute to its dev to make it load faster.".format(
                        plugin,
                        threshold,
                        spent_time,
                    ))
        except Exception as e:
            ctx = click_get_current_context_safe()
            if ctx is None or not ctx.resilient_parsing:
                plugin_name = plugin.replace("_", "/")
                LOGGER.warning(
                    "Error when loading plugin {}"
                    " (if the plugin is no more useful,"
                    " consider uninstalling the plugins {}): {}".format(
                        plugin_name,
                        plugin_name,
                        e,
                    ))
                on_command_loading_error()
        plugins_cache.add(plugin)
    for hook in afterloads:
        if hook not in afterloads_cache:
            hook()
            afterloads_cache.add(hook)
Example #4
0
    def get_help_record(self, ctx):
        show_default = self.show_default
        self.show_default = False
        res = super(ParameterMixin, self).get_help_record(ctx)
        self.show_default = show_default
        if res is None:
            metavar = self.type.get_metavar(ctx)
            if metavar:
                metavar = "%s %s" % (self.human_readable_name, metavar)
            else:
                metavar = self.human_readable_name
            res = (metavar, self.help)
        default = self._get_default_from_values(ctx)
        canon_default = self.default
        if isinstance(canon_default, (list, tuple)):
            canon_default = ', '.join('%s' % d for d in self.default)
        elif callable(canon_default):
            canon_default = canon_default()
        canon_default = str(canon_default)

        if self.default is not None and self.show_default:
            res1 = res[1]
            res1 += "  [default: "
            if default:
                res1 += default + " (computed from value.default.{}".format(
                    self.get_path(ctx))
                if self.default:
                    res1 += " and overriding static one: " + canon_default
                res1 += ")"
            elif isinstance(
                    canon_default,
                    six.string_types) and canon_default.startswith("value:"):
                res1 += config.get_settings("value").get(
                    canon_default[len("value:"):], {
                        "value": "None"
                    }).get("value")
                res1 += " (computed from {})".format(canon_default)
            else:
                res1 += canon_default
            res1 += "]"
            res = (
                res[0],
                res1,
            )
        if self.deprecated:
            res = (
                res[0],
                res[1] + " (deprecated: {})".format(self.deprecated),
            )
        return res
Example #5
0
 def decorator(func):
     # not sure why, but python can't access the default value with a closure in a statement of this kind
     #     default = default
     # so we have to use another name
     actual_default = config.get_settings('values').get(
         config_name, {}).get('value') or default or 'simple'
     opts = [
         option('--format',
                default=actual_default,
                help='Table format',
                type=get_tabulate_formats()),
     ]
     for opt in reversed(opts):
         func = opt(func)
     return func
Example #6
0
def eval_arg(arg):
    if not isinstance(arg, six.string_types):
        return arg
    eval_match = re.match('eval(\(\d+\)|):(.+)', arg)
    nexteval_match = re.match('nexteval(\(\d+\)|):(.+)', arg)
    if arg.startswith("noeval:"):
        arg = arg[len("noeval:"):]
    elif nexteval_match:
        arg = 'eval%s:%s' % (
            ('(%s)' % nexteval_match.group(1)
             if nexteval_match.group(1) else ''), nexteval_match.group(2))
    elif arg.startswith("value:"):
        key = arg[len("value:"):]
        arg = config.get_settings("value").get(key, {"value": None})["value"]
    elif arg.startswith("pyeval:"):
        try:
            evaluated_arg = str(eval(arg[len("pyeval:"):]))
            LOGGER.develop("%s evaluated to %s" % (arg, evaluated_arg))
            arg = evaluated_arg
        except Exception:
            LOGGER.develop(traceback.format_exc())
            LOGGER.error("Something went wrong when evaluating {}."
                         " If you did not want it to be evaluated"
                         " please use the following syntax: noeval:{}".format(
                             arg, arg))
            exit(1)
    elif eval_match:
        try:

            @cache_disk(expire=int(eval_match.group(1) or '600'))
            def evaluate(project, expr):
                return check_output(shlex.split(expr)).strip()

            evaluated_arg = evaluate(config.project, eval_match.group(2))
            LOGGER.develop("%s evaluated to %s" % (arg, evaluated_arg))
            arg = evaluated_arg
        except Exception:
            LOGGER.develop(traceback.format_exc())
            LOGGER.error("Something went wrong when evaluating {}."
                         " If you did not want it to be evaluated"
                         " please use the following syntax: noeval:{}".format(
                             arg, arg))
            exit(1)
    return arg
Example #7
0
 def _get_default_from_values(self, ctx):
     return config.get_settings("value").get(
         "default." + self.get_path(ctx), {}).get("value")
Example #8
0
    def _get_command(self, path, parent=None):
        name = path.split(".")[-1]
        commands_to_run = config.get_settings('alias')[path]["commands"]
        cmdhelp = config.get_settings('alias')[path]["documentation"]
        cmdhelp = cmdhelp or "Alias for: {}".format(' , '.join(
            ' '.join(quote(arg) for arg in cmd) for cmd in commands_to_run))
        short_help = cmdhelp.splitlines()[0]
        if len(cmdhelp) > 55:
            short_help = cmdhelp[:52] + '...'
        deps = []

        for cmd in commands_to_run:

            cmdctx = get_ctx(cmd, resilient_parsing=True)
            # capture the flow of the aliased command only if it is not called
            # with an explicit flow
            if (not cmdctx.params.get("flow")
                    and not cmdctx.params.get("flow_from")
                    and not cmdctx.params.get("flow_after")):
                deps += get_flow_commands_to_run(cmdctx.command.path)
        c = get_ctx(commands_to_run[-1])
        kind = None

        def create_cls(cls):
            return cls(name=name,
                       help=cmdhelp,
                       short_help=short_help,
                       ignore_unknown_options=c is not None
                       and c.ignore_unknown_options)

        if c is not None:
            if isinstance(c.command, Group):
                cls = create_cls(group)
                kind = "group"
            elif isinstance(c.command, Command):
                cls = create_cls(command)
                kind = "command"
            elif isinstance(c.command, config.main_command.__class__):
                cls = click.group(cls=config.main_command.__class__,
                                  name=name,
                                  help=cmdhelp,
                                  short_help=short_help)
                kind = config.main_command.path
            else:
                raise NotImplementedError()
        elif commands_to_run[-1][0] == config.main_command.path:
            cls = click.group(cls=config.main_command.__class__,
                              name=name,
                              help=cmdhelp,
                              short_help=short_help)
            del commands_to_run[-1][0]
            c = get_ctx(commands_to_run[-1])
            kind = config.main_command.path
        else:
            cls = create_cls(command)

        def alias_command(ctx, *args, **kwargs):
            if "config" in kwargs:
                del kwargs["config"]
            commands = list(commands_to_run)

            for command_ in commands[:-1]:
                LOGGER.debug("Running command: {}".format(" ".join(
                    quote(c) for c in command_)))
                run(command_)
            arguments = ctx.command.complete_arguments[:]
            arguments = clean_flow_arguments(arguments)
            whole_command = commands[-1] + arguments
            original_command_ctx = get_ctx(whole_command, side_effects=True)
            cur_ctx = original_command_ctx
            ctxs = []
            # if the resolution of the context brought too many commands, we
            # must not call the call back of the children of the original_command
            while cur_ctx and ctx.command.original_command != cur_ctx.command:
                cur_ctx = cur_ctx.parent

            while cur_ctx:
                ctxs.insert(0, cur_ctx)
                cur_ctx = cur_ctx.parent
            LOGGER.develop("Running command: {}".format(" ".join(
                quote(c) for c in commands[-1])))

            def run_callback(_ctx):
                LOGGER.develop(
                    "Running callback of {} with args {}, params {}".format(
                        _ctx.command.path,
                        config.commandline_profile.get_settings("parameters")[
                            _ctx.command.path],
                        _ctx.params,
                    ))
                with _ctx:
                    old_resilient_parsing = _ctx.resilient_parsing
                    _ctx.resilient_parsing = ctx.resilient_parsing
                    _ctx.command.callback(**_ctx.params)
                    _ctx.resilient_parsing = old_resilient_parsing

            for cur_ctx in ctxs:
                run_callback(cur_ctx)

        alias_command = pass_context(alias_command)
        alias_command = cls(alias_command)
        alias_command.params.append(
            AutomaticOption(
                ["--edit-alias"],
                help="Edit the alias",
                expose_value=False,
                is_flag=True,
                callback=lambda ctx, param, value: edit_alias_command(path)
                if value is True else None))
        if deps:
            alias_command.clickproject_flowdepends = deps

        alias_command.commands_to_run = commands_to_run
        if c is not None:
            alias_command.original_command = c.command
            if kind == "group":
                if c.command.default_cmd_name is not None:
                    alias_command.set_default_command(
                        c.command.default_cmd_name)
            elif kind == "command":
                alias_command.handle_dry_run = c.command.handle_dry_run
            alias_param_names = list(
                map(lambda c: c.name, alias_command.params))

            def was_given(param):
                return not (
                    # catched the default value only because it was not
                    # given to the command line
                    param.name in c.click_project_default_catch or
                    # not given for sure
                    c.params.get(param.name) is None)

            alias_command.params = [
                param for param in c.command.params
                if param.name not in alias_param_names and param.name not in
                ("flow", "flow_from", "flow_after") and (
                    # options may be given several times
                    isinstance(param, click.Option) or (
                        # it is an argument then!
                        not was_given(param) or
                        # may be given, but may be given again
                        param.multiple or
                        # may be given, but may be given again
                        param.nargs == -1))
            ] + alias_command.params
            # any option required with nargs=-1 that was already given should be
            # no more required
            for param in alias_command.params:
                if param.nargs == -1 and param.required and was_given(param):
                    param.required = False
        return alias_command