| 6 | const invoke = (name, args) => `${name}(code, ${args.join(", ")})`; |
| 7 | |
| 8 | const donkey = ({ |
| 9 | type = "py", |
| 10 | persistent, |
| 11 | terminal, |
| 12 | config, |
| 13 | serviceWorker, |
| 14 | }) => { |
| 15 | const globals = terminal ? '{"__terminal__":__terminal__}' : "{}"; |
| 16 | const args = persistent ? ["globals()", "__locals__"] : [globals, "{}"]; |
| 17 | |
| 18 | const src = URL.createObjectURL( |
| 19 | new Blob([ |
| 20 | [ |
| 21 | // this array is to better minify this code once in production |
| 22 | "from pyscript import sync, config", |
| 23 | '__message__ = lambda e,v: f"\x1b[31m\x1b[1m{e.__name__}\x1b[0m: {v}"', |
| 24 | "__locals__ = {}", |
| 25 | 'if config["type"] == "py":', |
| 26 | " import sys", |
| 27 | " def __error__(_):", |
| 28 | " info = sys.exc_info()", |
| 29 | " return __message__(info[0], info[1])", |
| 30 | "else:", |
| 31 | " __error__ = lambda e: __message__(e.__class__, e.value)", |
| 32 | "def execute(code):", |
| 33 | ` try: return ${invoke("exec", args)};`, |
| 34 | " except Exception as e: print(__error__(e));", |
| 35 | "def evaluate(code):", |
| 36 | ` try: return ${invoke("eval", args)};`, |
| 37 | " except Exception as e: print(__error__(e));", |
| 38 | "sync.execute = execute", |
| 39 | "sync.evaluate = evaluate", |
| 40 | ].join("\n"), |
| 41 | ]), |
| 42 | ); |
| 43 | |
| 44 | // create the script that exposes the code to execute or evaluate |
| 45 | const script = assign(document.createElement("script"), { type, src }); |
| 46 | script.toggleAttribute("worker", true); |
| 47 | script.toggleAttribute("terminal", true); |
| 48 | if (terminal) script.setAttribute("target", terminal); |
| 49 | if (config) { |
| 50 | script.setAttribute( |
| 51 | "config", |
| 52 | typeof config === "string" ? config : stringify(config), |
| 53 | ); |
| 54 | } |
| 55 | if (serviceWorker) script.setAttribute("service-worker", serviceWorker); |
| 56 | |
| 57 | return addPromiseListener( |
| 58 | document.body.appendChild(script), |
| 59 | `${type}:done`, |
| 60 | { stopPropagation: true }, |
| 61 | ).then(() => { |
| 62 | URL.revokeObjectURL(src); |
| 63 | return script; |
| 64 | }); |
| 65 | }; |