summaryrefslogtreecommitdiff
path: root/Biz/Repl.py
blob: 9844abfd3a679122fd949e0c2165aa16d9693e7c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
"""
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)