韩宇
init
1b7e88c
Raw
History Blame Contribute Delete
3.84 kB
import json
import os
import re
from copy import deepcopy
from distutils.util import strtobool
from pathlib import Path
import yaml
def build_from_file(file_path: str):
path = Path(file_path)
workers_path = path / "workers"
if not workers_path.exists():
return []
# init config dict
worker_configs = {}
other_configs = {}
file_names = {}
for file in path.rglob("*"):
if file.suffix not in [".json", ".yaml", ".yml"]:
continue
key = file.name.split(".", 1)[0]
if key in file_names:
raise Exception(
f"Duplicate file name [{key}] found:\n"
f"File 1: {file_names[key]}\n"
f"File 2: {file}"
)
file_names[key] = file
try:
with open(file, "r") as f:
if file.suffix == ".json":
content = json.load(f)
else: # .yaml or .yml
content = yaml.load(f, Loader=yaml.FullLoader)
except Exception as e:
raise Exception(f"Error loading file {file}: {str(e)}")
if workers_path in file.parents:
worker_configs[key] = content
else:
other_configs[key] = content
for conf in worker_configs.values():
prep_config(conf, other_configs, [])
worker_configs_list = []
for worker_config in worker_configs.values():
if isinstance(worker_config, list):
worker_configs_list.extend(worker_config)
else:
worker_configs_list.append(worker_config)
return worker_configs_list
def prep_config(sub_config: dict | list, config: dict, forbid_keys: list):
if isinstance(sub_config, dict):
for key, conf in sub_config.items():
if isinstance(conf, str):
if match := re.search(r"\$\{sub\|([^}]+)\}", conf):
module_key = match.group(1).strip()
if module_key not in config:
raise Exception(
"Incomplete configuration, lack module [{}]".format(
module_key
)
)
elif module_key in forbid_keys:
raise Exception(
"Can't reference submodule recursively. [{}]".format(
module_key
)
)
sub_config[key] = deepcopy(config[module_key])
prep_config(sub_config[key], config, forbid_keys + [module_key])
elif match := re.search(r"\$\{env\|([^,}]+)(?:,([^}]+))?\}", conf):
env_key = match.group(1).strip()
default_value = match.group(2)
env_value = os.getenv(env_key)
if env_value:
sub_config[key] = env_value
elif not env_value and default_value:
sub_config[key] = default_value.strip()
if sub_config[key] == "null" or sub_config[key] == "~":
sub_config[key] = None
else:
raise ValueError(
f"Environmental variable {env_key} need to be set."
)
elif isinstance(conf, dict):
prep_config(sub_config[key], config, forbid_keys)
elif isinstance(conf, list):
for i, item in enumerate(conf):
if isinstance(item, dict):
prep_config(sub_config[key][i], config, forbid_keys)
elif isinstance(sub_config, list):
for item in sub_config:
prep_config(item, config, forbid_keys)