X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/d1b1c8d9119229dbeed06cd252917e54a1cb77f6..1025235c72c31f7fa7b648c0e32ddcaa68a8f66a:/lunaix-os/scripts/build-tools/lcfg/api.py diff --git a/lunaix-os/scripts/build-tools/lcfg/api.py b/lunaix-os/scripts/build-tools/lcfg/api.py new file mode 100644 index 0000000..1b0b30f --- /dev/null +++ b/lunaix-os/scripts/build-tools/lcfg/api.py @@ -0,0 +1,139 @@ +from abc import abstractmethod + +class ConfigLoadBaseException(Exception): + def __init__(self, msg, node, inner=None) -> None: + super().__init__(msg) + + self.__msg = msg + self.__node = node + self.__inner = inner + + def __str__(self) -> str: + return super().__str__() + +class ConfigLoadException(ConfigLoadBaseException): + def __init__(self, msg, node = None, inner=None) -> None: + super().__init__(msg, node, inner) + +class ConfigTypeCheckError(ConfigLoadBaseException): + def __init__(self, msg, node, inner=None) -> None: + super().__init__(msg, node, inner) + +class ConfigIOProvider: + def __init__(self) -> None: + pass + + @abstractmethod + def export(self, env, config_dict): + pass + + @abstractmethod + def save(self, env, config_dict): + pass + + @abstractmethod + def load(self, env): + pass + + +class TypeProviderBase: + def __init__(self, type) -> None: + self._type = type + + @abstractmethod + def check(self, val): + return True + + @abstractmethod + def serialise(self, val): + pass + + @abstractmethod + def deserialise(self, val): + pass + + @abstractmethod + def parse_input(self, input_str): + pass + + @abstractmethod + def to_input(self, val): + pass + + def allow_none(self): + return False + + @staticmethod + def typedef_matched(typedef): + return False + + @abstractmethod + def __str__(self) -> str: + pass + +class Renderable: + def __init__(self) -> None: + pass + + @abstractmethod + def render(self, rctx): + pass + +class RenderContext: + def __init__(self) -> None: + pass + + @abstractmethod + def add_expandable(self, label, node, on_expand_cb): + pass + + @abstractmethod + def add_field(self, label, node): + pass + +class InteractiveRenderer(RenderContext): + def __init__(self) -> None: + super().__init__() + + @abstractmethod + def render_loop(self): + pass + + +class LConfigBuiltin: + def __init__(self, f, is_contextual, rename=None, caller_type=[]): + self.name = f.__name__ if not rename else rename + self.__f = f + self.__contextual = is_contextual + self.__caller_type = caller_type + + def __call__(self, env, *args, **kwds): + if not self.__contextual: + return self.__f(env, *args, **kwds) + + caller = env.callframe_at(0) + f_name = self.__f.__name__ + + if not caller: + raise ConfigLoadException( + f"contextual function '{f_name}' can not be called contextless", + None + ) + + if self.__caller_type and not any([isinstance(caller, x) for x in self.__caller_type]): + raise ConfigLoadException( + f"caller of '{f_name}' ({caller}) must have type of any {self.__caller_type}", + caller + ) + + return self.__f(env, caller, *args, **kwds) + +def contextual(name=None, caller_type=[]): + def wrapper(func): + return LConfigBuiltin(func, True, name, caller_type) + return wrapper + +def builtin(name=None): + def wrapper(func): + return LConfigBuiltin(func, False, name) + return wrapper