109 lines
2.5 KiB
Python
109 lines
2.5 KiB
Python
"""
|
|
Support for basic config templates
|
|
"""
|
|
|
|
import re
|
|
import tomllib
|
|
from pathlib import Path
|
|
|
|
from symconf import util
|
|
from symconf.reader import DictReader
|
|
|
|
|
|
class Template:
|
|
def __init__(
|
|
self,
|
|
template_str: str,
|
|
key_pattern: str = r"f{{(\S+?)}}",
|
|
exe_pattern: str = r"x{{((?:(?!x{{).)*)}}",
|
|
) -> None:
|
|
self.template_str = template_str
|
|
self.key_pattern = key_pattern
|
|
self.exe_pattern = exe_pattern
|
|
|
|
def fill(
|
|
self,
|
|
template_dict: dict,
|
|
) -> str:
|
|
dr = DictReader.from_dict(template_dict)
|
|
|
|
exe_filled = re.sub(
|
|
self.exe_pattern,
|
|
lambda m: self._exe_fill(m, dr),
|
|
self.template_str,
|
|
)
|
|
|
|
key_filled = re.sub(
|
|
self.key_pattern, lambda m: self._key_fill(m, dr), exe_filled
|
|
)
|
|
|
|
return key_filled
|
|
|
|
def _key_fill(
|
|
self,
|
|
match: re.Match,
|
|
dict_reader: DictReader,
|
|
) -> str:
|
|
key = match.group(1)
|
|
|
|
return str(dict_reader.get(key))
|
|
|
|
def _exe_fill(
|
|
self,
|
|
match: re.Match,
|
|
dict_reader: DictReader,
|
|
) -> str:
|
|
key_fill = re.sub(
|
|
self.key_pattern,
|
|
lambda m: f'"{self._key_fill(m, dict_reader)}"',
|
|
match.group(1),
|
|
)
|
|
|
|
return str(eval(key_fill))
|
|
|
|
|
|
class FileTemplate(Template):
|
|
def __init__(
|
|
self,
|
|
path: Path,
|
|
key_pattern: str = r"f{{(\S+?)}}",
|
|
exe_pattern: str = r"x{{((?:(?!x{{).)*)}}",
|
|
) -> None:
|
|
super().__init__(
|
|
path.open("r").read(),
|
|
key_pattern=key_pattern,
|
|
exe_pattern=exe_pattern,
|
|
)
|
|
|
|
|
|
class TOMLTemplate(FileTemplate):
|
|
def __init__(
|
|
self,
|
|
toml_path: Path,
|
|
key_pattern: str = r"f{{(\S+?)}}",
|
|
exe_pattern: str = r"x{{((?:(?!x{{).)*)}}",
|
|
) -> None:
|
|
super().__init__(
|
|
toml_path,
|
|
key_pattern=key_pattern,
|
|
exe_pattern=exe_pattern,
|
|
)
|
|
|
|
def fill(
|
|
self,
|
|
template_dict: dict,
|
|
) -> str:
|
|
filled_template = super().fill(template_dict)
|
|
toml_dict = tomllib.loads(filled_template)
|
|
|
|
return toml_dict
|
|
|
|
@staticmethod
|
|
def stack_toml(path_list: list[Path]) -> dict:
|
|
stacked_dict = {}
|
|
for toml_path in path_list:
|
|
updated_map = tomllib.load(toml_path.open("rb"))
|
|
stacked_dict = util.deep_update(stacked_dict, updated_map)
|
|
|
|
return stacked_dict
|