""" This module attempts to emulate the workflow of ghci or lisp repls. It uses importlib to load a namespace from the given path. It then binds 'r()' to a function that reloads the same namespace. """ import importlib import sys def use(ns: str, path: str) -> None: """ Load or reload the module named 'ns' from 'path'. Like `use` in the Guile Scheme repl. """ info(f"loading {ns} from {path}") spec = importlib.util.spec_from_file_location(ns, path) module = importlib.util.module_from_spec(spec) # delete module and its imported names if its already loaded if ns in sys.modules: del sys.modules[ns] for name in module.__dict__: if name in globals(): del globals()[name] sys.modules[ns] = module spec.loader.exec_module(module) names = [x for x in module.__dict__] globals().update({k: getattr(module, k) for k in names}) def info(s): print(f"info: repl: {s}") if __name__ == "__main__": NS = sys.argv[1] PATH = sys.argv[2] use(NS, PATH) info("use reload() or _r() after making changes") sys.ps1 = f"{NS}> " sys.ps2 = f"{NS}| " def reload(): return use(NS, PATH) def _r(): return use(NS, PATH)