81 lines
2.1 KiB
Python
81 lines
2.1 KiB
Python
"""Implements a config object with dot-indexing syntax."""
|
|
import os
|
|
from itertools import chain
|
|
from operator import truth
|
|
from typing import Iterable
|
|
|
|
from envyaml import EnvYAML
|
|
from frozendict import frozendict
|
|
from funcy import first, juxt, butlast, last, lmap
|
|
|
|
from pyinfra.locations import CONFIG_FILE
|
|
|
|
|
|
def _get_item_and_maybe_make_dotindexable(container, item):
|
|
ret = container[item]
|
|
return DotIndexable(ret) if isinstance(ret, dict) else ret
|
|
|
|
|
|
class DotIndexable:
|
|
def __init__(self, x):
|
|
self.x = x
|
|
|
|
def __getattr__(self, item):
|
|
return _get_item_and_maybe_make_dotindexable(self.x, item)
|
|
|
|
def __repr__(self):
|
|
return self.x.__repr__()
|
|
|
|
def __getitem__(self, item):
|
|
return self.__getattr__(item)
|
|
|
|
def __setitem__(self, key, value):
|
|
self.x[key] = value
|
|
|
|
|
|
class Config:
|
|
def __init__(self, config_path):
|
|
self.__config = EnvYAML(config_path)
|
|
|
|
def __getattr__(self, item):
|
|
if item in self.__config:
|
|
return _get_item_and_maybe_make_dotindexable(self.__config, item)
|
|
|
|
def __getitem__(self, item):
|
|
return self.__getattr__(item)
|
|
|
|
def __setitem__(self, key, value):
|
|
self.__config.key = value
|
|
|
|
def to_dict(self):
|
|
return to_dict(self.__config.export())
|
|
|
|
def __hash__(self):
|
|
return hash(self.to_dict())
|
|
|
|
|
|
def to_dict(v):
|
|
if isinstance(v, list):
|
|
return tuple(map(to_dict, v))
|
|
elif isinstance(v, DotIndexable):
|
|
return frozendict({k: to_dict(v) for k, v in v.x.items()})
|
|
elif isinstance(v, dict):
|
|
return frozendict({k: to_dict(v) for k, v in v.items()})
|
|
else:
|
|
return v
|
|
|
|
|
|
CONFIG = Config(CONFIG_FILE)
|
|
|
|
|
|
def parse_disjunction_string(disjunction_string):
|
|
def try_parse_env_var(disjunction_string):
|
|
try:
|
|
return os.environ[disjunction_string]
|
|
except KeyError:
|
|
return None
|
|
|
|
options = disjunction_string.split("|")
|
|
identifiers, fallback_value = juxt(butlast, last)(options)
|
|
return first(chain(filter(truth, map(try_parse_env_var, identifiers)), [fallback_value]))
|