def _try(description, last, command, args, call): """Try the completion""" if command == config.main_command.path: args = [config.main_command.path] + list(args) else: args = [config.main_command.path, command] + list(args) complete_envvar = "_{}_COMPLETE".format(config.main_command.path.upper().replace("-", "_")) if description: extra_env = { "COMMANDLINE": " ".join(quote(arg) for arg in args) + ('' if last else ' '), complete_envvar: "complete-fish", } else: extra_env = { "COMP_WORDS": " ".join(quote(arg) for arg in args), "COMP_CWORD": str(max(0, len(args) - (1 if last else 0))), complete_envvar: "complete", } extra_env.update({CASE_INSENSITIVE_ENV: 'ON'} if config.completion.case_insensitive else {}) with updated_env(**extra_env): if call: call_me() else: oldvalue = click_project.completion.IN_COMPLETION click_project.completion.IN_COMPLETION = True config.main_command() click_project.completion.IN_COMPLETION = oldvalue
def show(ctx, name_only, cmds, all, fields, format, **kwargs): """Show the flow dependencies of a command""" show_empty = len(cmds) > 0 if all: cmds = cmds or sorted(get_sub_commands(ctx, config.main_command)) else: cmds = cmds or sorted(config.flowdeps.readonly.keys()) with TablePrinter(fields, format) as tp, Colorer(kwargs) as colorer: for cmd in cmds: if name_only: click.echo(cmd) else: if all: deps = get_flow_commands_to_run(cmd) formatted = " ".join(quote(p) for p in deps) else: values = { profile.name: " ".join([ quote(p) for p in config.flowdeps.all_settings.get( profile.name, {}).get(cmd, []) ]) for profile in config.all_enabled_profiles } args = colorer.colorize(values, config.flowdeps.readprofile) formatted = " ".join(args) if show_empty: formatted = formatted or "None" if formatted: tp.echo(cmd, formatted)
def external_command(**kwargs): from click_project.lib import call config.merge_settings() args = ([command_path] + get_settings_for_path("parameters", path)) env = {(config.main_command.path + "___" + key).upper(): (str(value) if value else "") for key, value in kwargs.items()} ctx = click.get_current_context() env[(config.main_command.path + "___PATH").upper()] = (ctx.command_path.replace(" ", "_").upper()) while ctx: env.update({ (ctx.command_path.replace(" ", "_") + "__" + key).upper(): ((" ".join(map(quote, value)) if type(value) is tuple else str(value) if value else "")) for key, value in ctx.params.items() }) ctx = ctx.parent env[(config.main_command.path + "___CMD_OPTIND").upper()] = (str( len(config.command_line_settings["parameters"][path]))) env[(config.main_command.path + "___CMD_ARGS").upper()] = ( " ".join( quote(a) for a in config.command_line_settings["parameters"][path])) env[(config.main_command.path + "___OPTIND").upper()] = (str( len(args[1:]))) env[(config.main_command.path + "___ARGS").upper()] = (" ".join( quote(a) for a in args[1:])) with updated_env(**env): call(args)
def complete(self, ctx, incomplete): choices = [ " ".join([quote(v) for v in value]) for value in config.settings.get("launchers", {}).values() ] return [ launcher for launcher in choices if startswith(launcher, incomplete) ]
def external_command(**kwargs): from click_project.lib import call ctx = click.get_current_context() config.merge_settings() args = ([command_path] + list(ctx.params.get("args", []))) def value_to_string(value): return (" ".join(map(quote, value)) if type(value) is tuple else str(value) if value else "") env = {("CLK___" + key).upper(): (value_to_string(value)) for key, value in kwargs.items()} env[("CLK___PATH").upper()] = (ctx.command_path.replace( " ", "_").upper()) if "args" in ctx.params: env[("CLK___ARGS").upper()] = " ".join( map(quote, ctx.params["args"])) while ctx: env.update({ (ctx.command_path.replace(" ", "_") + "__" + key).upper(): (value_to_string(value)) for key, value in ctx.params.items() }) ctx = ctx.parent for path, parameters in config.get_settings2("parameters").items(): env[(f"CLK_P_" + path.replace("-", "__").replace( ".", "_")).upper()] = " ".join(map(quote, parameters)) env[("CLK___CMD_OPTIND").upper()] = (str( len( config.commandline_profile.get_settings("parameters") [path]))) env[("CLK___CMD_ARGS").upper()] = (" ".join( quote(a) for a in config.commandline_profile.get_settings( "parameters")[path])) env[("CLK___OPTIND").upper()] = (str(len(args[1:]))) env[("CLK___ALL").upper()] = (" ".join(quote(a) for a in args[1:])) with updated_env(**env): call( args, internal=True, )
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)
def show(ctx, name_only, launchers, all, fields, format, **kwargs): """Show the launchers""" launchers = launchers or sorted(config.settings.get("launchers", {})) with TablePrinter(fields, format) as tp, Colorer(kwargs, all) as colorer: for launcher_name in launchers: if name_only: click.echo(launcher_name) else: if config.launchers.readlevel == "settings-file": args = config.launchers.readonly.get(launcher_name, []) else: values = { level_name: " ".join([ quote(p) for p in config.launchers. all_settings[level_name].get(launcher_name, []) ]) for level_name in colorer.level_to_color } args = colorer.colorize(values, config.launchers.readlevel) if args and args[0]: tp.echo(launcher_name, args)
def show(ctx, name_only, launchers, fields, format, **kwargs): """Show the launchers""" launchers = launchers or sorted(config.settings.get("launchers", {})) with TablePrinter(fields, format) as tp, Colorer(kwargs) as colorer: for launcher_name in launchers: if name_only: click.echo(launcher_name) else: if config.launchers.readprofile == "settings-file": args = config.launchers.readonly.get(launcher_name, []) else: values = { profile.name: " ".join([ quote(p) for p in config.launchers.all_settings[ profile.name].get(launcher_name, []) ]) for profile in config.all_enabled_profiles } args = colorer.colorize(values, config.launchers.readprofile) if any(args): tp.echo(launcher_name, args)
def format(cmds): """Format the trigger command""" return " , ".join(" ".join(quote(arg) for arg in cmd) for cmd in cmds)
def get_line(profile_name): return " ".join([ quote(p) for p in config.parameters.all_settings.get(profile_name, {}).get(cmd_name, []) ])
def _get_command(self, path, parent=None): name = path.split(".")[-1] commands_to_run = get_settings('alias')[path]["commands"] cmdhelp = 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) # 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.command_line_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) 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
def compute_dot(cmds=None, strict=False, cluster=True, left_right=False, lonely=False): import networkx g = networkx.digraph.DiGraph() def cluster_replace(str): return str.replace(".", "_").replace("-", "_") dot = """digraph {\n""" if left_right: dot += """ rankdir = LR;\n""" clusters = defaultdict(six.moves.builtins.set) def register_cluster(cmd_path): if "." in cmd_path: parent_path = ".".join([part for part in cmd_path.split(".")[:-1]]) clusters[parent_path].add(cmd_path) aliases = {} def fill_graph(cmds): for cmd in iter_commands(from_paths=cmds): if hasattr(cmd, "commands_to_run"): aliases[cmd.path] = cmd.commands_to_run LOGGER.develop("Looking at {}".format(cmd.path)) if strict: deps = config.flowdeps.readonly.get(cmd.path, []) else: path = cmd.path deps = list(_flowdeps[path]) while "." in path: path = ".".join(path.split(".")[:-1]) deps += _flowdeps[path] for dep in deps: g.add_node(dep) g.add_node(cmd.path) try: networkx.shortest_path(g, dep, cmd.path) except networkx.NetworkXNoPath: pass else: continue g.add_edge(dep, cmd.path) register_cluster(dep) register_cluster(cmd.path) if not dep.startswith("["): fill_graph([dep]) if lonely: g.add_node(cmd.path) register_cluster(cmd.path) fill_graph(cmds) nodes = g.nodes() adjacency = g.edges() if not adjacency: return None if cluster: for parent_path, cmds in six.iteritems(clusters): if lonely or len(cmds.intersection(nodes)) > 1: dot += """ subgraph cluster_{} {{\n""".format( cluster_replace(parent_path)) dot += """ label="{}";\n""".format(parent_path) for cmd in cmds: if (lonely or cmd in nodes) and cmd not in clusters.keys(): dot += """ "{}";\n""".format(cmd) dot += " }\n" for node in nodes: if node not in clusters.keys(): dot += """ "{}" [label= "{}{}", fillcolor = {}, style = filled];\n""".format( node, node, "\n -> {}".format(' , '.join( ' '.join(quote(arg) for arg in cmd) for cmd in aliases[node])) if node in aliases else "", "greenyellow" if node in aliases else "skyblue", ) for src, dst in adjacency: dot += """ "{}" -> "{}";\n""".format(src, dst) dot += "}" LOGGER.develop(dot) return dot