"""
Functions for handling configuration files.
"""
import copy
import getpass
import json
import os
import time
from pathlib import Path
import numpy as np
import toml
import yaml
from .git_utils import try_get_toolbox_git_metadata
[docs]def default(obj):
# serialize numpy array for saving to json
if type(obj).__module__ == np.__name__:
if isinstance(obj, np.ndarray):
return obj.tolist()
return obj.item()
raise TypeError("Unknown type:", type(obj))
[docs]def save_config(configs: dict, config_file: str) -> None:
"""
Save the given configuration data to the specified file.
Args:
configs (dict): The configuration data to be saved.
config_file (str): The path to the file where the configuration data
will be saved.
Raises:
NotImplementedError: If the file type is not supported.
Supported types are yaml/yml and toml.
Note:
If the file type is Windows, it will convert the paths to Windows format.
"""
config_file = Path(config_file)
if config_file.suffix in [".yml", ".yaml"]:
with open(config_file, "w") as file:
yaml.dump_all(configs, file, default_flow_style=False, indent=4, sort_keys=False)
elif config_file.suffix == ".toml":
with open(config_file, "w") as file:
toml.dump(configs, file, encoder=toml.TomlNumpyEncoder())
elif config_file.suffix == ".json":
with open(config_file, "w") as file:
json.dump(configs, file, default=default)
else:
raise NotImplementedError(
f"config_file type {config_file} is not supported currently. " f"Implemented are yaml/yml and toml."
)
[docs]def config_fill_placeholders(config, placeholders):
"""
Replace placeholders in the given configuration data with their corresponding
values.
Args:
config (dict or list): The configuration data to be processed.
placeholders (dict): A dictionary containing the placeholder values.
Returns:
dict: The configuration data with placeholders replaced.
"""
filled_config = copy.deepcopy(config)
# iterate over all placeholders
for ph_key, ph_value in placeholders.items():
for config_key, config_value in filled_config.items():
if isinstance(config_value, dict):
filled_config[config_key] = config_fill_placeholders(config_value, placeholders)
elif isinstance(config_value, list):
if any([f"<{ph_key}>" in val if isinstance(val, str) else False for val in config_value]):
filled_config[config_key] = [
(
val.replace(f"<{ph_key}>", ph_value)
if (isinstance(val, str) and f"<{ph_key}>" in val)
else val
)
for val in config_value
]
elif isinstance(config_value, str) and f"<{ph_key}>" in config_value:
filled_config[config_key] = config_value.replace(f"<{ph_key}>", f"{ph_value}")
else:
continue
return filled_config
[docs]def config_fill_auto(config, working_directory=None):
"""
This function fills placeholders in the configuration data with auto-generated
values.
Args:
config (dict): The configuration data to be processed.
working_directory (str, optional): The directory where the git repository
is located.
Defaults to the current working directory.
Returns:
dict: The configuration data with placeholders replaced with auto-generated
values.
Note:
This function uses the `oslab_utils.git_utils` module to get the git hash
and commit message. The placeholders filled are: <git_hash>,
<commit_message>, <me>, <yyyymmdd>, <today>, and <time>.
"""
if working_directory is None:
working_directory = os.getcwd()
git_metadata = try_get_toolbox_git_metadata(working_directory)
if git_metadata is not None:
git_hash, commit_message = git_metadata
git_hash = git_hash[:7]
else:
git_hash, commit_message = "unknown", "unknown"
placeholder_dict = dict(
git_hash=git_hash,
commit_message=commit_message,
me=getpass.getuser(),
yyyymmdd=time.strftime("%Y%m%d", time.localtime()),
today=time.strftime("%Y%m%d", time.localtime()),
time=time.strftime("%H_%M", time.localtime()),
pwd=os.getcwd(),
)
return config_fill_placeholders(config, placeholder_dict)