def run_module(module_name: str, args: list[str]):
if (cwd := str(Path.cwd())) not in sys.path:
sys.path.insert(0, cwd)
from importlib.util import find_spec
from .core import ReactiveModule, SyncReloader, _loader, patch_meta_path
patch_meta_path()
spec = find_spec(module_name)
if spec is None:
raise ModuleNotFoundError(f"No module named '{module_name}'")
if spec.submodule_search_locations is not None:
# It's a package, look for __main__.py
spec = find_spec(f"{module_name}.__main__")
if spec and spec.origin:
entry = spec.origin
else:
raise ModuleNotFoundError(f"No module named '{module_name}.__main__'; '{module_name}' is a package and cannot be directly executed")
elif spec.origin is None:
raise ModuleNotFoundError(f"Cannot find entry point for module '{module_name}'")
else:
entry = spec.origin
args[0] = entry # Replace the first argument with the full path
_argv = sys.argv[:]
sys.argv[:] = args
_main = sys.modules["__main__"]
try:
reloader = SyncReloader(entry)
if spec.loader is not _loader:
spec.loader = _loader # make it reactive
namespace = {"__file__": entry, "__name__": "__main__", "__spec__": spec, "__loader__": _loader, "__package__": spec.parent, "__cached__": None, "__builtins__": builtins}
sys.modules["__main__"] = reloader.entry_module = ReactiveModule(Path(entry), namespace, "__main__")
reloader.keep_watching_until_interrupt()
finally:
sys.argv[:] = _argv
sys.modules["__main__"] = _main