Ejemplo n.º 1
0
def __handle_new_tool_arg(in_args):
    if len(in_args) < 1:
        log.error("--new_tool requires a value.")
        log.normal("\t--new_tool [config_type]")
        return
    module_dir = os.path.relpath(__file__)
    module_dir = os.path.dirname(module_dir)
    config_type = in_args.pop(0)
    config_type_dir = os.path.join(module_dir, config_type)
    if not os.path.exists(config_type_dir):
        module_dir = os.path.join(module_dir, "new_tool")
        os.mkdir(config_type_dir)
        files = [
            "__init__.py", "help.md", "default.py", "config/__init__.py",
            "options/__init__.py", "options/tool.py"
        ]
        for file_name in files:
            with open(os.path.join(module_dir, file_name)) as in_file:
                file_str = in_file.read()
                file_str = file_str.format_map({"config_type": config_type})
                tool_file = os.path.join(config_type_dir, file_name)
                os.makedirs(os.path.dirname(tool_file), exist_ok=True)
                with open(tool_file, "w") as out_file:
                    out_file.write(file_str)
        log.success("created " + config_type + " config_type!")
        log.normal("generate a config file by calling: " +
                   "'./confply.py --new_config " + config_type +
                   " my_config.py'")
    else:
        log.error(config_type + " already exists. (--new_tool)")
        pass
Ejemplo n.º 2
0
def __handle_in_arg(in_args):
    if len(in_args) < 1:
        log.error("--in requires a value.")
        log.normal("\t--in [config_path]")
        return
    in_path = in_args.pop(0)
    confply.config.config_path = in_path
Ejemplo n.º 3
0
def handle_args():
    if "--cpp_clean" in config.confply.args or config.clean:
        if os.path.exists(config.object_path):
            log.normal("cleaning compiled objects")
            os.system("rm -r " + config.object_path)
        else:
            log.normal("no objects to remove")
Ejemplo n.º 4
0
def __handle_version_arg(in_args):
    log.linebreak()
    log.normal("Confply " + get_version())
    log.normal("Copyright (C) 2021 Graham Hughes.")
    log.normal("License MIT.")
    log.normal("This is free software; " +
               "you are free to change and redistribute it.")
    log.normal("There is NO WARRANTY, to the extent permitted by law.")
Ejemplo n.º 5
0
 def _print_tools():
     num = -1
     for k in in_tools.keys():
         num += 1
         if not in_tools[k].is_found():
             log.warning("\t" + str(num) + ") " + k + " (not found)")
         else:
             log.normal("\t" + str(num) + ") " + k)
Ejemplo n.º 6
0
def on_complete():
    import confply.log as log
    import os
    if os.path.exists("libfwcore.a"):
        os.system("rm libfwcore.a")
    os.system("ar rcs libfwcore.a objects/fwcore/*.o")
    log.normal("")
    log.normal("output built libs to libfwcore.a")
Ejemplo n.º 7
0
def __handle_listen_arg(in_args):
    if len(in_args) < 1:
        log.error("--listen requires a value.")
        log.normal("\t--listen [launcher_file]")
        return

    arguement = in_args.pop(0)
    launcher_path = os.path.abspath(os.path.curdir) + "/" + arguement
    if os.path.exists(launcher_path):
        with pushd(os.path.dirname(__file__)):
            confply.server.start_server(launcher=launcher_path)
    else:
        log.error(launcher_path + " not found!")
Ejemplo n.º 8
0
def __print_config(config_name, config):
    diff_config = __get_diff_config(config)
    config_type_path = config.__file__

    if (os.path.exists(config_type_path)):
        log.normal(config_name + " configuration:")
        log.normal("")

        def print_dict(d1, depth=0):
            for k, v in d1.items():
                if isinstance(v, list):
                    log.bold("\t" * depth + log.format.bold(str(k)) + ": ")
                    for i in v:
                        log.normal("\t" * (depth + 1) + str(i))
                elif isinstance(v, dict):
                    log.normal("\t" * depth + log.format.bold(k) + ":")
                    print_dict(v, depth=depth + 1)
                    pass
                elif inspect.isfunction(v):
                    log.normal("\t" * depth + log.format.bold(str(k)) + ": " +
                               v.__name__)
                else:
                    log.normal("\t" * depth + log.format.bold(str(k)) + ": " +
                               str(v))

        if "confply" in diff_config:
            del diff_config["confply"]
        print_dict(diff_config)
        log.normal("")
    else:
        log.error(confply.config_config_type +
                  " is not a valid confply_config_type" +
                  " and should not be set by users.")
        log.normal("\tuse: 'import confply.[config_type].config" +
                   " as confply' to import confply_config_type.")
Ejemplo n.º 9
0
def __apply_overrides(config):
    # update the config and confply.config dictionaries with overrides
    if isinstance(confply.config.__override_dict, dict):
        confply_dict = confply.config.__override_dict
        config.confply.__dict__.update(confply_dict["confply"])
        del confply_dict["confply"]
        config.__dict__.update(confply_dict)
        confply.config.__override_dict = {"confply": {}}

    # update the configs with further overrides
    if isinstance(confply.config.__override_list, list):
        for k, v in confply.config.__override_list:
            try:
                exec("{0} = v".format(k), globals(), locals())
            except Exception:
                log.warning("failed to exec " + "{0} = {1}:".format(k, v))
                log.normal("\t\tcheck calling option  --" + k)
Ejemplo n.º 10
0
def __validate_config(config):
    tools = {}
    tool_dir = os.path.dirname(config.__file__)
    tool_dir = os.path.join(tool_dir, "..")
    if os.path.exists(tool_dir):
        files = os.listdir(tool_dir)
    else:
        log.error(config.__package__ + " is not a valid confply_config_type" +
                  " and should not be set by users.")
        log.normal("\tuse: " +
                   "'import confply.[config_type].config as config'" +
                   " to import confply_config_type.")
        return None

    tools = {}
    module_path = config.__package__.rsplit(".", 1)[0]
    for py in files:
        if py.endswith(".py") and not py == "__init__.py":
            tool = py[0:-3]
            tools[tool] = \
                importlib.import_module(module_path+"."+tool)

    tool = confply.config.tool
    pass

    #######
    if tool in tools:
        if not tools[tool].is_found():
            log.error("'" + tool + "' could not be found, is it installed?")
            if __tool_select(tools):
                return tools
            else:
                return None
        else:
            return tools
    else:
        log.error("'" + str(tool) + "' is not a valid tool.")
        if __tool_select(tools):
            return tools
        else:
            return None

    return tools
Ejemplo n.º 11
0
def __tool_select(in_tools):
    def _print_tools():
        num = -1
        for k in in_tools.keys():
            num += 1
            if not in_tools[k].is_found():
                log.warning("\t" + str(num) + ") " + k + " (not found)")
            else:
                log.normal("\t" + str(num) + ") " + k)

    shown_options = False
    while True:
        if input_prompt("continue with a different tool?"):
            if not shown_options:
                log.normal("which tool? options:")
                _print_tools()
                log.normal("")
                shown_options = True
            log.normal("tool: ", end="", flush=True)
            in_tool = input("")
            if (in_tool.isdigit()):
                tool_num = int(in_tool)
                if tool_num < len(in_tools):
                    tool_keys = list(in_tools.keys())
                    confply.config.tool = tool_keys[tool_num]
                    return True
                else:
                    log.error("'" + in_tool + "' is out of range.")
                pass
            else:
                if in_tool in in_tools:
                    confply.config.tool = in_tool
                    return True
                else:
                    log.error("'" + in_tool + "' could not be found," +
                              " is it installed?")
        else:
            if not shown_options:
                log.normal("options:")
                _print_tools()
                log.normal("")
            return False
Ejemplo n.º 12
0
def run_dict(in_dict):
    """
    runs the confply dict for the supplied config_type

    usage: run_dict(in_dict)
    """
    log.linebreak()
    log.header("run config")
    log.linebreak()

    # setup config run
    should_run = confply.config.run
    if ("config_path" in in_dict["confply"]):
        path = in_dict["confply"]["config_path"]
    else:
        path = None
    __load_vcs_info(path)
    confply.config.config_path = path
    config_name = os.path.basename(path)
    confply.config.config_name = config_name
    confply.config.modified = os.path.getmtime(path).real
    config_locals = apply_to_config(in_dict)
    if not config_locals:
        log.error("failed to load:  json")
        return -1

    if ("config" not in config_locals):
        log.error("confply failed import")
        log.normal(
            "\tuse: '__package__': 'confply.[config_type].config' in json/ini")
        clean_modules()
        return -1

    if (not __validate_types(config_locals["config"])):
        log.error("failed to run config")
        return -1

    # ensure we don't run if should_run was EVER false
    if should_run is not True:
        confply.config.run = should_run
    return __run_config(config_locals)
Ejemplo n.º 13
0
def __run_dependencies(config, should_run):
    store = config_to_dict(config)
    importlib.reload(config)
    importlib.reload(config.confply)
    confply.config.run = should_run
    depends_return = 0
    if len(store["confply"]["dependencies"]) > 0:
        for d in store["confply"]["dependencies"]:
            if d not in __configs_run:
                confply.config.log_topic = store["confply"]["log_topic"]
                log.normal("running dependency: " + str(d))
                confply.config.log_topic = "confply"
                log.linebreak()
                __configs_run.add(d)
                depends_return = run_commandline(["--in", d])
                if depends_return < 0:
                    confply.config.log_topic = store["confply"]["log_topic"]
                    confply.config.log_file = store["confply"]["log_file"]
                    log.error("failed to run: " + str(d))
                    if not input_prompt("continue execution?"):
                        log.normal("aborting final commands")
                        break
                    else:
                        log.normal("continuing execution.")
        pass
    # reset confply.config
    apply_to_config(store)
    # #todo: make this jump to the mail section
    return depends_return
Ejemplo n.º 14
0
 def print_dict(d1, depth=0):
     for k, v in d1.items():
         if isinstance(v, list):
             log.bold("\t" * depth + log.format.bold(str(k)) + ": ")
             for i in v:
                 log.normal("\t" * (depth + 1) + str(i))
         elif isinstance(v, dict):
             log.normal("\t" * depth + log.format.bold(k) + ":")
             print_dict(v, depth=depth + 1)
             pass
         elif inspect.isfunction(v):
             log.normal("\t" * depth + log.format.bold(str(k)) + ": " +
                        v.__name__)
         else:
             log.normal("\t" * depth + log.format.bold(str(k)) + ": " +
                        str(v))
Ejemplo n.º 15
0
def input_prompt(message):
    """
    prompt the user for a Y/N answer on a 10 second timeout
    """
    if os.name != "nt":
        while True:
            log.normal(message + " (Y/N): ", end="", flush=True)
            select_args = ([sys.stdin], [], [], 10)
            rlist, _, _ = select.select(*select_args)
            if rlist:
                answer = sys.stdin.readline()
                answer = answer.upper()
                answer = answer.replace("\n", "")
                if answer == "YES" or answer == "Y":
                    return True

                elif answer == "NO" or answer == "N":
                    return False
            else:
                print("")
                log.normal("timed out after 10 seconds")
                return False
    else:
        return False
Ejemplo n.º 16
0
def __handle_launcher_arg(in_args):
    if len(in_args) < 1:
        log.error("--launcher requires a value.")
        log.normal("\t--launcher [new_launcher_file]")
        return
    confply_dir = __get_confply_dir()
    arguement = in_args.pop(0)
    launcher_path = os.path.abspath(os.path.curdir) + "/" + arguement
    if not os.path.exists(launcher_path):
        with open(launcher_path, "w") as launcher_file:
            launcher_str = __new_launcher_str.format_map({
                "confply_dir":
                confply_dir,
                "launcher":
                arguement,
                "comment":
                "{\n    # 'myconfig':'path/to/config.py'\n}"
            })
            launcher_file.write(launcher_str)
        st = os.stat(launcher_path)
        os.chmod(launcher_path, st.st_mode | stat.S_IEXEC)
        log.success("wrote: " + launcher_path)
    else:
        log.error(launcher_path + " already exists!")
Ejemplo n.º 17
0
def _handle_config_dict_arg(in_args):
    if len(in_args) < 1:
        log.error("--config requires a value.")
        log.normal("\t--config \"{'confply':{'tool':'cl'}}\"")
        return
    overide_dict = None
    try:
        overide_dict = ast.literal_eval(in_args.pop(0))
        if not isinstance(overide_dict, dict):
            log.error("--config must be a dictionary.")
            log.normal("\t--config \"{'confply':{'tool':'cl'}}\"")
            return
        elif "confply" in overide_dict:
            if not isinstance(overide_dict["confply"], dict):
                log.error("--config.confply must be a dictionary.")
                log.normal("\t--config \"{'confply':{'tool':'cl'}}\"")
                return
        else:
            overide_dict["confply"] = {}
    except Exception:
        log.error("--config failed to parse argument as a dictionary")
        return

    confply.config.__override_dict.update(overide_dict)
Ejemplo n.º 18
0
#!../tools/confply/confply.py
# generated using:
# python ../tools/confply/confply.py --config cpp_compiler build.py
import sys
sys.path.append('../tools/confply')
import confply.cpp_compiler.config as confply
import confply.log as log
import os

confply.confply_log_topic = "fwcore"
log.normal("loading build.py with confply_args: " + str(confply.confply_args))

confply.confply_tool = "clang++"
confply.output_executable = False
confply.object_path = "objects/fwcore"
confply.include_paths = ["fmt/include/"]
confply.source_files = [
    "fmt/src/format.cc",
    "fmt/src/os.cc",
]


def on_complete():
    import confply.log as log
    import os
    if os.path.exists("libfwcore.a"):
        os.system("rm libfwcore.a")
    os.system("ar rcs libfwcore.a objects/fwcore/*.o")
    log.normal("")
    log.normal("output built libs to libfwcore.a")
Ejemplo n.º 19
0
#!../confply.py --in
# generated using:
# python ../confply.py --config cpp_compiler cpp_compiler.cpp.py
import sys
sys.path.append('..')
import confply.cpp_compiler.config as config
import confply.cpp_compiler.options as options
import confply.log as log
############# modify_below ################

config.confply.log_topic = "cpp_compiler"
log.normal("loading cpp_compiler with confply_args: " +
           str(config.confply.args))

config.source_files = ["main.cpp"]
config.output_file = "hello_confply"
config.link_libraries = ["stdc++"]
config.standard = options.standard.cpp17
config.warnings = options.warnings.all_warnings
config.confply.log_config = True


def post_run():
    import subprocess
    import sys
    subprocess.run("./hello_confply",
                   stdout=sys.stdout,
                   stderr=subprocess.STDOUT,
                   shell=True)
    pass
Ejemplo n.º 20
0
#!/usr/bin/env python
import os
import sys
import confply
import confply.log as log

if __name__ == "__main__":
    in_args = sys.argv[1:]
    version = sys.version_info
    version = (version.major, version.minor, version.micro)
    if "--no_header" not in in_args:
        log.confply_header()
        log.linebreak()
        log.normal("python" + str(version))
        log.normal("confply " + confply.get_version())
        log.normal("date: " + str(confply.datetime.now()))
    if (version[0] < 3 or (version[0] == 3 and version[1] < 8)):
        log.error("python version must be 3.8 or above")
        log.linebreak()
        exit(1)

    return_code = -999999
    if len(in_args) != 0:
        while len(in_args) > 0:
            cmd_return = confply.run_commandline(in_args)

            if (cmd_return > return_code and cmd_return != 0):
                return_code = cmd_return

            # fatal error.
            if return_code == -1:
Ejemplo n.º 21
0
import ast
import os
sys.path.append('.')
import confply.cpp_compiler.config as config
import confply.cpp_compiler.options as options
import confply.log as log
############# modify_below ################
# set the default compiler
config.confply.tool = options.tool.clangpp

# set debug_info from commandline args
debug = False
if "debug" in config.confply.args:
    debug = True
    config.object_path = "objects/debug"
    log.normal("set to debug config")

config.debug_info = debug
config.confply.mail_to = "*****@*****.**"
config.confply.mail_from = "*****@*****.**"
# config.confply.log_file = "confply.log"
config.confply.log_debug = True
mail_login = ()
slack_bot = ""
if os.path.exists("mail_details.py"):
    with open("mail_details.py") as details_file:
        mail_login = ast.literal_eval(details_file.read())
if os.path.exists("slack_details.py"):
    with open("slack_details.py") as details_file:
        slack_bot = ast.literal_eval(details_file.read())
config.confply.__mail_login = mail_login
Ejemplo n.º 22
0
def __handle_new_config_arg(in_args):
    if len(in_args) < 2:
        log.error("--config requires two values:")
        log.normal("\t--new_config [config_type] [new_config_file]")
        log.normal("")
        log.normal("valid tool types:")
        module_dir = os.path.dirname(__file__)
        files = os.listdir(module_dir)
        for dir in files:
            if (os.path.isdir(os.path.join(module_dir, dir))
                    and not dir == "__pycache__" and not dir == "new_tool"):
                log.normal("\t" + dir)
        return

    confply_dir = __get_confply_dir()
    config_type_arg = in_args.pop(0)
    config_arg = in_args.pop(0)
    config_path = os.path.abspath(os.path.curdir) + "/" + config_arg
    config_type_dir = os.path.dirname(os.path.relpath(__file__))
    config_type_dir = os.path.join(config_type_dir, config_type_arg)

    if not os.path.exists(config_type_dir):
        log.error(config_type_arg + " is not a valid config_type, consider:")
        for dir_file in os.listdir(confply_dir + "/confply/"):
            if os.path.isdir(confply_dir + "/confply/" + dir_file):
                if not dir_file == "__pycache__":
                    log.normal("\t" + dir_file)
        return

    hash_file = os.path.join(config_type_dir, "config/__init__.py")
    config_hash = md5_file(hash_file)
    if not os.path.exists(config_path):
        with open(config_path, "w") as config_file:
            config_str = __new_config_str.format_map({
                "confply_dir": confply_dir,
                "config_type_arg": config_type_arg,
                "config_file": config_arg,
                "config_hash": config_hash
            })
            config_file.write(config_str)
        st = os.stat(config_path)
        os.chmod(config_path, st.st_mode | stat.S_IEXEC)
        log.success("wrote: " + config_path)
    else:
        log.error(config_path + " already exists!")
        log.normal("aborted --new_config.")
Ejemplo n.º 23
0
def __handle_config_arg(option, in_args):
    global logged_overrides
    if len(in_args) < 1:
        log.error("--config requires a value.")
        log.normal("\t--config.confply.tool \"cl\"")
        return

    path = option.split(".")[1:]
    if len(path) == 0:
        log.error("--config invalid path.")
        log.normal("\t--config.confply.tool \"cl\"")
        return

    if path[0] == "confply" and len(path) == 1:
        log.error("--config invalid path, cannot set confply")
        log.normal("\t--config.confply.tool \"cl\"")
        return
    # #todo: this is pretty shit, it doesn't solve the general case at all
    #  but I'm being lazy you should be able to set values in a deep dictionary
    #  but you can't.
    arg = in_args.pop(0)
    value = None
    try:
        value = ast.literal_eval(arg)
    except Exception:
        value = arg

    # #todo: this should be done prior to running the config. not now.
    # this logging section is lazy af.
    if not logged_overrides:
        logged_overrides = True
        log.normal("overrides:")

    if isinstance(value, str):
        log.normal("\t" + option[2:] + " = \"" + str(value) + "\" <" +
                   type(value).__name__ + ">")
    else:
        log.normal("\t" + option[2:] + " = " + str(value) + " <" +
                   type(value).__name__ + ">")
    confply.config.__override_list.append([option[2:], value])
Ejemplo n.º 24
0
def run_commandline(in_args):
    """
    runs the confply config, with supplied arguements.
    confply reservered options will be stripped. e.g. --help
    see help.md

    usage: run_commandline(["path_to_config", "optional", "arguements"])
    """
    log.normal("called with args: " + str(in_args))
    in_args = __strip_confply_args(in_args)
    confply.config.args = in_args
    if confply.config.config_path:
        config_path = confply.config.config_path
        if not os.path.exists(config_path):
            log.error("couldn't find: " + config_path)
            return -1
        if config_path.endswith(".py"):
            log.linebreak()
            log.header("run config")
            log.linebreak()
            # setup config run
            should_run = confply.config.run
            config_locals = load_config(config_path)
            if not config_locals:
                log.error("failed to load: " + config_path)
                return -1

            if ("config" not in config_locals):
                log.error("confply config incorrectly imported")
                log.normal(
                    "\tuse: 'import confply.[config_type].config as config'")
                clean_modules()
                return -1

            config = config_locals["config"]
            if (not __validate_types(config)):
                log.error("failed to run config")
                return -1
            # ensure we don't run if should_run was EVER false
            if should_run is not True:
                confply.config.run = should_run
            # config
            config_hash = md5_file(config.__file__)
            if ("config_hash" not in config_locals
                    or config_hash != config_locals["config_hash"]):
                log.warning("warning: config_hash doesn't match expected hash")
                log.normal("\tconfig file might not function correctly")
                log.normal("\texpected:")
                log.normal("\t\t" + "config_hash='" + config_hash + "'")
                log.normal("")
            return __run_config(config_locals)

        elif config_path.endswith(".json"):
            if os.path.exists(config_path):
                with open(config_path) as in_json:
                    in_dict = json.loads(in_json.read())
                    in_dict["confply"].update({"config_path": config_path})
                    return run_dict(in_dict)
        elif config_path.endswith(".ini"):
            if os.path.exists(config_path):
                import configparser

                def parse_lit(in_val):
                    try:
                        return ast.literal_eval(in_val)
                    except Exception:
                        return in_val

                conf = configparser.ConfigParser()
                conf.read(config_path)
                in_dict = {"confply": {"config_path": config_path}}
                for (key, val) in conf["config"].items():
                    in_dict[key] = parse_lit(val)
                for (key, val) in conf["confply"].items():
                    in_dict["confply"][key] = parse_lit(val)
                return run_dict(in_dict)
        else:
            log.error("unsupported config type: " + config_path)
            return -1
    else:
        return 0
    return 0
Ejemplo n.º 25
0
def load_config(path):
    global config_modules
    if os.name == "nt":
        confply.config.platform = "windows"
    elif os.name == "posix":
        confply.config.platform = "linux"

    __load_vcs_info(path)
    # find group config in parent directories
    directory_paths = __get_group_configs(path)
    directory_paths.append(path)
    config_locals = {}
    # load and execute the config files
    for dir_path in directory_paths:
        if dir_path is None:
            continue
        if os.path.exists(dir_path) and os.path.isfile(dir_path):
            config_name = os.path.basename(dir_path)
            confply.config.config_name = config_name
            confply.config.modified = os.path.getmtime(dir_path).real
            with open(dir_path) as config_file:
                with pushd(os.path.dirname(dir_path)):
                    try:
                        exec(config_file.read(), {}, config_locals)
                        # find imported confply configs for cleanup
                        for k, v in config_locals.items():
                            m_valid = isinstance(v, types.ModuleType)
                            if not m_valid:
                                continue

                            v_name = v.__name__
                            m_valid = m_valid and v not in config_modules
                            m_valid = m_valid and v_name.startswith("confply.")
                            m_valid = m_valid and v_name.endswith(".config")
                            if m_valid:
                                config_modules.add(v)

                        # validate there are less than 2 imported configs
                        if len(config_modules) > 1:
                            log.error("too many confply configs imported:")
                            for c in config_modules:
                                log.normal("\t " + c)
                            log.normal(
                                "confply only supports one config import.")
                            clean_modules()
                            return None, None

                        log.linebreak()
                        log.success("loaded: " + str(dir_path))
                    except Exception:
                        log.error("failed to exec: " + str(dir_path))
                        trace = traceback.format_exc().replace(
                            "<string>", str(dir_path))
                        log.normal("traceback:\n\n" + trace)
                        return None, None

        else:
            log.error("failed to find: " + str(dir_path))
            return None, None

    return config_locals
Ejemplo n.º 26
0
def __run_config(config_locals):
    in_args = confply.config.args
    config = config_locals["config"]
    return_code = 0
    should_run = confply.config.run
    file_path = confply.config.config_path
    __apply_overrides(config)
    new_working_dir = os.path.dirname(file_path)
    old_stdout = sys.stdout
    # setting confply command configuration up
    with pushd(new_working_dir):
        if confply.config.log_file:
            log.normal("writing to: " + confply.config.log_file + "....")
            try:
                sys.stdout = open(confply.config.log_file, "w")
                version = sys.version_info
                version = (version.major, version.minor, version.micro)
                if "--no_header" not in in_args:
                    log.confply_header()
                    log.linebreak()
                    log.normal("python" + str(version))
                    log.normal("confply " + get_version())
                    log.normal("date: " + str(datetime.now()))
                    log.linebreak()
                log.normal("confply logging to " + confply.config.log_file)
            except Exception:
                log.error("couldn't open " + confply.config.log_file +
                          " for write.")
                return_code = -1
        try:
            if (confply.config.post_load
                    and inspect.isfunction(confply.config.post_load)):
                log.normal("running post load script: " +
                           confply.config.post_load.__name__)
                sys.stdout.flush()
                exec(confply.config.post_load.__code__, config_locals, {})
                log.linebreak()

        except Exception:
            log.error("failed to exec " + confply.config.post_load.__name__)
            trace = traceback.format_exc()
            log.normal("traceback:\n\n" + trace)
            pass

        diff_config = __get_diff_config(config)
        should_run = confply.config.run
        report = {
            "config_path": file_path,
            "config_json": json.dumps(diff_config, indent=4),
            "config_type": "unknown",
            "tool": "unknown",
            "status": "failure",
            "vcs_root": confply.config.vcs_root,
            "vcs_log": confply.config.vcs_log,
            "vcs": confply.config.vcs,
            "vcs_branch": confply.config.vcs_branch,
            "vcs_author": confply.config.vcs_author,
            "time_taken": "00:00:00"
        }
        if return_code >= 0:
            if confply.config.log_config is not False:
                __print_config(os.path.basename(file_path), config)
            try:
                time_start = timeit.default_timer()
                # #todo: tool selection phase should happen first.
                tools = __validate_config(config)
                config_type = config.__package__
                tool = confply.config.tool
                report["tool"] = tool
                report["config_type"] = config_type
                if tools:
                    shell_cmd = tools[tool]
                    shell_cmd.handle_args()
                    # #todo: rename generate to gen_config_type.
                    shell_cmd = shell_cmd.generate() if tools else None
                else:
                    shell_cmd = None

                __run_dependencies(config, should_run)

                if shell_cmd is not None:
                    cmd_env = tools[tool].get_environ()
                    if len(shell_cmd) > 0:
                        if isinstance(shell_cmd, list):
                            log.normal("final commands:\n")
                            for shell_str in shell_cmd:
                                cmd = confply.config.command_prepend + shell_str
                                cmd = cmd + confply.config.command_append
                                print(cmd)
                            print("")
                        else:
                            cmd = confply.config.command_prepend + shell_cmd
                            cmd = shell_cmd + confply.config.command_append
                            log.normal("final command:\n\n" + str(cmd) + "\n")
                        if should_run:
                            log.header("begin " + tool)
                    sys.stdout.flush()

                    if should_run and isinstance(shell_cmd, list):
                        for cmd in shell_cmd:
                            cmd_time_start = timeit.default_timer()
                            sys.stdout.flush()
                            log.linebreak()
                            cmd = confply.config.command_prepend + cmd
                            cmd = cmd + confply.config.command_append
                            log.normal(cmd)
                            log.normal("", flush=True)
                            return_code = __run_shell_cmd(cmd, cmd_env, tool)
                            cmd_time_end = timeit.default_timer()
                            # #todo: this can be tidied with format var capture
                            s = cmd_time_end - cmd_time_start
                            m = int(s / 60)
                            h = int(m / 60)
                            # time formating via format specifiers
                            # https://docs.python.org/3.8/library/string.html#formatspec
                            time = f"{h:0>2.0f}:{m:0>2.0f}:{s:0>5.2f}"
                            log.normal("time elapsed " + time)
                    elif should_run:
                        return_code = __run_shell_cmd(shell_cmd, cmd_env, tool)
                    else:
                        log.warning("no commands run")
                else:
                    log.error("failed to generate a valid command.")
                    return_code = -1

                time_end = timeit.default_timer()
                s = time_end - time_start
                m = int(s / 60)
                h = int(m / 60)
                # time formating via format specifiers
                # https://docs.python.org/3.8/library/string.html#formatspec
                time = f"{h:0>2.0f}:{m:0>2.0f}:{s:0>5.2f}"
                log.normal("total time elapsed " + time)
                report["time_taken"] = time
                report["status"] = "success" if return_code == 0 else "failure"

            except Exception:
                log.error("failed to run config: ")
                trace = traceback.format_exc()
                log.normal("traceback:\n\n" + trace)
                return_code = -1
            sys.stdout.flush()
            if (confply.config.post_run
                    and inspect.isfunction(confply.config.post_run)):
                try:
                    log.linebreak()
                    log.normal("running post run script: " +
                               confply.config.post_run.__name__)
                    sys.stdout.flush()
                    exec(confply.config.post_run.__code__, config_locals, {})
                    log.linebreak()
                except Exception:
                    log.error("failed to exec " +
                              confply.config.post_run.__name__)
                    trace = traceback.format_exc()
                    log.normal("traceback:\n\n" + trace)
            log.normal("date: " + str(datetime.now()))
            log.linebreak()
            sys.stdout.flush()

            if sys.stdout != old_stdout:
                sys.stdout.close()
                sys.stdout = old_stdout
                if confply.config.log_echo_file:
                    with open(confply.config.log_file) as out_log:
                        log_str = out_log.read()
                        log_str = log_str.split("confply logging to " +
                                                confply.config.log_file)[1]
                        log.normal("wrote:" + log_str)

            if (confply.config.mail_send == report["status"]
                    or confply.config.mail_send == "all"):
                mail.host = confply.config.__mail_host
                mail.sender = confply.config.mail_from
                mail.recipients = confply.config.mail_to
                mail.login = confply.config.__mail_login
                mail.attachments = confply.config.mail_attachments
                if (confply.config.log_file and report["status"] == "failure"):
                    mail.attachments.append(
                        os.path.abspath(confply.config.log_file))
                    pass
                if mail.login:
                    mail.send_report(report)

            if (confply.config.slack_send == report["status"]
                    or confply.config.slack_send == "all"):
                slack.bot_token = confply.config.__slack_bot_token
                slack.uploads = confply.config.slack_uploads
                if (confply.config.log_file and report["status"] == "failure"):
                    slack.uploads.append(
                        os.path.abspath(confply.config.log_file))
                if slack.bot_token:
                    slack.send_report(report)
    clean_modules()
    return return_code
Ejemplo n.º 27
0
def generate():
    object_path = config.object_path
    object_path = os.path.join(object_path, tool)

    def gen_command(config, source=None):
        command = ""
        command += tool + " " + config.command_prepend + " "
        command += include + " " + (" " + include + " ").join(
            config.include_paths) + " " if config.include_paths else ""
        command += define + " " + (" " + define + " ").join(
            config.defines) + " " if config.defines else ""
        command += debug + " " if config.debug_info else ""
        command += standard + config.standard + " " if config.standard else ""
        command += gen_warnings()
        command += optimisation + str(
            config.optimisation) + " " if config.optimisation else ""
        if source is None:
            command += " ".join(
                config.source_files) + " " if config.source_files else ""
            command += output_exe + config.output_file + " " if config.output_file else output_exe + "app.bin"
            command += pass_to_linker + " "
            command += library + (" " + library).join(
                config.library_paths) + " " if config.library_paths else ""
            command += link + " " + (" " + link + " ").join(
                config.link_libraries) + " " if config.link_libraries else ""
        else:
            command += build_object + " " + source + " " + output_obj + os.path.join(
                object_path,
                os.path.basename(source) + object_ext + " ")
            command += exception_handling + " "
            if config.track_dependencies:
                command += dependencies + " " + dependencies_output + " " + os.path.join(
                    object_path,
                    os.path.basename(source) + ".d ")
        return command + " " + config.command_append

    if config.build_objects:
        os.makedirs(object_path, exist_ok=True)
        commands = []
        sources = config.source_files
        objects = []
        output_time = config.output_file if config.output_file else "app.bin"
        output_time = os.path.getmtime(output_time).real if os.path.exists(
            output_time) else 0
        should_link = False
        tracking_md5 = config.track_checksums
        tracking_depends = config.track_dependencies
        config_name = config.confply.config_name if os.path.exists(
            config.confply.config_name) else None

        # generate checksums
        def md5(fname):
            hash_md5 = hashlib.md5()
            with open(fname, "rb") as f:
                for chunk in iter(lambda: f.read(4096), b""):
                    hash_md5.update(chunk)
            return hash_md5.hexdigest()

        tracking = {}
        tracking_path = os.path.join(object_path, "tracking.py")

        if tracking_md5 or tracking_depends:
            if os.path.exists(tracking_path):
                with open(tracking_path, "r") as tracking_file:
                    tracking = ast.literal_eval(tracking_file.read())

        def update_tracking(file_path):
            nonlocal tracking
            if os.path.exists(file_path):
                file_time = os.path.getmtime(file_path).real
                if file_path in tracking:
                    if file_time > tracking[file_path]["t"]:
                        if tracking_md5:
                            old_md5 = tracking[file_path][
                                "h"] if "h" in tracking[file_path] else None
                            new_md5 = md5(file_path)
                            tracking[file_path].update({
                                "t": file_time,
                                "h": new_md5
                            })
                            return old_md5 != new_md5
                        else:
                            tracking[file_path].update({"t": file_time})
                            return True
                    else:
                        return False
                elif tracking_md5:
                    tracking[file_path] = {"t": file_time, "h": md5(file_path)}
                    return True
                else:
                    tracking[file_path] = {"t": file_time}
                    return True
                pass
            return False

        compile_all = update_tracking(
            config_name) if config.rebuild_on_change else False

        for source_path in sources:
            should_compile = compile_all
            if os.path.exists(source_path):
                deps_path = os.path.join(object_path,
                                         os.path.basename(source_path + ".d"))
                obj_path = os.path.join(
                    object_path, os.path.basename(source_path + object_ext))
                obj_time = os.path.getmtime(obj_path).real if os.path.exists(
                    obj_path) else 0
                objects.append(obj_path)
                # dependency tracking
                if tracking_depends and os.path.exists(deps_path):
                    with open(deps_path, "r") as deps_file:
                        deps_string = deps_file.read()
                        for dep_path in parse_deps(deps_string):
                            should_compile = update_tracking(
                                dep_path) or should_compile
                else:
                    should_compile = update_tracking(
                        source_path) or should_compile

                if should_compile or obj_time == 0:
                    commands.append(gen_command(config, source_path))
                    should_link = True
                elif obj_time > output_time:
                    should_link = True

            else:
                log.warning(source_path + " could not be found")

        if should_link and config.output_executable:
            config.source_files = objects
            commands.append(gen_command(config))
            config.source_files = sources
            num_commands = len(commands)
            log.normal(str(num_commands) + " files to compile")
        else:
            log.normal("no files to compile")

        if tracking_md5 or tracking_depends:
            with open(tracking_path, "w") as tracking_file:
                tracking_file.write("# do not edit this file.\n")
                tracking_file.write(json.dumps(tracking, indent=4))
        return commands
    else:
        return gen_command(config)
Ejemplo n.º 28
0
aliases = {comment}

# "all" will run all of the aliases
aliases["all"] = " -- ".join([val for key, val in aliases.items()])

if __name__ == "__main__":
    if "--listen" in sys.argv:
        return run_commandline(["--listen", __file__])
    else:
        dir_name = os.path.dirname(__file__)
        if not dir_name == "":
            os.chdir(dir_name)
        launcher(sys.argv[1:], aliases)
"""

__new_config_str = """#!{confply_dir}/confply.py --in
# generated using:
# python {confply_dir}/confply.py --config {config_type_arg} {config_file}
import sys
sys.path.append('{confply_dir}')
import confply.{config_type_arg}.config as config
import confply.{config_type_arg}.options as options
import confply.log as log
config_hash = '{config_hash}'
############# modify_below ################

config.confply.log_topic = "{config_type_arg}"
log.normal("loading {config_file} with confply_args: "+str(config.confply.args))
"""
# list of configs that have already been run
__configs_run = set()