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 ]
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
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)
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
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
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
def _get_default_from_values(self, ctx): return config.get_settings("value").get( "default." + self.get_path(ctx), {}).get("value")
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