Source code for temci.scripts.cli

import locale
from enum import Enum
import datetime

from temci.utils.number import FNumber
from temci.utils.plugin import load_plugins
from temci.utils.util import sphinx_doc, get_doc_for_type_scheme

import warnings

from temci.scripts.temci_completion import completion_file_name, create_completion_dir
from temci.utils import util
if __name__ == "__main__":
    util.allow_all_imports = True

warnings.simplefilter("ignore")
import shutil

from temci.utils.typecheck import *

from temci.build.builder import BuildError
from temci.run.run_processor import RunProcessor
from temci.build.build_processor import BuildProcessor
import temci.run.run_driver as run_driver
import temci.run.run_driver_plugin
from temci.report.report import ReporterRegistry
from temci.utils.settings import Settings
from temci.report.report_processor import ReportProcessor
import temci.report.report
import temci.report.testers
import click, sys, logging, json, os

from temci.utils.click_helper import type_scheme_option, cmd_option, CmdOption, CmdOptionList, document_func
import temci.scripts.version
import typing as t


Settings().load_files()


[docs]class ErrorCode(Enum): NO_ERROR = 0 PROGRAM_ERROR = 1 TEMCI_ERROR = 255
load_plugins() @click.group(epilog=""" temci (version {}) Copyright (C) {} Johannes Bechberger This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. For details, see the LICENSE file in the source folder of temci. This program is still in an alpha stage. It may happen that your system needs to be rebooted to be usable again. Plugins are loaded from `~/.temci` and from the environment variable `TEMCI_PLUGIN_PATH` (colon separated paths). """.format(temci.scripts.version.version, datetime.datetime.now().year)) def cli(): if "TEMCI_ENV" in os.environ: Settings()["env"] = json.loads(os.getenv("TEMCI_ENV")) command_docs = { "build": "Build programs and output modified run config file", "report": "Generate a report from benchmarking result", "init": "Helper commands to initialize files (like settings)", "completion": "Creates completion files for several shells.", "short": "Utility commands to ease working directly on the command line", "clean": "Clean up the temporary files", "setup": "Compile all needed binaries in the temci scripts folder", "version": "Print the current version ({})".format(temci.scripts.version.version), "format": "Format a number" } for driver in run_driver.RunDriverRegistry.registry: command_docs[driver] = run_driver.RunDriverRegistry.registry[driver].__description__.strip().split("\n")[0] common_options = CmdOptionList( CmdOption.from_non_plugin_settings("") ) run_options = { "common": CmdOptionList( CmdOption.from_non_plugin_settings("run"), CmdOption.from_non_plugin_settings("stats", name_prefix="stats_"), CmdOption.from_non_plugin_settings("report/number", name_prefix="report_number_") ), "run_driver_specific": { # besides DRIVER_misc and plugins "exec": CmdOptionList() } } # init the run_options dictionary for driver in run_driver.RunDriverRegistry.registry: options = CmdOptionList( CmdOption.from_registry(run_driver.RunDriverRegistry.registry[driver]), CmdOption.from_non_plugin_settings("run/{}_misc".format(driver)), CmdOption.from_non_plugin_settings("run/cpuset", name_prefix="cpuset_"), run_options["common"] ) if driver not in run_options["run_driver_specific"]: run_options["run_driver_specific"][driver] = options else: run_options["run_driver_specific"][driver].append(options) report_options = CmdOptionList( CmdOption.from_non_plugin_settings("report"), CmdOption.from_non_plugin_settings("stats") ) # init the report_options dictionary for reporter in ReporterRegistry.registry: options = CmdOption.from_non_plugin_settings("report/{}_misc".format(reporter), name_prefix=reporter + "_") report_options.append(options) build_options = CmdOptionList( CmdOption.from_non_plugin_settings("build") ) misc_commands = { "init": { "common": CmdOptionList(), "sub_commands": { "settings": CmdOptionList(), "build_config": CmdOptionList(), "run_config": CmdOptionList() } }, "completion": { "common": CmdOptionList(), "sub_commands": { "bash": CmdOptionList(), #"fish": CmdOptionList(), "zsh": CmdOptionList() } }, "short": { "common": CmdOptionList(), "sub_commands": { "exec": CmdOptionList(CmdOption("with_description", type_scheme=ListOrTuple(Tuple(Str(), Str())) // Description("DESCRIPTION COMMAND: Benchmark the command and set its" " description attribute." "Appends '$ARGUMENT' " "to the command if the string isn't present. " "Use the '--argument' option to set the value " "that this string is replaced with."), short="d", completion_hints={"zsh": "_command"}), CmdOption("without_description", short="wd", type_scheme=ListOrTuple(Str()) // Description("COMMAND: Benchmark the command and use " "itself as its description. " "Appends '$ARGUMENT' " "to the command if the string isn't present. " "Use the '--argument' option to set the value " "that this string is replaced with."), completion_hints={"zsh": "_command"}), run_options["run_driver_specific"]["exec"], run_options["common"] ), "shell": CmdOptionList(run_options["run_driver_specific"]["exec"], run_options["common"]) } }, "clean": CmdOptionList(), "setup": CmdOptionList(CmdOption("build_kernel_modules", type_scheme=Bool() // Default(False) // Description("Build the rusage helper program and the " "kernel modules used for disabling " "the CPU caches (with the --build_kernel_modules option)"))) } misc_commands_description = { "completion": { "zsh": "Creates a new tab completion file for zsh and returns its file name", #"fish": "Creates a file /tmp/temci_fish_completion for fish completion support.", "bash": "Creates a new tab completion file for zsh and returns its file name", }, "init": { "settings": "Create a new settings file temci.yaml (or the file name passed) in the current directory", "build_config": "Creates a sample build config file build_config.yaml (or the file name passed) in the current directory", "run_config": "Creates a sample exec run config file run_config.yaml (or the file name passed) in the current directory" }, "short": { "exec": "Execute commands directly with the exec run driver", "shell": "Execute a command in a shell with benchmarking setup" } }
[docs]def benchmark_and_exit(runs: t.List[dict] = None): """ Benchmark and exit with an exit code if an error occurred: 0 if everything went okay, 1 if at least one benchmarked program failed, 255 if temci itself failed """ try: processor = RunProcessor(runs) processor.build() processor.benchmark() if processor.recorded_error(): sys.exit(ErrorCode.PROGRAM_ERROR.value) except BuildError as err: err.log() sys.exit(ErrorCode.PROGRAM_ERROR.value) except KeyboardInterrupt: logging.error("KeyboardInterrupt. Cleaned up everything.") sys.exit(ErrorCode.TEMCI_ERROR.value)
[docs]def create_run_driver_function(driver: str, options: CmdOptionList): @cli.command(name=driver, short_help=command_docs[driver]) @click.argument("run_file", default="") @cmd_option(options) def _func(*args, **kwargs): globals()["temci__" + driver](*args, **kwargs) def _func2(run_file, **kwargs): Settings()["run/driver"] = driver if run_file != "": Settings()["run/in"] = run_file benchmark_and_exit() _func2.__name__ = "temci__" + driver document_func(command_docs[driver], options, argument="configuration YAML file")(_func2) globals()["temci__" + driver] = _func2
# Register a command for each run driver for driver in run_driver.RunDriverRegistry.registry: create_run_driver_function(driver, CmdOptionList(common_options, run_options["common"], run_options["run_driver_specific"][driver]))
[docs]def temci__short(): pass
temci__short.__doc__ = command_docs["short"] @cli.group(short_help=command_docs["short"]) @cmd_option(common_options) def short(**kwargs): pass @short.command(short_help=misc_commands_description["short"]["exec"]) @click.argument('commands', nargs=-1, metavar="COMMANDS") @cmd_option(common_options) @cmd_option(misc_commands["short"]["sub_commands"]["exec"]) def exec(commands, **kwargs): temci__short__exec(list(commands), **kwargs)
[docs]@document_func(misc_commands_description["short"]["exec"], common_options, misc_commands["short"]["sub_commands"]["exec"]) def temci__short__exec(commands: list, with_description: list = None, without_description: list = None, **kwargs): runs = [] def create_run_config(cmd: str) -> dict: res = { "run_cmd": [cmd] } return res if with_description is not None: for (descr, cmd) in with_description: runs.append({ "run_config": create_run_config(cmd), "attributes": { "description": descr } }) for cmd in commands + (list(without_description) or []): runs.append({"run_config": create_run_config(cmd), "attributes": { "description": cmd } }) for run in runs: con = run["run_config"] if "$ARGUMENT" not in con["run_cmd"]: con["run_cmd"][0] += " $ARGUMENT" Settings()["run/driver"] = "exec" benchmark_and_exit(runs)
@short.command(short_help=misc_commands_description["short"]["shell"]) @click.argument('command', nargs=-1, metavar="COMMAND") @cmd_option(common_options) @cmd_option(misc_commands["short"]["sub_commands"]["shell"]) def shell(command, **kwargs): temci__short__shell(" ".join(command) if len(command) > 0 else "sh", **kwargs)
[docs]@document_func(misc_commands_description["short"]["shell"], common_options, misc_commands["short"]["sub_commands"]["shell"]) def temci__short__shell(command: str, **kwargs): Settings()["run/driver"] = "shell" Settings()["run/runs"] = 1 Settings()["run/discarded_runs"] = 0 Settings()["run/cpuset/parallel"] = 0 benchmark_and_exit([{"run_config": { "run_cmd": command }, "attributes": { "description": command } }])
@cli.command(short_help=command_docs["report"]) @click.argument('report_file', type=click.Path(exists=True), nargs=-1) @cmd_option(common_options) @cmd_option(report_options) def report(*args, **kwargs): if not kwargs["report_file"]: kwargs["report_file"] = Settings()["report"]["in"] temci__report(*args, **kwargs)
[docs]@document_func(command_docs["report"], common_options, report_options) def temci__report(report_file: t.List[str], **kwargs): Settings()["report/in"] = report_file ReportProcessor().report()
@cli.group(short_help=command_docs["init"]) @cmd_option(misc_commands["init"]["common"]) @cmd_option(common_options) def init(**kwargs): pass
[docs]def temci__init(): pass
temci__init.__doc__ = short_help=command_docs["init"] @init.command(short_help=misc_commands_description["init"]["settings"]) @click.argument('file', type=click.Path(exists=False), default="temci.yaml") @cmd_option(misc_commands["init"]["sub_commands"]["settings"]) @cmd_option(common_options) def settings(file, **kwargs): temci__init__settings(file, **kwargs)
[docs]@document_func(misc_commands_description["init"]["settings"], misc_commands["init"]["sub_commands"]["settings"], common_options) def temci__init__settings(file, **kwargs): Settings().store_into_file(file, comment_out_defaults=True)
@init.command(short_help=misc_commands_description["init"]["build_config"], name="build_config") @cmd_option(misc_commands["init"]["sub_commands"]["build_config"]) @cmd_option(common_options) @click.argument('file', type=click.Path(exists=False), default="build_config.yaml") def build_config(file, **kwargs): temci__init__build_config(file, **kwargs)
[docs]@document_func(misc_commands_description["init"]["build_config"], misc_commands["init"]["sub_commands"]["build_config"], common_options) def temci__init__build_config(file, **kwargs): BuildProcessor.store_example_config(file)
@init.command(short_help=misc_commands_description["init"]["run_config"], name="run_config") @cmd_option(misc_commands["init"]["sub_commands"]["run_config"]) @cmd_option(common_options) @click.argument('file', type=click.Path(exists=False), default="run_config.yaml") def run_config(file, **kwargs): temci__init__run_config(file, **kwargs)
[docs]@document_func(misc_commands_description["init"]["run_config"], misc_commands["init"]["sub_commands"]["run_config"], common_options) def temci__init__run_config(file, **kwargs): run_driver.ExecRunDriver.store_example_config(file)
@cli.command(short_help=command_docs["build"]) @click.argument('build_file', type=click.Path(exists=True)) @cmd_option(CmdOptionList(common_options, build_options)) def build(build_file: str, **kwargs): temci__build(build_file, **kwargs)
[docs]@document_func(command_docs["build"], common_options, build_options, argument="build configuration YAML file") def temci__build(build_file: str, **kwargs): try: Settings()["build/in"] = build_file BuildProcessor().build() except KeyboardInterrupt: logging.error("Aborted") except BaseException as err: print(err) logging.error(str(err))
@cli.command(short_help=command_docs["clean"]) @cmd_option(common_options) def clean(**kwargs): temci__clean(**kwargs)
[docs]@document_func(command_docs["clean"], common_options) def temci__clean(**kwargs): shutil.rmtree(Settings()["tmp_dir"])
@cli.command(short_help=command_docs["version"]) @cmd_option(common_options) def version(**kwargs): print(temci.scripts.version.version)
[docs]@document_func(command_docs["version"], common_options) def temci__version(**kwargs): print(temci.scripts.version.version)
format_options = CmdOption.from_non_plugin_settings("report/number") @cli.command(short_help=command_docs["format"]) @click.argument("number", type=float) @click.argument("abs_deviation", type=float, default=0) @cmd_option(common_options) @cmd_option(format_options) def format(number, abs_deviation, **kwargs): temci__format(number, abs_deviation, **kwargs)
[docs]@document_func(command_docs["format"], common_options, format_options) def temci__format(number, abs_deviation, **kwargs): print(FNumber(number, abs_deviation=abs_deviation).format())
@cli.group(short_help=command_docs["completion"]) @cmd_option(common_options) def completion(**kwargs): pass
[docs]def temci__completion(): pass
temci__completion.__doc__ = command_docs["completion"] @cli.group(short_help=command_docs["completion"]) @cmd_option(common_options) def completion(**kwargs): pass @completion.command(short_help=misc_commands_description["completion"]["zsh"]) @cmd_option(common_options) def zsh(**kwargs): temci__completion__zsh()
[docs]@document_func(misc_commands_description["completion"]["zsh"], common_options) def temci__completion__zsh(): subcommands = "\n\t".join(['"{}:{}"'.format(cmd, command_docs[cmd]) for cmd in sorted(command_docs.keys())]) def process_options(options: CmdOptionList, one_line=False): typecheck(options, CmdOptionList) strs = [] for option in sorted(options): multiple = isinstance(option.type_scheme, List) or isinstance(option.type_scheme, ListOrTuple) rounds = 10 if multiple else 1 # hack to allow multiple applications of an option assert isinstance(option, CmdOption) descr = "{}".format(option.description) if option.description is not None else "Undoc" option_str = "--{}".format(option.option_name) if option.has_short: option_str = "{{-{},--{}}}".format(option.short, option.option_name) if option.is_flag: option_str = "{{--{o},--no-{o}}}".format(o=option.option_name) new_completion = "" if option.has_completion_hints and "zsh" in option.completion_hints: new_completion = '{option_str}\"[{descr}]: :{hint}"'.format( option_str=option_str, descr=descr, hint=option.completion_hints["zsh"] ) else: format_str = '{option_str}\"[{descr}]"' if option.is_flag else '{option_str}\"[{descr}]: :()"' new_completion = format_str.format( option_str=option_str, descr=descr ) for i in range(rounds): strs.append(new_completion) if one_line: return " ".join(strs) return "\n\t".join(strs) misc_cmds_wo_subcmds = list(filter(lambda x: isinstance(misc_commands[x], CmdOptionList), misc_commands.keys())) misc_cmds_w_subcmds = list(filter(lambda x: isinstance(misc_commands[x], dict), misc_commands.keys())) ret_str = """ # Auto generated tab completion for the temci ({version}) benchmarking tool. #compdef temci _temci(){{ # printf '%s ' "${{words[@]}}" > /tmp/out local ret=11 state local -a common_opts common_opts=( {common_opts} ) typeset -A opt_args _arguments -C ':subcommand:->subcommand' '2: :->second_level' '*::options:->options' && ret=0 #echo $state > tmp_file local sub_cmd="" case $words[1] in temci) sub_cmd=$words[2] ;; *) sub_cmd=$words[1] esac #echo $words[@] >> tmp_file case $words[2] in ({misc_cmds_wo_subs}) state="options" ;; esac case $state in subcommand) local -a subcommands subcommands=( {subcommands} ) _describe -t subcommands 'temci subcommand' subcommands && ret=0 ;; """.format(common_opts=process_options(common_options), subcommands=" ".join("\"{}:{}\"".format(cmd, command_docs[cmd]) for cmd in command_docs), misc_cmds_wo_subs="|".join(misc_cmds_wo_subcmds), version=temci.scripts.version.version) ret_str += """ second_level) #echo $words[@] > tmp_file case $words[2] in """ for misc_cmd in misc_cmds_w_subcmds: ret_str += """ ({misc_cmd}) #echo "here" > tmp_file local -a subcommands subcommands=( {sub_cmds} ) _describe -t subcommands 'temci subcommand' subcommands && ret=0 && return 0 ;; """.format(misc_cmd=misc_cmd, sub_cmds="\n\t".join("\"{}:{}\"".format(x, misc_commands_description[misc_cmd][x]) for x in misc_commands_description[misc_cmd])) cmds = { "report": { "pattern": r"*\.yaml", "type": "files", "options": report_options, }, "build": { "pattern": r"*\.yaml", "type": "files", "options": build_options }, "format": { "pattern": "*", "type": "any", "options": format_options } } for cmd, conf in cmds.items(): ret_str += r""" ({cmd}) args=( $common_opts {options} ) _arguments "2: :{completion} " $args \ ;; """.format(drivers="|".join(sorted(run_driver.RunDriverRegistry.registry.keys())), options=process_options(conf["options"]), completion={"files": "_files -g '{}'".format(conf["pattern"]), "any": conf["pattern"]}[conf["type"]], cmd=cmd) for name in run_driver.RunDriverRegistry.registry.keys(): ret_str += r""" ({driver}) args=( $common_opts {options} ) _arguments "2: :_files -g '*\.yaml' " $args \ ;; """.format(driver=name, options=process_options(run_options["run_driver_specific"][name])) ret_str += """ esac ;; (options) local -a args args=( $common_opts ) #echo "options" $words[@] > tmp_file case $words[1] in """ for driver in run_driver.RunDriverRegistry.registry.keys(): ret_str += """ {driver}) case $words[2] in *.yaml) args=( $common_opts {opts} ) _arguments "1:: :echo 3" $args && ret=0 ;; *) _arguments "1:: :echo 3" && ret=0 esac ;; """.format(driver=driver, opts=process_options(run_options["run_driver_specific"][driver])) for name in cmds: ret_str += """ ({name}) #echo "({name})" $words[2] #case $words[2] in # {pattern}) args=( $common_opts {options} ) _arguments "1:: :echo 3" $args && ret=0 # ;; # *) # _arguments "1:: :echo 3" && ret=0 #esac ;; """.format(name=name, pattern=cmds[name]["pattern"], options=process_options(cmds[name]["options"])) for misc_cmd in misc_cmds_w_subcmds: ret_str += """ ({misc_cmd}) case $words[2] in """.format(misc_cmd=misc_cmd) for sub_cmd in misc_commands[misc_cmd]["sub_commands"]: ret_str +=""" {sub_cmd}) #echo "{sub_cmd}" $words[@] > tmp_file args+=( {common_opts} {opts} ) #echo "sdf" $args[@] > tmp_file _arguments "1:: :echo 3" $args && ret=0 ;; """.format(sub_cmd=sub_cmd, opts=process_options(misc_commands[misc_cmd]["sub_commands"][sub_cmd]), common_opts=process_options(misc_commands[misc_cmd]["common"])) ret_str += """ esac ;; """ ret_str += """ esac case $sub_cmd in """ for misc_cmd in misc_cmds_wo_subcmds: ret_str += """ {misc_cmd}) # echo "{misc_cmd}" $words[@] >> tmp_file args+=( {opts} ) case $words[2] in $sub_cmd) _arguments "1:: :echo 3" $args && ret=0 ;; *) # echo "Hi" >> tmp_file _arguments $args && ret=0 ;; esac ;; """.format(misc_cmd=misc_cmd, opts=process_options(misc_commands[misc_cmd])) ret_str += """ esac #_arguments $common_opts && ret=0 && return 0 ;; esac } compdef _temci temci=temci """ create_completion_dir() file_name = completion_file_name("zsh") if not os.path.exists(os.path.dirname(file_name)): os.mkdir(os.path.dirname(file_name)) with open(file_name, "w") as f: f.write(ret_str) logging.debug("\n".join("{:>3}: {}".format(i, s) for (i, s) in enumerate(ret_str.split("\n")))) f.flush() os.chmod(file_name, 0o777) print(file_name)
@completion.command(short_help=misc_commands_description["completion"]["bash"]) @cmd_option(common_options) def bash(**kwargs): temci__completion__bash()
[docs]@document_func(misc_commands_description["completion"]["bash"], common_options) def temci__completion__bash(): subcommands = "\n\t".join(sorted(command_docs.keys())) def process_options(options: CmdOptionList) -> str: typecheck(options, CmdOptionList) strs = [] for option in sorted(options.options): strs.append("--" + option.option_name) if option.short is not None: strs.append("-" + option.short) if option.is_flag: strs.append("--no-" + option.option_name) return "\n\t".join(strs) def process_misc_commands(): ret_str = "" for misc_cmd in misc_commands: if "sub_commands" not in misc_commands[misc_cmd]: continue ret_str += """ case ${{COMP_WORDS[1]}} in {misc_cmd}) case ${{COMP_WORDS[2]}} in """.format(misc_cmd=misc_cmd) for sub_cmd in misc_commands[misc_cmd]["sub_commands"].keys(): ret_str += """ {sub_cmd}) args=( ${{common_opts[@]}} {common_opts} {cmd_ops} ) # printf ' _%s ' "${{args[@]}}" >> /tmp/out # printf ' __%s ' "${{args[*]}}" >> /tmp/out COMPREPLY=( $(compgen -W "${{args[*]}}" -- $cur) ) && return 0 ;; """.format(sub_cmd=sub_cmd, cmd_ops=process_options(misc_commands[misc_cmd]["sub_commands"][sub_cmd]), common_opts=process_options(misc_commands[misc_cmd]["common"])) ret_str += """ *) local args=( ) COMPREPLY=( $(compgen -W "" -- $cur) ) && return 0 esac ;; *) ;; esac """ return ret_str def process_misc_commands_case(): ret_str = "" for misc_cmd in misc_commands: args = [] if "sub_commands" in misc_commands[misc_cmd]: args = " ".join(sorted(misc_commands[misc_cmd]["sub_commands"].keys())) else: typecheck(misc_commands[misc_cmd], CmdOptionList) args = process_options(misc_commands[misc_cmd].append(common_options)) ret_str += """ {misc_cmd}) args=({sub_cmds}) ;; """.format(misc_cmd=misc_cmd, sub_cmds=args) return ret_str run_cmd_file_code = "" for driver in run_driver.RunDriverRegistry.registry: run_cmd_file_code += """ {driver}) case ${{COMP_WORDS[2]}} in *.yaml) args=( $common_opts $run_common_opts {driver_opts} ) COMPREPLY=( $(compgen -W "${{args[*]}}" -- $cur) ) && return 0 ;; esac ;; """.format(driver=driver, driver_opts=process_options(run_options["run_driver_specific"][driver])) file_structure = """ # Auto generated tab completion for the temci ({version}) benchmarking tool. _temci(){{ local cur=${{COMP_WORDS[COMP_CWORD]}} local prev=${{COMP_WORDS[COMP_CWORD-1]}} local common_opts=( {common_opts} ) local args=( {common_opts} ) local run_common_opts=( {run_common_opts} ) local report_common_opts=( {report_common_opts} ) local build_common_opts=( {build_common_opts} ) {misc_commands_code} case ${{COMP_WORDS[1]}} in format) args=( $common_opts $format_common_opts ) COMPREPLY=( $(compgen -W "${{args[*]}}" -- $cur) ) && return 0 ;; report) case ${{COMP_WORDS[2]}} in *.yaml) args=( $common_opts $report_common_opts ) COMPREPLY=( $(compgen -W "${{args[*]}}" -- $cur) ) && return 0 ;; esac ;; build) case ${{COMP_WORDS[2]}} in *.yaml) args=( $common_opts $build_common_opts ) COMPREPLY=( $(compgen -W "${{args[*]}}" -- $cur) ) && return 01 ;; esac ;; {run_cmd_file_code} *) ;; esac case ${{COMP_WORDS[1]}} in (report|build|{run_drivers}) local IFS=$'\n' local LASTCHAR=' ' COMPREPLY=($(compgen -o plusdirs -o nospace -f -X '!*.yaml' -- "${{COMP_WORDS[COMP_CWORD]}}")) if [ ${{#COMPREPLY[@]}} = 1 ]; then [ -d "$COMPREPLY" ] && LASTCHAR=/ COMPREPLY=$(printf %q%s "$COMPREPLY" "$LASTCHAR") else for ((i=0; i < ${{#COMPREPLY[@]}}; i++)); do [ -d "${{COMPREPLY[$i]}}" ] && COMPREPLY[$i]=${{COMPREPLY[$i]}}/ done fi return 0 ;; {misc_commands_case_code} *) args=({commands}) esac COMPREPLY=( $(compgen -W "${{args[*]}}" -- $cur) ) }} shopt -s extglob complete -F _temci temci """.format(common_opts=process_options(common_options), run_common_opts=process_options(run_options["common"]), report_common_opts=process_options(report_options), format_common_opts=process_options(format_options), commands=" ".join(sorted(command_docs.keys())), run_drivers="|".join(run_options["run_driver_specific"].keys()), misc_commands_case_code=process_misc_commands_case(), misc_commands_code=process_misc_commands(), build_common_opts=process_options(build_options), run_cmd_file_code=run_cmd_file_code, version=temci.scripts.version.version) create_completion_dir() file_name = completion_file_name("bash") with open(file_name, "w") as f: f.write(file_structure) logging.debug("\n".join("{:>3}: {}".format(i, s) for (i, s) in enumerate(file_structure.split("\n")))) f.flush() os.chmod(file_name, 0o777) print(file_name)
[docs]def cli_with_verb_arg_handling(): """ Handles ` -- ` properly and calls the cli """ if "--" in sys.argv: split_index = sys.argv.index("--") sys.argv = sys.argv[:split_index] + [" ".join(sys.argv[split_index + 1:])] cli()
[docs]def cli_with_error_catching(): """ Process the command line arguments and catch (some) errors. """ try: locale.setlocale(locale.LC_ALL, "en_US.UTF-8") except: pass try: cli_with_verb_arg_handling() except EnvironmentError as err: logging.error(err) exit(1) except TypeError as err: logging.error(err) import traceback logging.debug("".join(traceback.format_exception(None, err, err.__traceback__))) exit(1)
@cli.command(short_help=command_docs["setup"]) @cmd_option(misc_commands["setup"]) def setup(**kwargs): temci__setup(**kwargs)
[docs]@document_func(command_docs["setup"], misc_commands["setup"]) def temci__setup(build_kernel_modules: bool): from temci.setup.setup import make_scripts make_scripts(build_kernel_modules)
if sphinx_doc(): Settings.__doc__ += """ The whole configuration file has the following structure: """ + get_doc_for_type_scheme(Settings().type_scheme) if __name__ == "__main__": # for testing purposes only cli()