Last active
February 27, 2026 12:33
-
-
Save synodriver/80c7e9702c5c60fbcb5e4933883419a7 to your computer and use it in GitHub Desktop.
import lua pkgs from py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -*- coding: utf-8 -*- | |
| import sys | |
| from importlib.abc import Loader, MetaPathFinder | |
| from importlib.machinery import ModuleSpec | |
| from pathlib import Path | |
| from types import ModuleType | |
| try: | |
| from lupa.lua import LuaRuntime | |
| except ImportError: | |
| from lupa import LuaRuntime | |
| class LuaFinder(MetaPathFinder): | |
| def __init__(self, lua: LuaRuntime = None, paths: list[str] = None): | |
| self.lua = lua or LuaRuntime() | |
| self.paths = paths or [] | |
| path_str = ";".join(self.paths) | |
| self.lua.globals().package.path += path_str + ";" | |
| # self.lua.execute(f"package.path = package.path .. [[{path_str}]]") | |
| def find_spec(self, fullname, path, target=None): | |
| # print(f"in find_spec fullname: {fullname} path: {path} target: {target}") | |
| if path is not None: # sub package e.g. import a.b; from a import b | |
| maybe_lua_file = fullname[fullname.rfind(".") + 1 :] | |
| lua_file_name = maybe_lua_file + ".lua" | |
| luac_file_name = maybe_lua_file + ".luac" | |
| for p in path: | |
| if (Path(p) / lua_file_name).exists(): # lua file | |
| return ModuleSpec( | |
| fullname, | |
| LuaLoader(self.lua), | |
| origin=str(Path(p) / lua_file_name), | |
| ) | |
| if (Path(p) / luac_file_name).exists(): # luac file | |
| return ModuleSpec( | |
| fullname, | |
| LuaLoader(self.lua), | |
| origin=str(Path(p) / luac_file_name), | |
| ) | |
| if (Path(p) / maybe_lua_file / "init.lua").exists(): # lua dir | |
| spec = ModuleSpec( | |
| fullname, | |
| LuaLoader(self.lua), | |
| origin=str(Path(p) / maybe_lua_file / "init.lua"), | |
| is_package=True, | |
| ) | |
| spec.submodule_search_locations = [str(Path(p) / maybe_lua_file)] | |
| return spec | |
| if ( | |
| Path(p) / maybe_lua_file / "init.luac" | |
| ).exists(): # lua dir with luac file | |
| spec = ModuleSpec( | |
| fullname, | |
| LuaLoader(self.lua), | |
| origin=str(Path(p) / maybe_lua_file / "init.luac"), | |
| is_package=True, | |
| ) | |
| spec.submodule_search_locations = [str(Path(p) / maybe_lua_file)] | |
| return spec | |
| for path_ in self.paths: # top level package e.g. import a | |
| if (Path(path_).parent / (fullname + ".lua")).exists(): # lua file | |
| return ModuleSpec( | |
| fullname, | |
| LuaLoader(self.lua), | |
| origin=str(Path(path_).parent / (fullname + ".lua")), | |
| ) | |
| if (Path(path_).parent / (fullname + ".luac")).exists(): # luac file | |
| return ModuleSpec( | |
| fullname, | |
| LuaLoader(self.lua), | |
| origin=str(Path(path_).parent / (fullname + ".luac")), | |
| ) | |
| if (Path(path_).parent / fullname / "init.lua").exists(): # lua dir | |
| spec = ModuleSpec( | |
| fullname, | |
| LuaLoader(self.lua), | |
| origin=str(Path(path_).parent / fullname / "init.lua"), | |
| is_package=True, | |
| ) | |
| spec.submodule_search_locations = [str(Path(path_).parent / fullname)] | |
| return spec | |
| if ( | |
| Path(path_).parent / fullname / "init.luac" | |
| ).exists(): # lua dir with luac file | |
| spec = ModuleSpec( | |
| fullname, | |
| LuaLoader(self.lua), | |
| origin=str(Path(path_).parent / fullname / "init.luac"), | |
| is_package=True, | |
| ) | |
| spec.submodule_search_locations = [str(Path(path_).parent / fullname)] | |
| return spec | |
| return None | |
| def invalidate_caches(self): | |
| return | |
| class LuaLoader(Loader): | |
| def __init__(self, lua: LuaRuntime): | |
| self.loaded = False | |
| self.lua = lua | |
| def create_module(self, spec: ModuleSpec): | |
| # print(f"in create_module, name: {spec.name} ") | |
| if spec.name in sys.modules: | |
| self.loaded = True | |
| return sys.modules[spec.name] | |
| mod = ModuleType(spec.name) | |
| mod.__file__ = spec.origin | |
| mod.__spec__ = spec | |
| assert self is spec.loader | |
| mod.__loader__ = spec.loader | |
| return mod | |
| def exec_module(self, module): | |
| # print(f"in exec_module, module: {module} ") | |
| lua_mod_table = self.lua.require(module.__name__) | |
| # print(lua_mod_table) | |
| if hasattr(lua_mod_table, "items"): | |
| for k, v in lua_mod_table.items(): | |
| module.__dict__[k.decode() if isinstance(k, bytes) else k] = v | |
| else: | |
| module.__dict__["_main"] = lua_mod_table |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment