142 lines
4.6 KiB
Python
142 lines
4.6 KiB
Python
"""
|
|
Integrate is used to pull config data from multiple sources and merge it into
|
|
the hub. Once it is merged then when a sub is loaded the respective config data
|
|
is loaded into the sub as `OPTS`
|
|
"""
|
|
# Take an *args list of modules to import and look for conf.py
|
|
# Import conf.py if present
|
|
# After gathering all dicts, modify them to merge CLI options
|
|
#
|
|
# Import python libs
|
|
import importlib
|
|
import copy
|
|
import os
|
|
|
|
|
|
def _ex_final(confs, final, override, key_to_ref, ops_to_ref):
|
|
"""
|
|
Scan the configuration datasets, create the final config
|
|
value, and detect collisions
|
|
"""
|
|
for arg in confs:
|
|
for key in confs[arg]:
|
|
ref = f"{arg}.{key}"
|
|
if ref in override:
|
|
s_key = override[ref]["key"]
|
|
s_opts = override[ref]["options"]
|
|
else:
|
|
s_key = key
|
|
s_opts = confs[arg][key].get("options", [])
|
|
s_opts.append(f"--{s_key}")
|
|
final[s_key] = confs[arg][key]
|
|
if s_opts:
|
|
final[s_key]["options"] = s_opts
|
|
if s_key in key_to_ref:
|
|
key_to_ref[s_key].append(ref)
|
|
else:
|
|
key_to_ref[s_key] = [ref]
|
|
for opt in s_opts:
|
|
if opt in ops_to_ref:
|
|
ops_to_ref[opt].append(ref)
|
|
else:
|
|
ops_to_ref = [ref]
|
|
|
|
|
|
def load(
|
|
hub,
|
|
imports,
|
|
override=None,
|
|
cli=None,
|
|
roots=False,
|
|
loader="json",
|
|
logs=True,
|
|
version=True,
|
|
):
|
|
"""
|
|
This function takes a list of python packages to load and look for
|
|
respective configs. The configs are then loaded in a non-collision
|
|
way modifying the cli options dynamically.
|
|
The args look for the named <package>.conf python module and then
|
|
looks for dictionaries named after the following convention:
|
|
|
|
override = {'<package>.key': 'key': 'new_key', 'options': ['--option1', '--option2']}
|
|
|
|
CONFIG: The main configuration for this package - loads to hub.OPT['<import>']
|
|
CLI_CONFIG: Loaded only if this is the only import or if specified in the cli option
|
|
SUBS: Used to define the subcommands, only loaded if this is the cli config
|
|
"""
|
|
if override is None:
|
|
override = {}
|
|
if isinstance(imports, str):
|
|
if cli is None:
|
|
cli = imports
|
|
imports = [imports]
|
|
primary = imports[0] if cli is None else cli
|
|
confs = {}
|
|
final = {}
|
|
collides = []
|
|
key_to_ref = {}
|
|
ops_to_ref = {}
|
|
subs = {}
|
|
for imp in imports:
|
|
try:
|
|
cmod = importlib.import_module(f"{imp}.conf")
|
|
except ImportError:
|
|
continue
|
|
if hasattr(cmod, "CONFIG"):
|
|
confs[imp] = copy.deepcopy(cmod.CONFIG)
|
|
if cli == imp:
|
|
if hasattr(cmod, "CLI_CONFIG"):
|
|
confs[imp].update(copy.deepcopy(cmod.CLI_CONFIG))
|
|
if hasattr(cmod, "SUBS"):
|
|
subs = copy.deepcopy(cmod.SUBS)
|
|
if logs:
|
|
lconf = hub.conf.log.init.conf(primary)
|
|
lconf.update(confs[primary])
|
|
confs[primary] = lconf
|
|
if version:
|
|
vconf = hub.conf.version.CONFIG
|
|
vconf.update(confs[primary])
|
|
confs[primary] = vconf
|
|
_ex_final(confs, final, override, key_to_ref, ops_to_ref)
|
|
for opt in ops_to_ref:
|
|
g_count = 0
|
|
if len(ops_to_ref[opt]) > 1:
|
|
collides.append({opt: ops_to_ref[opt]})
|
|
for key in key_to_ref:
|
|
col = []
|
|
for ref in key_to_ref[key]:
|
|
col.append(ref)
|
|
if len(col) > 1:
|
|
collides.append({key: key_to_ref[key]})
|
|
if collides:
|
|
raise KeyError(collides)
|
|
opts = hub.conf.reader.read(final, subs, loader=loader)
|
|
# This will be put into an immutable data type before it is passed on
|
|
f_opts = {}
|
|
for key in opts:
|
|
if key == "_subparser_":
|
|
f_opts["_subparser_"] = opts["_subparser_"]
|
|
continue
|
|
for ref in key_to_ref[key]:
|
|
imp = ref[: ref.rindex(".")]
|
|
local_key = ref[ref.rindex(".") + 1 :]
|
|
if imp not in f_opts:
|
|
f_opts[imp] = {}
|
|
f_opts[imp][local_key] = opts[key]
|
|
if roots:
|
|
root_dir = f_opts.get(cli, {}).get("root_dir")
|
|
hub.conf.dirs.roots(
|
|
final.get("root_dir", {}).get("default", os.path.abspath(os.sep)),
|
|
f_opts,
|
|
root_dir,
|
|
)
|
|
for imp in f_opts:
|
|
hub.conf.dirs.verify(f_opts[imp])
|
|
hub.OPT = hub.pop.data.imap(f_opts)
|
|
if logs:
|
|
log_plugin = hub.OPT[primary].get("log_plugin")
|
|
getattr(hub, f"conf.log.{log_plugin}.setup")(hub.OPT[primary])
|
|
if hub.OPT[primary].get("version"):
|
|
hub.conf.version.run(primary)
|