def graph(output, format, cmds, strict, cluster, left_right, lonely): """Display the flow dependencies as a graph""" dot = compute_dot(cmds=cmds, strict=strict, cluster=cluster, left_right=left_right, lonely=lonely) if dot is None: LOGGER.status("Nothing to show") exit(0) if format != 'dot': dotpath = which("dot") if dotpath is None: raise click.UsageError( "You don't have graphviz installed. Therefore you cannot use dot." " Hint: graphviz is shipped with CSS :-)") args = [dotpath, "-T{}".format(format)] p = subprocess.Popen( args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, ) out, _ = p.communicate(dot.encode("utf-8")) else: out = dot.encode("utf-8") if output == '-': click.echo(out) elif output: open(output, "wb").write(out) elif format not in ['x11']: path = os.path.join(tempfile.gettempdir(), 'flow.{}'.format(format)) with open(path, 'wb') as f: f.write(out) webbrowser.open('file://' + path)
def _get_command(self, path, parent=None): name = path.replace("@", ".") cmdhelp = "external command" command_name = name paths = self.cmddirs command_path = os.path.abspath( which(command_name, os.pathsep.join(paths))) options = [] arguments = [] flags = [] remaining_args = False ignore_unknown_options = False try: process = subprocess.Popen([command_path, "--help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = process.communicate() if process.returncode == 0: out = out.decode("utf-8") cmdhelp_lines = out.splitlines() + [''] try: index_desc = cmdhelp_lines.index('') + 1 except ValueError: index_desc = 0 try: metadata_desc = cmdhelp_lines.index('--') except ValueError: metadata_desc = -1 # then, we don't bother parsing the arguments. Let the # remaining arguments and unknown options pass through ignore_unknown_options = True remaining_args = "Remaining arguments" cmdhelp = "\n".join(cmdhelp_lines[index_desc:metadata_desc]) cmdhelp = cmdhelp.strip() metadata_out = out[metadata_desc:] ignore_unknown_options = False for l in metadata_out.splitlines(): if l.startswith("O:"): m = re.match( "^O:(?P<name>[^:]+):(?P<type>[^:]+):(?P<help>[^:]+)(:(?P<default>[^:]+))?$", l) if m is None: raise click.UsageError( "Expected format in {} is O:name:type:help[:defautl]," " got {}".format(path, l)) options.append(m.groupdict()) if l.startswith("F:"): m = re.match( "^F:(?P<name>[^:]+):(?P<help>[^:]+)(:(?P<default>[^:]+))?$", l) if m is None: raise click.UsageError( "Expected format in {} is F:name:help[:defautl]," " got {}".format(path, l)) flags.append(m.groupdict()) if l.startswith("A:"): m = re.match( "^A:(?P<name>[^:]+):(?P<type>[^:]+):(?P<help>[^:]+)(:(?P<nargs>[^:]+))?$", l) if m is None: raise click.UsageError( "Expected format in {} is A:name:type:help[:nargs]," " got {}".format(path, l)) arguments.append(m.groupdict()) m = re.match("^N:(?P<help>[^:]+)$", l) if m is not None: remaining_args = m.group("help") m = re.match("^M:(?P<meta>.+)$", l) if m is not None: meta = m.group("meta") if "I" in meta: ignore_unknown_options = True cmdflowdepends = re.search('flowdepends: (.+)', out) if cmdflowdepends: cmdflowdepends = cmdflowdepends.group(1).split(', ') else: cmdflowdepends = [] else: cmdflowdepends = [] cmdhelp = "No help found... (the command is most likely broken)" process.wait() except Exception as e: LOGGER.warning("When loading command {}: {}".format(name, e)) from click_project.overloads import on_command_loading_error on_command_loading_error() raise from click_project.decorators import command, argument, option, flag 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, ) types = { "int": int, "float": float, "str": str, } def get_type(t): if t.startswith("["): t = click.Choice(json.loads(t)) elif "." in t: t = t.split(".") m = importlib.import_module(".".join(t[:-1])) t = getattr(m, t[-1]) elif t.startswith("date("): format = re.match("date\((?P<format>.+)\)", t).group("format") from click_project.lib import parsedatetime t = lambda value: parsedatetime(value)[0].strftime(format) else: t = types[t] return t if remaining_args: external_command = argument('args', nargs=-1, help=remaining_args)(external_command) for o in options: if "type" in o: t = get_type(o["type"]) external_command = option( *(o["name"].split(",")), help=o["help"], type=t or str, default=o.get("default"), )(external_command) for a in reversed(arguments): if "type" in a: t = get_type(a["type"]) external_command = argument( a["name"], help=a["help"], type=t or str, nargs=int(a["nargs"] or "1"), )(external_command) for f in flags: external_command = flag( *(f["name"].split(",")), help=f["help"], default=f["default"] == "True", )(external_command) external_command = command( name=name, ignore_unknown_options=ignore_unknown_options, help=cmdhelp, short_help=cmdhelp.splitlines()[0] if cmdhelp else "", handle_dry_run=True, flowdepends=cmdflowdepends)(external_command) external_command.params.append( AutomaticOption(["--edit-customcommand"], help="Edit the external command", expose_value=False, is_flag=True, callback=lambda ctx, param, value: edit_external_command(command_path) if value is True else None)) external_command.customcommand_path = command_path return external_command
def git(): git = which("git") if not git: raise click.UsageError("Git is needed to use the git-store command") return git
def _get_command(self, path, parent=None): prefix = config.app_name + "-" name = path.replace("@", ".") cmdhelp = "external command" command_name = prefix + name paths = external_cmds_paths() command_path = which(command_name, os.pathsep.join(paths)) options = [] arguments = [] flags = [] remaining_args = "Remaining arguments" try: process = subprocess.Popen([command_path, "--help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = process.communicate() if process.returncode == 0: out = out.decode("utf-8") cmdhelp_lines = out.splitlines() + [''] try: index_desc = cmdhelp_lines.index('') + 1 except ValueError: index_desc = 0 try: metadata_desc = cmdhelp_lines.index('--') remaining_args = False except ValueError: metadata_desc = -1 cmdhelp = "\n".join(cmdhelp_lines[index_desc:metadata_desc]) cmdhelp = cmdhelp.strip() metadata_out = out[metadata_desc:] for l in metadata_out.splitlines(): if l.startswith("O:"): m = re.match( "^O:(?P<name>[^:]+):(?P<type>[^:]+):(?P<help>[^:]+)$", l) if m is None: raise click.UsageError( "Expected format in {} is O:name:type:help," " got {}".format(path, l)) options.append(m.groupdict()) if l.startswith("F:"): m = re.match( "^F:(?P<name>[^:]+):(?P<help>[^:]+)(:(?P<default>[^:]+))?$", l) if m is None: raise click.UsageError( "Expected format in {} is F:name:help," " got {}".format(path, l)) flags.append(m.groupdict()) if l.startswith("A:"): m = re.match( "^A:(?P<name>[^:]+):(?P<type>[^:]+):(?P<help>[^:]+)(:(?P<nargs>[^:]+))?$", l) if m is None: raise click.UsageError( "Expected format in {} is A:name:type:help[:nargs]," " got {}".format(path, l)) arguments.append(m.groupdict()) m = re.match("^N:(?P<help>[^:]+)$", l) if m is not None: remaining_args = m.group("help") cmdflowdepends = re.search('flowdepends: (.+)', out) if cmdflowdepends: cmdflowdepends = cmdflowdepends.group(1).split(', ') else: cmdflowdepends = [] else: cmdflowdepends = [] cmdhelp = "No help found... (the command is most likely broken)" process.wait() except Exception as e: LOGGER.warning("When loading command {}: {}".format(name, e)) from click_project.overloads import on_command_loading_error on_command_loading_error() raise from click_project.decorators import command, argument, option, flag 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) types = { "int": int, "float": float, "str": str, } for o in options: if "type" in o: if "." in o["type"]: t = o["type"].split(".") m = importlib.import_module(".".join(t[:-1])) t = getattr(m, t[-1]) else: t = types[o["type"]] external_command = option( o["name"], help=o["help"], type=t or str, )(external_command) for a in arguments: if "type" in a: if "." in a["type"]: t = a["type"].split(".") m = importlib.import_module(".".join(t[:-1])) t = getattr(m, t[-1]) else: t = types[a["type"]] external_command = argument( a["name"], help=a["help"], type=t or str, nargs=int(a["nargs"] or "1"), )(external_command) for f in flags: external_command = flag( f["name"], help=f["help"], default=f["default"] == "True", )(external_command) if remaining_args: external_command = argument('args', nargs=-1, help=remaining_args)(external_command) external_command = command( name=name, help=cmdhelp, short_help=cmdhelp.splitlines()[0] if cmdhelp else "", handle_dry_run=True, flowdepends=cmdflowdepends)(external_command) return external_command