mirror of
https://github.com/vladmandic/sdnext.git
synced 2026-01-29 05:02:09 +03:00
141 lines
4.2 KiB
Python
141 lines
4.2 KiB
Python
import json
|
|
import os
|
|
import warnings
|
|
from dataclasses import asdict, field
|
|
from typing import Any, Dict, Union
|
|
import yaml
|
|
from pydantic import ValidationError
|
|
from pydantic.dataclasses import dataclass
|
|
from yaml import safe_load
|
|
|
|
|
|
@dataclass
|
|
class BaseConfig:
|
|
"""This is the BaseConfig class which defines all the useful loading and saving methods
|
|
of the configs"""
|
|
|
|
name: str = field(init=False)
|
|
|
|
def __post_init__(self):
|
|
self.name = self.__class__.__name__
|
|
|
|
@classmethod
|
|
def from_dict(cls, config_dict: Dict[str, Any]) -> "BaseConfig":
|
|
"""Creates a BaseConfig instance from a dictionnary
|
|
|
|
Args:
|
|
config_dict (dict): The Python dictionnary containing all the parameters
|
|
|
|
Returns:
|
|
:class:`BaseConfig`: The created instance
|
|
"""
|
|
try:
|
|
config = cls(**config_dict)
|
|
except (ValidationError, TypeError) as e:
|
|
raise e
|
|
return config
|
|
|
|
@classmethod
|
|
def _dict_from_json(cls, json_path: Union[str, os.PathLike]) -> Dict[str, Any]:
|
|
try:
|
|
with open(json_path) as f:
|
|
try:
|
|
config_dict = json.load(f)
|
|
return config_dict
|
|
|
|
except (TypeError, json.JSONDecodeError) as e:
|
|
raise TypeError(
|
|
f"File {json_path} not loadable. Maybe not json ? \n"
|
|
f"Catch Exception {type(e)} with message: " + str(e)
|
|
) from e
|
|
|
|
except FileNotFoundError:
|
|
raise FileNotFoundError(
|
|
f"Config file not found. Please check path '{json_path}'"
|
|
)
|
|
|
|
@classmethod
|
|
def from_json(cls, json_path: str) -> "BaseConfig":
|
|
"""Creates a BaseConfig instance from a JSON config file
|
|
|
|
Args:
|
|
json_path (str): The path to the json file containing all the parameters
|
|
|
|
Returns:
|
|
:class:`BaseConfig`: The created instance
|
|
"""
|
|
config_dict = cls._dict_from_json(json_path)
|
|
|
|
config_name = config_dict.pop("name")
|
|
|
|
if cls.__name__ != config_name:
|
|
warnings.warn(
|
|
f"You are trying to load a "
|
|
f"`{ cls.__name__}` while a "
|
|
f"`{config_name}` is given."
|
|
)
|
|
|
|
return cls.from_dict(config_dict)
|
|
|
|
def to_dict(self) -> dict:
|
|
"""Transforms object into a Python dictionnary
|
|
|
|
Returns:
|
|
(dict): The dictionnary containing all the parameters"""
|
|
return asdict(self)
|
|
|
|
def to_json_string(self):
|
|
"""Transforms object into a JSON string
|
|
|
|
Returns:
|
|
(str): The JSON str containing all the parameters"""
|
|
return json.dumps(self.to_dict())
|
|
|
|
def save_json(self, file_path: str):
|
|
"""Saves a ``.json`` file from the dataclass
|
|
|
|
Args:
|
|
file_path (str): path to the file
|
|
"""
|
|
with open(os.path.join(file_path), "w", encoding="utf-8") as fp:
|
|
fp.write(self.to_json_string())
|
|
|
|
def save_yaml(self, file_path: str):
|
|
"""Saves a ``.yaml`` file from the dataclass
|
|
|
|
Args:
|
|
file_path (str): path to the file
|
|
"""
|
|
with open(os.path.join(file_path), "w", encoding="utf-8") as fp:
|
|
yaml.dump(self.to_dict(), fp)
|
|
|
|
@classmethod
|
|
def from_yaml(cls, yaml_path: str) -> "BaseConfig":
|
|
"""Creates a BaseConfig instance from a YAML config file
|
|
|
|
Args:
|
|
yaml_path (str): The path to the yaml file containing all the parameters
|
|
|
|
Returns:
|
|
:class:`BaseConfig`: The created instance
|
|
"""
|
|
with open(yaml_path, "r") as f:
|
|
try:
|
|
config_dict = safe_load(f)
|
|
except yaml.YAMLError as e:
|
|
raise yaml.YAMLError(
|
|
f"File {yaml_path} not loadable. Maybe not yaml ? \n"
|
|
f"Catch Exception {type(e)} with message: " + str(e)
|
|
) from e
|
|
|
|
config_name = config_dict.pop("name")
|
|
|
|
if cls.__name__ != config_name:
|
|
warnings.warn(
|
|
f"You are trying to load a "
|
|
f"`{ cls.__name__}` while a "
|
|
f"`{config_name}` is given."
|
|
)
|
|
|
|
return cls.from_dict(config_dict)
|