Source code for lab_driver.yaml_handler

import yaml
from logging import getLogger, Logger
from typing import Any
from os import makedirs
from os.path import join, exists
from lab_driver import get_path_to_project


[docs] class YamlConfigHandler: __path2yaml_folder: str __yaml_name: str __logger: Logger = getLogger(__name__) @property def path2chck(self) -> str: """Getting the path to the desired YAML file""" return join(self.__path2yaml_folder, f"{self.__yaml_name}.yaml") def __init__(self, yaml_template: Any | dict, path2yaml='config', yaml_name='Config_Train', folder_reference: str='lab_driver'): """Creating a class for handling YAML files Args: yaml_template: Dummy dataclass with entries or dictionary (is only generated if YAML not exist) path2yaml: String with path to the folder which has the YAML file [Default: ''] yaml_name: String with name of the YAML file [Default: 'Config_Train'] folder_reference: String with folder reference to start """ self.__path2yaml_folder = join(get_path_to_project(folder_ref=folder_reference), path2yaml) self.__yaml_name = self.__remove_ending_from_filename(yaml_name) self._template = yaml_template makedirs(self.__path2yaml_folder, exist_ok=True) if not exists(self.path2chck): data2yaml = yaml_template if isinstance(yaml_template, dict) else self.translate_dataclass_to_dict(yaml_template) self.write_dict_to_yaml(data2yaml) self.__logger.info("... created new yaml file in folder!") @staticmethod def __remove_ending_from_filename(file_name: str) -> str: """Function for removing data type ending :param file_name: String with file name :return: String with file name without data type ending """ yaml_ending_chck = ['.yaml', '.yml'] yaml_file_name = file_name for yaml_end in yaml_ending_chck: if yaml_end in yaml_file_name: yaml_file_name = yaml_file_name.split(yaml_end)[0] break return yaml_file_name
[docs] @staticmethod def translate_dataclass_to_dict(class_content: type) -> dict: """Translating all class variables with default values into dict""" return {key: value for key, value in class_content.__dict__.items() if not key.startswith('__') and not callable(key)}
def __check_scheme_validation(self, template: type | dict, real_file: type | dict) -> bool: """Function for validating the key entries from template yaml and real yaml file :param template: Dictionary or class from the template for generating yaml file :param real_file: Dictionary from real_file :return: Boolean decision if both key are equal """ template_used = self.translate_dataclass_to_dict(template) if not isinstance(template, dict) else template real_used = self.translate_dataclass_to_dict(real_file) if not isinstance(real_file, dict) else real_file equal_chck = template_used.keys() == real_used.keys() if not equal_chck: raise RuntimeError("Config file not valid! - Please check and remove actual config file!") else: return template_used.keys() == real_used.keys()
[docs] def write_dict_to_yaml(self, config_data: dict, print_output: bool=False) -> None: """Writing list with configuration sets to YAML file Args: config_data: Dict. with configuration print_output: Printing the data in YAML format Returns: None """ makedirs(self.__path2yaml_folder, exist_ok=True) with open(self.path2chck, 'w') as f: yaml.dump(config_data, f, sort_keys=False) if print_output: print(yaml.dump(config_data, sort_keys=False))
[docs] def get_class(self, class_constructor: type): """Getting all key inputs from yaml dictionary to a class""" data = self.get_dict() self.__check_scheme_validation(self._template, data) return class_constructor(**data)
[docs] def get_dict(self) -> dict: """Writing list with configuration sets to YAML file Returns: Dict. with configuration """ if not exists(self.path2chck): raise FileNotFoundError("YAML does not exists - Please create one!") else: # --- Reading YAML file with open(self.path2chck, 'r') as f: config_data = yaml.safe_load(f) self.__logger.debug(f"... read YAML file: {self.path2chck}") return config_data