X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/bcc25888b3299758ad36721530cca3b899b7166c..c043fa535514a76091be87a45ad472a505f9dd33:/lunaix-os/scripts/build-tools/shared/shconfig/common.py?ds=sidebyside diff --git a/lunaix-os/scripts/build-tools/shared/shconfig/common.py b/lunaix-os/scripts/build-tools/shared/shconfig/common.py new file mode 100644 index 0000000..c9825e9 --- /dev/null +++ b/lunaix-os/scripts/build-tools/shared/shconfig/common.py @@ -0,0 +1,106 @@ +import inspect +import textwrap + +from typing import Callable, Any +from lib.utils import Schema + +def select(val, _if, _else): + return _if if val else _else + +def get_config_name(name): + return f"CONFIG_{name.upper()}" + +def cmd(name, *alias): + def __cmd(fn: Callable): + fn.__annotations__["__CMD__"] = True + fn.__annotations__["__NAME__"] = name + fn.__annotations__["__ALIAS__"] = [*alias] + return fn + return __cmd + +def imply_schema(fn: Callable): + type_map = inspect.get_annotations(fn) + arg_list = [] + + for arg in inspect.getargs(fn.__code__).args: + if arg == "self": + continue + + t = type_map.get(arg) + t = t if t else Any + + arg_list.append((arg, t)) + + return Schema([x[1] for x in arg_list]), arg_list + +class ShconfigException(Exception): + def __init__(self, *args): + super().__init__(*args) + + def __str__(self): + return str(self.args[0]) + +class Executor: + def __init__(self, body: Callable): + self.name = body.__annotations__["__NAME__"] + self.alias = body.__annotations__["__ALIAS__"] + self.help = inspect.getdoc(body) + self.help = textwrap.dedent(self.help if self.help else "") + + schema, args = imply_schema(body) + self.argstr = ' '.join( + [f'<{n.upper()}: {t.__name__}>' for n, t in args]) + + self.__fn = body + self.__argtype = schema + + def match_name(self, name): + return self.name == name or name in self.alias + + def try_invoke(self, *args): + t_args = [self.__type_mapper(x) for x in args] + if self.__argtype != t_args: + raise ShconfigException( + f"invalid parameter ({args}), expect: ({self.argstr})") + + self.__fn(*t_args) + + def __type_mapper(self, strtype): + if strtype in ['True', 'False']: + return bool(strtype) + if strtype in ['y', 'n']: + return bool(strtype == 'y') + + try: return int(strtype) + except: pass + + return strtype + + def __str__(self): + return '\n'.join([ + *[f"{name} {self.argstr}" for name in self.alias + [self.name]], + textwrap.indent(self.help, '\t') + ]) + +class CmdTable: + def __init__(self): + self._cmd_map = [] + + fns = inspect.getmembers(self, + lambda p: isinstance(p, Callable)) + for _, fn in fns: + if not hasattr(fn, "__annotations__"): + continue + if "__CMD__" not in fn.__annotations__: + continue + + self._cmd_map.append(Executor(fn)) + + def call(self, name, *args): + for exe in self._cmd_map: + if exe.match_name(name): + exe.try_invoke(*args) + return + + raise ShconfigException( + f"command not found {name}") \ No newline at end of file