Files
basegame-vcko/python3-vckonline/lib/python3.8/site-packages/pop/mods/conf/integrate.py
2020-11-03 18:30:14 -08:00

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)