1"""
2Configuration file core loading functions
3"""
4import pathlib
5
6import dict_tools.update
7
8
9def parse(hub, raw, cli, os_vars, cli_args, loader):
10    """
11    Determine if a config file or a config dir has been set up and load it up!
12    """
13    # This function is the entry point for the config.conf_file sub
14    # Figure out what config file value to use in this priority
15    default = raw[cli]["CONFIG"].get("config", {}).get("default")
16    default_dir = raw[cli]["CONFIG"].get("config_dir", {}).get("default")
17    if cli in os_vars:
18        os_conf = os_vars[cli].get("config", default)
19        os_dir = os_vars[cli].get("config_dir", default_dir)
20    else:
21        os_conf = os_vars.get("config", default)
22        os_dir = os_vars.get("config_dir", default_dir)
23    conf = cli_args.get("config", os_conf)
24    dir_ = cli_args.get("config_dir", os_dir)
25    file_opts = {}
26    dir_opts = {}
27    if dir_:
28        file_opts = hub.config.file.load_dir(dir_, loader)
29    if conf:
30        dir_opts = hub.config.file.load(conf, loader)
31    ret = dict_tools.update.update(dir_opts, file_opts)
32    return ret
33
34
35def load(hub, paths, loader, includes=True):
36    """
37    Load a single configuration file
38    """
39    opts = {}
40    if not isinstance(paths, list):
41        paths = [paths]
42    add = []
43    for fn in paths:
44        for path in pathlib.Path(fn).rglob("**"):
45            add.append(str(path))
46    paths.extend(add)
47    for fn in paths:
48        fn_data = hub.render.init.load_file(loader, fn)
49        if includes:
50            fn_data = hub.config.file.proc_include(fn, fn_data, loader)
51        dict_tools.update.update(opts, fn_data)
52    return opts
53
54
55def load_dir(
56    hub,
57    confdir,
58    loader,
59    includes=True,
60    recurse=True,
61):
62    """
63    Load takes a directory location to scan for configuration files. These
64    files will be read in.
65    """
66    opts = {}
67    if not isinstance(confdir, list):
68        confdir = [confdir]
69    confdirs = []
70    for dirs in confdir:
71        if not isinstance(dirs, (list, tuple)):
72            dirs = [dirs]
73        for dir_ in dirs:
74            for g in pathlib.Path(dir_).rglob("**"):
75                confdirs.append(g)
76    paths = []
77    for dir_ in confdirs:
78        dirpaths = []
79        if not dir_.is_dir():
80            continue
81        if not recurse:
82            for path in dir_.iterdir():
83                if path.is_dir():
84                    # Don't process directories
85                    continue
86                dirpaths.append(str(path))
87        else:
88            for p in dir_.iterdir():
89                dirpaths.append(str(p))
90
91        # Sort confdir directory paths like:
92        # /b.txt
93        # /c.txt
94        # /a/x.txt
95        # /b/x.txt
96        paths.extend(sorted(dirpaths, key=lambda p: (p.count(pathlib.os.path.sep), p)))
97    dict_tools.update.update(opts, hub.config.file.load(paths, loader, includes))
98    return opts
99
100
101def proc_include(hub, fn, opts, loader):
102    """
103    Process include and include_dir
104    """
105    dirname = pathlib.Path(fn).parent
106    root = pathlib.Path(pathlib.os.sep).absolute()
107    if opts.get("include_dir"):
108        idir = pathlib.Path(opts.pop("include_dir"))
109        pathlib.sep
110        if not str(idir).startswith(str(root)):
111            idir = dirname / idir
112        dict_tools.update.update(opts, hub.config.file.load_dir(str(idir), loader))
113        hub.config.file.proc_include(str(idir / "f"), opts, loader)
114    if opts.get("include"):
115        ifn = opts.pop("include")
116        if not ifn.startswith(str(root)):
117            ifn = dirname / ifn
118        dict_tools.update.update(opts, hub.config.file.load(ifn, loader))
119        hub.config.file.proc_include(ifn, opts, loader)
120    return opts
121