mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-19 18:27:29 -05:00
Add a "donkey" worker that execs or evaluates all the things (#2210)
* WIP * Add a "donkey" worker that execs or evaluates all the things --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
8c6bfecbff
commit
f827efe2fc
18
core/package-lock.json
generated
18
core/package-lock.json
generated
@@ -368,9 +368,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/common": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz",
|
||||
"integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==",
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.2.tgz",
|
||||
"integrity": "sha512-Z+R3hN6kXbgBWAuejUNPihylAL1Z5CaFqnIe0nTX8Ej+XlIy3EGtXxn6WtLMO+os2hRkQvm2yvaGMYliUzlJaw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -1208,9 +1208,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001664",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz",
|
||||
"integrity": "sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g==",
|
||||
"version": "1.0.30001666",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001666.tgz",
|
||||
"integrity": "sha512-gD14ICmoV5ZZM1OdzPWmpx+q4GyefaK06zi8hmfHV5xe4/2nOQX3+Dw5o+fSqOws2xVwL9j+anOPFwHzdEdV4g==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -1637,9 +1637,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.30",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.30.tgz",
|
||||
"integrity": "sha512-sXI35EBN4lYxzc/pIGorlymYNzDBOqkSlVRe6MkgBsW/hW1tpC/HDJ2fjG7XnjakzfLEuvdmux0Mjs6jHq4UOA==",
|
||||
"version": "1.5.31",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.31.tgz",
|
||||
"integrity": "sha512-QcDoBbQeYt0+3CWcK/rEbuHvwpbT/8SV9T3OSgs6cX1FlcUAkgrkqbg9zLnDrMM/rLamzQwal4LYFCiWk861Tg==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
|
||||
@@ -37,6 +37,11 @@ import {
|
||||
import { stdlib, optional } from "./stdlib.js";
|
||||
export { stdlib, optional, inputFailure };
|
||||
|
||||
export const donkey = (options) =>
|
||||
import(/* webpackIgnore: true */ "./plugins/donkey.js").then((module) =>
|
||||
module.default(options),
|
||||
);
|
||||
|
||||
// generic helper to disambiguate between custom element and script
|
||||
const isScript = ({ tagName }) => tagName === "SCRIPT";
|
||||
|
||||
|
||||
@@ -5,6 +5,11 @@ export default {
|
||||
/* webpackIgnore: true */
|
||||
"./plugins/deprecations-manager.js"
|
||||
),
|
||||
donkey: () =>
|
||||
import(
|
||||
/* webpackIgnore: true */
|
||||
"./plugins/donkey.js"
|
||||
),
|
||||
error: () =>
|
||||
import(
|
||||
/* webpackIgnore: true */
|
||||
|
||||
64
core/src/plugins/donkey.js
Normal file
64
core/src/plugins/donkey.js
Normal file
@@ -0,0 +1,64 @@
|
||||
import { assign, dedent } from "polyscript/exports";
|
||||
|
||||
const invoke = (name, args) => `${name}(code, ${args.join(", ")})`;
|
||||
|
||||
export default (options = {}) => {
|
||||
const type = options.type || "py";
|
||||
const args = options.persistent
|
||||
? ["globals()", "__locals__"]
|
||||
: ["{}", "{}"];
|
||||
const src = URL.createObjectURL(
|
||||
new Blob([
|
||||
dedent(`
|
||||
from pyscript import sync, config
|
||||
__message__ = lambda e,v: f"\x1b[31m\x1b[1m{e.__name__}\x1b[0m: {v}"
|
||||
__locals__ = {}
|
||||
if config["type"] == "py":
|
||||
import sys
|
||||
def __error__(_):
|
||||
info = sys.exc_info()
|
||||
return __message__(info[0], info[1])
|
||||
else:
|
||||
__error__ = lambda e: __message__(e.__class__, e.value)
|
||||
def execute(code):
|
||||
try: return ${invoke("exec", args)};
|
||||
except Exception as e: print(__error__(e));
|
||||
def evaluate(code):
|
||||
try: return ${invoke("eval", args)};
|
||||
except Exception as e: print(__error__(e));
|
||||
sync.execute = execute
|
||||
sync.evaluate = evaluate
|
||||
`),
|
||||
]),
|
||||
);
|
||||
|
||||
const script = assign(document.createElement("script"), { type, src });
|
||||
|
||||
script.toggleAttribute("worker", true);
|
||||
script.toggleAttribute("terminal", true);
|
||||
if (options.terminal) script.setAttribute("target", options.terminal);
|
||||
if (options.config)
|
||||
script.setAttribute("config", JSON.stringify(options.config));
|
||||
|
||||
return new Promise((resolve) => {
|
||||
script.addEventListener(`${type}:done`, (event) => {
|
||||
event.stopPropagation();
|
||||
URL.revokeObjectURL(src);
|
||||
const { xworker, process, terminal } = script;
|
||||
const { execute, evaluate } = xworker.sync;
|
||||
script.remove();
|
||||
resolve({
|
||||
process,
|
||||
execute: (code) => execute(dedent(code)),
|
||||
evaluate: (code) => evaluate(dedent(code)),
|
||||
clear: () => terminal.clear(),
|
||||
reset: () => terminal.reset(),
|
||||
kill: () => {
|
||||
xworker.terminate();
|
||||
terminal.dispose();
|
||||
},
|
||||
});
|
||||
});
|
||||
document.body.append(script);
|
||||
});
|
||||
};
|
||||
@@ -14,5 +14,5 @@
|
||||
a:hover { opacity: 1; }
|
||||
</style>
|
||||
</head>
|
||||
<body><ul><li><strong><span>javascript</span></strong><ul><li><a href="./javascript/async-listener.html">async-listener<small>.html</small></a></li><li><a href="./javascript/config-url.html">config-url<small>.html</small></a></li><li><a href="./javascript/config_type.html">config_type<small>.html</small></a></li><li><strong><a href="./javascript/fetch/index.html">fetch</a></strong></li><li><a href="./javascript/ffi.html">ffi<small>.html</small></a></li><li><a href="./javascript/hooks.html">hooks<small>.html</small></a></li><li><strong><a href="./javascript/issue-2093/index.html">issue-2093</a></strong></li><li><a href="./javascript/js-storage.html">js-storage<small>.html</small></a></li><li><a href="./javascript/js_modules.html">js_modules<small>.html</small></a></li><li><strong><a href="./javascript/loader/index.html">loader</a></strong></li><li><a href="./javascript/mpy.html">mpy<small>.html</small></a></li><li><a href="./javascript/py-terminal-main.html">py-terminal-main<small>.html</small></a></li><li><a href="./javascript/py-terminal-worker.html">py-terminal-worker<small>.html</small></a></li><li><a href="./javascript/py-terminal.html">py-terminal<small>.html</small></a></li><li><a href="./javascript/py-terminals.html">py-terminals<small>.html</small></a></li><li><a href="./javascript/storage.html">storage<small>.html</small></a></li><li><strong><a href="./javascript/workers/index.html">workers</a></strong><ul><li><a href="./javascript/workers/named.html">named<small>.html</small></a></li></ul></li></ul></li><li><strong><a href="./manual/index.html">manual</a></strong><ul><li><a href="./manual/all-done.html">all-done<small>.html</small></a></li><li><a href="./manual/async.html">async<small>.html</small></a></li><li><a href="./manual/camera.html">camera<small>.html</small></a></li><li><a href="./manual/click.html">click<small>.html</small></a></li><li><a href="./manual/code-a-part.html">code-a-part<small>.html</small></a></li><li><a href="./manual/combo.html">combo<small>.html</small></a></li><li><a href="./manual/config.html">config<small>.html</small></a></li><li><a href="./manual/create-element.html">create-element<small>.html</small></a></li><li><a href="./manual/dialog.html">dialog<small>.html</small></a></li><li><a href="./manual/display.html">display<small>.html</small></a></li><li><a href="./manual/error.html">error<small>.html</small></a></li><li><a href="./manual/html-decode.html">html-decode<small>.html</small></a></li><li><a href="./manual/input.html">input<small>.html</small></a></li><li><a href="./manual/interpreter.html">interpreter<small>.html</small></a></li><li><strong><a href="./manual/issue-7015/index.html">issue-7015</a></strong></li><li><a href="./manual/multi.html">multi<small>.html</small></a></li><li><a href="./manual/multiple-editors.html">multiple-editors<small>.html</small></a></li><li><a href="./manual/no-error.html">no-error<small>.html</small></a></li><li><strong><a href="./manual/no_sab/index.html">no_sab</a></strong></li><li><strong><a href="./manual/piratical/index.html">piratical</a></strong></li><li><a href="./manual/py-editor.html">py-editor<small>.html</small></a></li><li><a href="./manual/py-editor-failure.html">py-editor-failure<small>.html</small></a></li><li><strong><a href="./manual/py-terminals/index.html">py-terminals</a></strong><ul><li><a href="./manual/py-terminals/no-repl.html">no-repl<small>.html</small></a></li><li><a href="./manual/py-terminals/repl.html">repl<small>.html</small></a></li></ul></li><li><a href="./manual/py_modules.html">py_modules<small>.html</small></a></li><li><strong><a href="./manual/service-worker/index.html">service-worker</a></strong></li><li><a href="./manual/split-config.html">split-config<small>.html</small></a></li><li><a href="./manual/submit.html">submit<small>.html</small></a></li><li><a href="./manual/target.html">target<small>.html</small></a></li><li><a href="./manual/test_display_HTML.html">test_display_HTML<small>.html</small></a></li><li><a href="./manual/test_when.html">test_when<small>.html</small></a></li><li><a href="./manual/worker.html">worker<small>.html</small></a></li></ul></li><li><strong><a href="./python/index.html">python</a></strong></li></ul></body>
|
||||
<body><ul><li><strong><span>javascript</span></strong><ul><li><a href="./javascript/async-listener.html">async-listener<small>.html</small></a></li><li><a href="./javascript/config-url.html">config-url<small>.html</small></a></li><li><a href="./javascript/config_type.html">config_type<small>.html</small></a></li><li><strong><a href="./javascript/fetch/index.html">fetch</a></strong></li><li><a href="./javascript/ffi.html">ffi<small>.html</small></a></li><li><a href="./javascript/hooks.html">hooks<small>.html</small></a></li><li><strong><a href="./javascript/issue-2093/index.html">issue-2093</a></strong></li><li><a href="./javascript/js-storage.html">js-storage<small>.html</small></a></li><li><a href="./javascript/js_modules.html">js_modules<small>.html</small></a></li><li><strong><a href="./javascript/loader/index.html">loader</a></strong></li><li><a href="./javascript/mpy.html">mpy<small>.html</small></a></li><li><a href="./javascript/py-terminal-main.html">py-terminal-main<small>.html</small></a></li><li><a href="./javascript/py-terminal-worker.html">py-terminal-worker<small>.html</small></a></li><li><a href="./javascript/py-terminal.html">py-terminal<small>.html</small></a></li><li><a href="./javascript/py-terminals.html">py-terminals<small>.html</small></a></li><li><a href="./javascript/storage.html">storage<small>.html</small></a></li><li><strong><a href="./javascript/workers/index.html">workers</a></strong><ul><li><a href="./javascript/workers/named.html">named<small>.html</small></a></li></ul></li></ul></li><li><strong><a href="./manual/index.html">manual</a></strong><ul><li><a href="./manual/all-done.html">all-done<small>.html</small></a></li><li><a href="./manual/async.html">async<small>.html</small></a></li><li><a href="./manual/camera.html">camera<small>.html</small></a></li><li><a href="./manual/click.html">click<small>.html</small></a></li><li><a href="./manual/code-a-part.html">code-a-part<small>.html</small></a></li><li><a href="./manual/combo.html">combo<small>.html</small></a></li><li><a href="./manual/config.html">config<small>.html</small></a></li><li><a href="./manual/create-element.html">create-element<small>.html</small></a></li><li><a href="./manual/dialog.html">dialog<small>.html</small></a></li><li><a href="./manual/display.html">display<small>.html</small></a></li><li><strong><a href="./manual/donkey/index.html">donkey</a></strong></li><li><a href="./manual/error.html">error<small>.html</small></a></li><li><a href="./manual/html-decode.html">html-decode<small>.html</small></a></li><li><a href="./manual/input.html">input<small>.html</small></a></li><li><a href="./manual/interpreter.html">interpreter<small>.html</small></a></li><li><strong><a href="./manual/issue-7015/index.html">issue-7015</a></strong></li><li><a href="./manual/multi.html">multi<small>.html</small></a></li><li><a href="./manual/multiple-editors.html">multiple-editors<small>.html</small></a></li><li><a href="./manual/no-error.html">no-error<small>.html</small></a></li><li><strong><a href="./manual/no_sab/index.html">no_sab</a></strong></li><li><strong><a href="./manual/piratical/index.html">piratical</a></strong></li><li><a href="./manual/py-editor.html">py-editor<small>.html</small></a></li><li><a href="./manual/py-editor-failure.html">py-editor-failure<small>.html</small></a></li><li><strong><a href="./manual/py-terminals/index.html">py-terminals</a></strong><ul><li><a href="./manual/py-terminals/no-repl.html">no-repl<small>.html</small></a></li><li><a href="./manual/py-terminals/repl.html">repl<small>.html</small></a></li></ul></li><li><a href="./manual/py_modules.html">py_modules<small>.html</small></a></li><li><strong><a href="./manual/service-worker/index.html">service-worker</a></strong></li><li><a href="./manual/split-config.html">split-config<small>.html</small></a></li><li><a href="./manual/submit.html">submit<small>.html</small></a></li><li><a href="./manual/target.html">target<small>.html</small></a></li><li><a href="./manual/test_display_HTML.html">test_display_HTML<small>.html</small></a></li><li><a href="./manual/test_when.html">test_when<small>.html</small></a></li><li><a href="./manual/worker.html">worker<small>.html</small></a></li></ul></li><li><strong><a href="./python/index.html">python</a></strong></li></ul></body>
|
||||
</html>
|
||||
|
||||
15
core/tests/manual/donkey/index.html
Normal file
15
core/tests/manual/donkey/index.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<link rel="stylesheet" href="../../../dist/core.css" />
|
||||
<script type="module" src="./index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container"></div>
|
||||
<button id="run" disabled>Run</button>
|
||||
<button id="clear" disabled>Clear</button>
|
||||
<button id="kill" disabled>Kill</button>
|
||||
</body>
|
||||
</html>
|
||||
34
core/tests/manual/donkey/index.js
Normal file
34
core/tests/manual/donkey/index.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import { donkey } from '../../../dist/core.js';
|
||||
|
||||
const runButton = document.querySelector('#run');
|
||||
const clearButton = document.querySelector('#clear');
|
||||
const killButton = document.querySelector('#kill');
|
||||
|
||||
const {
|
||||
execute, // exec(expression)
|
||||
evaluate, // eval(expression)
|
||||
process, // process(code)
|
||||
clear,
|
||||
kill,
|
||||
} = await donkey({ terminal: '#container' });
|
||||
|
||||
clearButton.onclick = clear;
|
||||
killButton.onclick = kill;
|
||||
|
||||
runButton.disabled = false;
|
||||
runButton.onclick = async () => {
|
||||
killButton.disabled = false;
|
||||
clearButton.disabled = true;
|
||||
runButton.disabled = true;
|
||||
// multiline code
|
||||
await execute(`
|
||||
a = 1 + 2
|
||||
print(f'1 + 2 = {a}')
|
||||
`);
|
||||
// single expression evaluation
|
||||
const name = await evaluate('input("what is your name? ")');
|
||||
alert(`Hello ${name}`);
|
||||
killButton.disabled = true;
|
||||
clearButton.disabled = false;
|
||||
runButton.disabled = false;
|
||||
};
|
||||
1
core/types/core.d.ts
vendored
1
core/types/core.d.ts
vendored
@@ -1,3 +1,4 @@
|
||||
export function donkey(options: any): Promise<any>;
|
||||
export function offline_interpreter(config: any): string;
|
||||
import { stdlib } from "./stdlib.js";
|
||||
import { optional } from "./stdlib.js";
|
||||
|
||||
1
core/types/plugins.d.ts
vendored
1
core/types/plugins.d.ts
vendored
@@ -1,5 +1,6 @@
|
||||
declare const _default: {
|
||||
"deprecations-manager": () => Promise<typeof import("./plugins/deprecations-manager.js")>;
|
||||
donkey: () => Promise<typeof import("./plugins/donkey.js")>;
|
||||
error: () => Promise<typeof import("./plugins/error.js")>;
|
||||
"py-editor": () => Promise<typeof import("./plugins/py-editor.js")>;
|
||||
"py-terminal": () => Promise<typeof import("./plugins/py-terminal.js")>;
|
||||
|
||||
2
core/types/plugins/donkey.d.ts
vendored
Normal file
2
core/types/plugins/donkey.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare function _default(options?: {}): Promise<any>;
|
||||
export default _default;
|
||||
Reference in New Issue
Block a user