Source code for vcorelib.dict.config

"""
A module for implementing a configuration data manager with a dictionary.
"""

# built-in
from collections import UserDict as _UserDict
from typing import Any as _Any
from typing import MutableMapping as _MutableMapping

# internal
from vcorelib.dict import GenericDict as _GenericDict
from vcorelib.dict import consume as _consume
from vcorelib.dict import merge as _merge
from vcorelib.dict import set_if_not as _set_if_not
from vcorelib.io import ARBITER as _ARBITER
from vcorelib.io.types import FileExtension as _FileExtension
from vcorelib.paths import Pathlike as _Pathlike
from vcorelib.paths import normalize as _normalize

ConfigData = _MutableMapping[str, _Any]


[docs] class Config( _UserDict, # type: ignore ConfigData, ): """A dictionary that allows access to data only once via each key.""" def __getitem__(self, key) -> _Any: """Consume keys after their data is retreived.""" assert key in self.data, f"Key '{key}' not found in configuration!" return _consume(self.data, key)
[docs] def get(self, key, default=None) -> _Any: """Get data from the configuration but allow a default value.""" return _consume(self.data, key, default)
[docs] def set_if_not(self, key, value) -> _Any: """Set this value if a value is not already set.""" return _set_if_not(self.data, key, value)
[docs] def merge(self, other: _GenericDict, *args, **kwargs) -> None: """Merge another dictionary into this one.""" _merge(self.data, other, *args, **kwargs)
[docs] @staticmethod def from_file(pathlike: _Pathlike, *args, **kwargs) -> "Config": """Load a configuration from a file on disk.""" _set_if_not(kwargs, "require_success", True) return Config(_ARBITER.decode(pathlike, *args, **kwargs).data)
[docs] @staticmethod def from_directory(pathlike: _Pathlike, *args, **kwargs) -> "Config": """Load a configuration from a directory on disk.""" _set_if_not(kwargs, "require_success", True) return Config( _ARBITER.decode_directory(pathlike, *args, **kwargs).data )
[docs] @staticmethod def from_path(pathlike: _Pathlike, *args, **kwargs) -> "Config": """Load a configuration from an arbitrary path.""" path = _normalize(pathlike) # Load this as a directory if it is one. if path.is_dir(): return Config.from_directory(path, *args, **kwargs) candidates = list( _FileExtension.data_candidates(path, exists_only=True) ) count = len(candidates) assert ( count == 1 ), f"Found {count} configurations for '{path}': {candidates}." # Load the data file. result = Config.from_file(candidates[0], *args, **kwargs) # Also load a directory of the stem name matches one. Load this data # via merging dictionaries. to_check = path.with_suffix("") if to_check.is_dir(): result.merge(Config.from_directory(to_check).data) return result