diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/infini/loader.py | 152 | ||||
| -rw-r--r-- | src/infini/typing.py | 3 |
2 files changed, 153 insertions, 2 deletions
diff --git a/src/infini/loader.py b/src/infini/loader.py index d5a95699..0686aaeb 100644 --- a/src/infini/loader.py +++ b/src/infini/loader.py @@ -1,2 +1,152 @@ +from importlib.util import spec_from_file_location +from infini.core import Core +from infini.generator import Generator +from infini.handler import Handler +from infini.interceptor import Interceptor +from infini.register import Register +from infini.typing import List, Dict, Sequence, ModuleType, RouterType, Callable +from pathlib import Path + +import inspect +import sys +import importlib +import importlib.abc + + +class InfiniMetaFinder(importlib.abc.MetaPathFinder): + def find_spec(self, fullname: str, path: Sequence[str] | None, target=None): + default_entries = [ + Path.cwd() / "src", + Path.home() / ".ipm" / "src", + ] + + entries: List[Path] = ( + [Path(catch_path).resolve() for catch_path in path] + default_entries + if path + else default_entries + ) + + if "." in fullname: + *_, name = fullname.split(".") + else: + name = fullname + + for entry in entries: + if (entry / name).is_dir(): + filename = entry / name / "src" / "__init__.py" + submodule_locations = [entry / name / "src"] + if not filename.exists(): + filename = entry / name / "src" / (name + ".py") + else: + continue + if not filename.exists(): + continue + + return spec_from_file_location( + fullname, + filename, + loader=InfiniLoader(str(filename)), + submodule_search_locations=[ + str(submodule_location) + for submodule_location in submodule_locations + ] + if submodule_locations + else None, + ) + + return None + + +class InfiniLoader(importlib.abc.Loader): + def __init__(self, filename): + self.filename = filename + + def create_module(self, _): + return None + + def exec_module(self, module): + with open(self.filename) as f: + data = f.read() + + exec(data, vars(module)) + + +def install(): + sys.meta_path.insert(0, InfiniMetaFinder()) + + +def uninstall(): + for meta_path in sys.meta_path: + if isinstance(meta_path, InfiniMetaFinder): + sys.meta_path.remove(meta_path) + break + + class Loader: - ... + pre_interceptors: List[RouterType] + handlers: List[RouterType] + events: Dict[str, str] + global_variables: Dict[str, str | Callable] + interceptors: List[RouterType] + + def __init__(self) -> None: + self.pre_interceptors = [] + self.handlers = [] + self.events = {} + self.global_variables = {} + self.interceptors = [] + self.prepare() + + def _find_register_variables(self, module: ModuleType) -> List[Register]: + module_variables = inspect.getmembers(module) + register_variables = [ + var for _, var in module_variables if isinstance(var, Register) + ] + return register_variables + + def prepare(self) -> None: + install() + + def load(self, name: str) -> ModuleType: + self.prepare() + + module = importlib.import_module(name) + registers = self._find_register_variables(module) + for register in registers: + self.load_from_register(register) + if not registers: + # TODO 警告内容 + ... + + return module + + def load_from_register(self, register: Register): + self.pre_interceptors.extend(register.pre_interceptors) + self.handlers.extend(register.handlers) + self.events.update(register.events) + self.global_variables.update(register.global_variables) + self.interceptors.extend(register.interceptors) + + def close(self): + uninstall() + + def inject(self, core: Core): + pre_interceptor = Interceptor() + pre_interceptor.interceptors = self.pre_interceptors + handler = Handler() + handler.handlers = self.handlers + generator = Generator() + generator.events = self.events + generator.global_variables = self.global_variables + interceptor = Interceptor() + interceptor.interceptors = self.interceptors + + core.pre_interceptor = pre_interceptor + core.handler = handler + core.generator = generator + core.interceptor = interceptor + + def output(self) -> Core: + core = Core() + self.inject(core) + return core diff --git a/src/infini/typing.py b/src/infini/typing.py index 0a0d3292..a1273f02 100644 --- a/src/infini/typing.py +++ b/src/infini/typing.py @@ -5,12 +5,13 @@ from typing import ( Generic as Generic, Callable as Callable, Literal as Literal, + Sequence as Sequence, overload as overload, TypeVar, TypedDict, Union, ) -from types import ModuleType as ModuleType +from types import ModuleType as ModuleType, GeneratorType as GeneratorType from . import router, input, output T = TypeVar("T") |
