pumpkin-api-py/src/pumpkin_api/build.py
2026-06-16 10:27:14 -07:00

69 lines
2.2 KiB
Python

import argparse
import os
import tempfile
import componentize_py
def _build_entrypoint_wrapper(app_module: str, wrapper_dir: str) -> str:
wrapper_name = "_pumpkin_componentize_entry"
wrapper_path = os.path.join(wrapper_dir, f"{wrapper_name}.py")
with open(wrapper_path, "w", encoding="utf-8") as wrapper_file:
wrapper_file.write(
"from pathlib import Path\n"
"from pumpkin_api.impl import MetadataImpl, WitWorldImpl\n\n"
"WitWorld = WitWorldImpl\n"
"Metadata = MetadataImpl\n\n"
f"import {app_module}\n"
)
return wrapper_name
def main():
parser = argparse.ArgumentParser(description="Build a Pumpkin Python plugin")
parser.add_argument(
"app_module", help="The python module containing the plugin (e.g. 'main')"
)
parser.add_argument(
"-o", "--output", default="plugin.wasm", help="Output wasm file name"
)
args = parser.parse_args()
import pumpkin_api
pkg_dir = os.path.dirname(pumpkin_api.__file__)
# In source checkout, they are in wit_files/repo/...
# In installed package, they are directly in wit_files/
wit_dir = os.path.join(pkg_dir, "..", "..", "wit", "v0.1")
if not os.path.exists(wit_dir):
wit_dir = os.path.join(pkg_dir, "wit")
# Pass the parent directory of pumpkin_api to componentize-py so it can resolve `pumpkin_api` module
# in case it's not installed in a standard site-packages (e.g. editable install or no venv)
pkg_parent_dir = os.path.dirname(pkg_dir)
with tempfile.TemporaryDirectory(prefix="pumpkin-api-build-") as wrapper_dir:
wrapper_module = _build_entrypoint_wrapper(args.app_module, wrapper_dir)
componentize_py.componentize(
wit_path=[wit_dir],
worlds=[],
features=[],
all_features=False,
world_module="wit_world",
python_path=[".", pkg_parent_dir, wrapper_dir],
module_worlds=[],
app_name=wrapper_module,
output_path=args.output,
stub_wasi=False,
import_interface_names=[],
export_interface_names=[],
full_names=False,
intersect_world=None,
)
if __name__ == "__main__":
main()