Source code for config

"""Module for configuration settings."""

import logging
import json

from merge_utils import io_utils

DEFAULT_CONFIG = ["defaults/metadata.yaml", "defaults/defaults.yaml"]

# Configuration dictionaries
inputs: dict = {}
output: dict = {}
validation: dict = {}
sites: dict = {}
merging: dict = {}

initialized: bool = False

logger = logging.getLogger(__name__)

[docs] def update_list(old_list: list, new_list: list) -> None: """ Append values from new_list to old_list. Strings beginning with '~' are removed from old_list instead. :param old_list: List to be updated. :param new_list: List with new values. :return: None """ # Ensure new_list is a list if not isinstance(new_list, list): new_list = [new_list] for val in new_list: if isinstance(val, str) and val.startswith("~"): # Remove the value if it starts with '~' val = val[1:] # Remove the '~' prefix if val in old_list: old_list.remove(val) elif val not in old_list: # Add the value if it is not already in the old list old_list.append(val)
[docs] def update_dict(old_dict: dict, new_dict: dict) -> None: """ Add key value pairs from new_dict to old_dict. If a key in new_dict does not exist in old_dict, it is added. If the value is a dict or list, the values are merged recursively. If a key in new_dict starts with '~', it overrides the value in old_dict instead. If the value is None, the key is removed from old_dict instead. :param old_dict: Dictionary to be updated. :param new_dict: Dictionary with new values. :return: None """ for key, val in new_dict.items(): if val is None and key in old_dict: # If the value is None, remove the key from the old dictionary del old_dict[key] continue if key.startswith("~"): # If the key starts with '~', override the value in old_dict key = key[1:] # Remove the '~' prefix old_dict[key] = val continue if key not in old_dict: # If the key does not exist in the old dictionary, add it old_dict[key] = val continue old_val = old_dict.get(key, None) if isinstance(old_val, dict): # If both are dictionaries, recursively update if isinstance(val, dict): update_dict(old_dict[key], val) elif isinstance(old_val, list): # If the old value is a list, extend it with the new value update_list(old_dict[key], val) else: old_dict[key] = val
[docs] def update(cfg: dict) -> None: """ Update the global configuration with values from the provided dictionary. :param cfg: Dictionary containing new configuration values. :return: None """ update_dict(inputs, cfg.get("inputs", {})) update_dict(output, cfg.get("output", {})) update_dict(validation, cfg.get("validation", {})) update_dict(sites, cfg.get("sites", {})) update_dict(merging, cfg.get("merging", {}))
[docs] def load(files: list = None) -> None: """ Load the specified configuration files. Missing keys will be filled in with the defaults in DEFAULT_CONFIG. :param files: List of configuration files. :return: None """ # Add the default configuration file to the beginning of the list if not files: files = DEFAULT_CONFIG elif isinstance(files, str): files = DEFAULT_CONFIG + [files] else: files = DEFAULT_CONFIG + files for file in files: cfg = io_utils.read_config_file(file) logger.info("Loaded configuration file %s", file) update(cfg) logger.debug( "Final configuration:\ninputs: %s\noutput: %s\nvalidation: %s\nsites: %s\nmerging: %s", json.dumps(inputs, indent=2), json.dumps(output, indent=2), json.dumps(validation, indent=2), json.dumps(sites, indent=2), json.dumps(merging, indent=2) )