56 lines
1.7 KiB
Python
56 lines
1.7 KiB
Python
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Dict, Iterable, Optional
|
|
|
|
import tomli
|
|
|
|
from ..util import merge_dicts
|
|
from .model import Preset
|
|
|
|
__all__ = (
|
|
"PresetResolverConfig",
|
|
"PresetResolver",
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class PresetResolverConfig:
|
|
deafult: bool = True
|
|
user: bool = True
|
|
project: bool = True
|
|
|
|
|
|
class PresetResolver:
|
|
_source_cache: Dict[Path, dict] = {}
|
|
|
|
def __init__(self, basepath: Path, config: Optional[PresetResolverConfig] = None):
|
|
self._basepath = basepath
|
|
self._config = config or PresetResolverConfig()
|
|
|
|
def iter_sources(self) -> Iterable[Path]:
|
|
if self._config.deafult:
|
|
for filepath in (Path(__file__).parent / "default").iterdir():
|
|
yield filepath
|
|
if self._config.user:
|
|
user_preset = Path.home() / ".preset.toml"
|
|
if user_preset.exists():
|
|
yield user_preset
|
|
if self._config.project:
|
|
projectpath = self._basepath
|
|
while projectpath.exists():
|
|
project_preset = projectpath / ".preset.toml"
|
|
if project_preset.exists():
|
|
yield project_preset
|
|
if projectpath.parent == projectpath:
|
|
break
|
|
projectpath = projectpath.parent
|
|
|
|
def resolve_preset(self) -> Preset:
|
|
result_preset_data = {}
|
|
for filepath in self.iter_sources():
|
|
if filepath not in self._source_cache:
|
|
with open(filepath, "rb") as fd:
|
|
self._source_cache[filepath] = tomli.load(fd)
|
|
merge_dicts(result_preset_data, self._source_cache[filepath])
|
|
return Preset(**result_preset_data)
|