Source code for simvx.core.script_embed

"""Virtual importlib finder/loader for embedded scripts.

Embedded scripts are source code stored directly in the scene/project file
(on ``node._script_embedded``) rather than as separate ``.py`` files. This
module installs a ``sys.meta_path`` finder that makes those scripts importable
via standard ``import`` machinery, so ScriptManager can load them the same way
as file-backed scripts.

Usage:
    from simvx.core.script_embed import EmbeddedScriptFinder

    EmbeddedScriptFinder.register("_simvx_embed_my_script", source_code)
    import _simvx_embed_my_script  # works!
    EmbeddedScriptFinder.unregister("_simvx_embed_my_script")
"""


from __future__ import annotations

import importlib.abc
import importlib.machinery
import logging
import sys

log = logging.getLogger(__name__)


[docs] class EmbeddedScriptFinder(importlib.abc.MetaPathFinder): """Finds modules registered as embedded scripts.""" _registry: dict[str, str] = {}
[docs] @classmethod def register(cls, module_name: str, source: str): """Register source code under *module_name* for import.""" cls._registry[module_name] = source # Invalidate any cached "not found" result sys.modules.pop(module_name, None)
[docs] @classmethod def unregister(cls, module_name: str): """Remove an embedded module registration.""" cls._registry.pop(module_name, None) sys.modules.pop(module_name, None)
[docs] def find_module(self, fullname, path=None): if fullname in self._registry: return _EmbeddedLoader() return None
[docs] def find_spec(self, fullname, path, target=None): if fullname not in self._registry: return None return importlib.machinery.ModuleSpec( fullname, _EmbeddedLoader(), origin=f"<embedded:{fullname}>", )
class _EmbeddedLoader(importlib.abc.Loader): """Loads embedded script source via exec().""" def create_module(self, spec): return None # use default semantics def exec_module(self, module): source = EmbeddedScriptFinder._registry.get(module.__name__, "") code = compile(source, f"<embedded:{module.__name__}>", "exec") exec(code, module.__dict__) # Install the finder once at import time if not any(isinstance(f, EmbeddedScriptFinder) for f in sys.meta_path): sys.meta_path.insert(0, EmbeddedScriptFinder())