From a9717afeb7ac666d79b54fc17184b89b918d665b Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Wed, 24 Jan 2024 13:19:33 +0100 Subject: [PATCH 001/179] updated Pyodide to 0.25.0 (#1949) --- pyscript.core/package-lock.json | 20 ++++++++++---------- pyscript.core/package.json | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index f834954070f..16211fcbb56 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.3.18", + "version": "0.3.19", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.3.18", + "version": "0.3.19", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.6.13", + "polyscript": "^0.6.15", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -21,7 +21,7 @@ "@codemirror/lang-python": "^6.1.3", "@codemirror/language": "^6.10.0", "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.23.0", + "@codemirror/view": "^6.23.1", "@playwright/test": "^1.41.1", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", @@ -133,9 +133,9 @@ "dev": true }, "node_modules/@codemirror/view": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.23.0.tgz", - "integrity": "sha512-/51px9N4uW8NpuWkyUX+iam5+PM6io2fm+QmRnzwqBy5v/pwGg9T0kILFtYeum8hjuvENtgsGNKluOfqIICmeQ==", + "version": "6.23.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.23.1.tgz", + "integrity": "sha512-J2Xnn5lFYT1ZN/5ewEoMBCmLlL71lZ3mBdb7cUEuHhX2ESoSrNEucpsDXpX22EuTGm9LOgC9v4Z0wx+Ez8QmGA==", "dev": true, "dependencies": { "@codemirror/state": "^6.4.0", @@ -2403,9 +2403,9 @@ } }, "node_modules/polyscript": { - "version": "0.6.13", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.6.13.tgz", - "integrity": "sha512-VlRLIf6KGqZRVqqiA6eUbepxOe5Sfc2OAirlrzMBM/uzD62+MTUwJsr0CP/pU+u3Gozk15DUYpV2wez3CbCzUQ==", + "version": "0.6.15", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.6.15.tgz", + "integrity": "sha512-ppkcEgNlH+/+S4+bxSy+oda/V9Qo/M7IA4ddhoCeVUObRMZBiOrvWkStZDI/xs/Mw3nbAZ4L772+TIz/RgfU2Q==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 031defba77a..a5deffca4d8 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.3.18", + "version": "0.3.19", "type": "module", "description": "PyScript", "module": "./index.js", @@ -42,7 +42,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.6.13", + "polyscript": "^0.6.15", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -52,7 +52,7 @@ "@codemirror/lang-python": "^6.1.3", "@codemirror/language": "^6.10.0", "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.23.0", + "@codemirror/view": "^6.23.1", "@playwright/test": "^1.41.1", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", From f6470dcad56d030cd1528ad26b1d80530addd7ea Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Wed, 24 Jan 2024 17:33:55 +0100 Subject: [PATCH 002/179] Multiple Worker based Terminals (#1948) Multiple Worker based Terminals --- pyscript.core/package-lock.json | 4 +- pyscript.core/package.json | 2 +- pyscript.core/src/plugins/py-terminal.js | 301 ++++++++++-------- pyscript.core/src/sync.js | 3 + pyscript.core/test/mpy.spec.js | 5 + pyscript.core/test/py-terminal-worker.html | 3 +- pyscript.core/test/py-terminals.html | 27 ++ .../tests/integration/test_py_terminal.py | 5 +- pyscript.core/types/sync.d.ts | 1 + 9 files changed, 204 insertions(+), 147 deletions(-) create mode 100644 pyscript.core/test/py-terminals.html diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 16211fcbb56..0fb24c5bbd6 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.3.19", + "version": "0.3.20", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.3.19", + "version": "0.3.20", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index a5deffca4d8..07a92902d42 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.3.19", + "version": "0.3.20", "type": "module", "description": "PyScript", "module": "./index.js", diff --git a/pyscript.core/src/plugins/py-terminal.js b/pyscript.core/src/plugins/py-terminal.js index edf9db3cd27..bd66156bf22 100644 --- a/pyscript.core/src/plugins/py-terminal.js +++ b/pyscript.core/src/plugins/py-terminal.js @@ -14,31 +14,73 @@ const notifyAndThrow = (message) => { throw new Error(message); }; +const notParsedYet = (script) => !bootstrapped.has(script); + +const onceOnMain = ({ attributes: { worker } }) => !worker; + +const bootstrapped = new WeakSet(); + +let addStyle = true; + +// this callback will be serialized as string and it never needs +// to be invoked multiple times. Each xworker here is bootstrapped +// only once thanks to the `sync.is_pyterminal()` check. +const workerReady = ({ interpreter, io, run }, { sync }) => { + if (!sync.is_pyterminal()) return; + + // in workers it's always safe to grab the polyscript currentScript + run("from polyscript.currentScript import terminal as __terminal__"); + + // This part is inevitably duplicated as external scope + // can't be reached by workers out of the box. + // The detail is that here we use sync though, not readline. + const decoder = new TextDecoder(); + let data = ""; + const generic = { + isatty: true, + write(buffer) { + data = decoder.decode(buffer); + sync.pyterminal_write(data); + return buffer.length; + }, + }; + interpreter.setStdout(generic); + interpreter.setStderr(generic); + interpreter.setStdin({ + isatty: true, + stdin: () => sync.pyterminal_read(data), + }); + + io.stderr = (error) => { + sync.pyterminal_write(`${error.message || error}\n`); + }; +}; + const pyTerminal = async () => { const terminals = document.querySelectorAll(SELECTOR); - // no results will look further for runtime nodes - if (!terminals.length) return; + const unknown = [].filter.call(terminals, notParsedYet); - // if we arrived this far, let's drop the MutationObserver - // as we only support one terminal per page (right now). - mo.disconnect(); + // no results will look further for runtime nodes + if (!unknown.length) return; + // early flag elements as known to avoid concurrent + // MutationObserver invokes of this async handler + else unknown.forEach(bootstrapped.add, bootstrapped); // we currently support only one terminal as in "classic" - if (terminals.length > 1) notifyAndThrow("You can use at most 1 terminal."); - - const [element] = terminals; - // hopefully to be removed in the near future! - if (element.matches('script[type="mpy"],mpy-script')) - notifyAndThrow("Unsupported terminal."); + if ([].filter.call(terminals, onceOnMain).length > 1) + notifyAndThrow("You can use at most 1 main terminal"); // import styles lazily - document.head.append( - Object.assign(document.createElement("link"), { - rel: "stylesheet", - href: new URL("./xterm.css", import.meta.url), - }), - ); + if (addStyle) { + addStyle = false; + document.head.append( + Object.assign(document.createElement("link"), { + rel: "stylesheet", + href: new URL("./xterm.css", import.meta.url), + }), + ); + } // lazy load these only when a valid terminal is found const [{ Terminal }, { Readline }, { FitAddon }] = await Promise.all([ @@ -47,136 +89,113 @@ const pyTerminal = async () => { import(/* webpackIgnore: true */ "../3rd-party/xterm_addon-fit.js"), ]); - const readline = new Readline(); - - // common main thread initialization for both worker - // or main case, bootstrapping the terminal on its target - const init = (options) => { - let target = element; - const selector = element.getAttribute("target"); - if (selector) { - target = - document.getElementById(selector) || - document.querySelector(selector); - if (!target) throw new Error(`Unknown target ${selector}`); - } else { - target = document.createElement("py-terminal"); - target.style.display = "block"; - element.after(target); - } - const terminal = new Terminal({ - theme: { - background: "#191A19", - foreground: "#F5F2E7", - }, - ...options, - }); - const fitAddon = new FitAddon(); - terminal.loadAddon(fitAddon); - terminal.loadAddon(readline); - terminal.open(target); - fitAddon.fit(); - terminal.focus(); - defineProperty(element, "terminal", { value: terminal }); - return terminal; - }; - - // branch logic for the worker - if (element.hasAttribute("worker")) { - // when the remote thread onReady triggers: - // setup the interpreter stdout and stderr - const workerReady = ({ interpreter, io, run }, { sync }) => { - // in workers it's always safe to grab the polyscript currentScript - run( - "from polyscript.currentScript import terminal as __terminal__", - ); - sync.pyterminal_drop_hooks(); - - // This part is inevitably duplicated as external scope - // can't be reached by workers out of the box. - // The detail is that here we use sync though, not readline. - const decoder = new TextDecoder(); - let data = ""; - const generic = { - isatty: true, - write(buffer) { - data = decoder.decode(buffer); - sync.pyterminal_write(data); - return buffer.length; + for (const element of unknown) { + // hopefully to be removed in the near future! + if (element.matches('script[type="mpy"],mpy-script')) + notifyAndThrow("Unsupported terminal."); + + const readline = new Readline(); + + // common main thread initialization for both worker + // or main case, bootstrapping the terminal on its target + const init = (options) => { + let target = element; + const selector = element.getAttribute("target"); + if (selector) { + target = + document.getElementById(selector) || + document.querySelector(selector); + if (!target) throw new Error(`Unknown target ${selector}`); + } else { + target = document.createElement("py-terminal"); + target.style.display = "block"; + element.after(target); + } + const terminal = new Terminal({ + theme: { + background: "#191A19", + foreground: "#F5F2E7", }, - }; - interpreter.setStdout(generic); - interpreter.setStderr(generic); - interpreter.setStdin({ - isatty: true, - stdin: () => sync.pyterminal_read(data), + ...options, }); - - io.stderr = (error) => { - sync.pyterminal_write(`${error.message || error}\n`); - }; + const fitAddon = new FitAddon(); + terminal.loadAddon(fitAddon); + terminal.loadAddon(readline); + terminal.open(target); + fitAddon.fit(); + terminal.focus(); + defineProperty(element, "terminal", { value: terminal }); + return terminal; }; - // add a hook on the main thread to setup all sync helpers - // also bootstrapping the XTerm target on main - hooks.main.onWorker.add(function worker(_, xworker) { - hooks.main.onWorker.delete(worker); - init({ - disableStdin: false, - cursorBlink: true, - cursorStyle: "block", - }); - xworker.sync.pyterminal_read = readline.read.bind(readline); - xworker.sync.pyterminal_write = readline.write.bind(readline); - // allow a worker to drop main thread hooks ASAP - xworker.sync.pyterminal_drop_hooks = () => { - hooks.worker.onReady.delete(workerReady); - }; - }); - - // setup remote thread JS/Python code for whenever the - // worker is ready to become a terminal - hooks.worker.onReady.add(workerReady); - } else { - // in the main case, just bootstrap XTerm without - // allowing any input as that's not possible / awkward - hooks.main.onReady.add(function main({ interpreter, io, run }) { - console.warn("py-terminal is read only on main thread"); - hooks.main.onReady.delete(main); - - // on main, it's easy to trash and clean the current terminal - globalThis.__py_terminal__ = init({ - disableStdin: true, - cursorBlink: false, - cursorStyle: "underline", - }); - run("from js import __py_terminal__ as __terminal__"); - delete globalThis.__py_terminal__; - - // This part is inevitably duplicated as external scope - // can't be reached by workers out of the box. - // The detail is that here we use readline here, not sync. - const decoder = new TextDecoder(); - let data = ""; - const generic = { - isatty: true, - write(buffer) { - data = decoder.decode(buffer); - readline.write(data); - return buffer.length; - }, - }; - interpreter.setStdout(generic); - interpreter.setStderr(generic); - interpreter.setStdin({ - isatty: true, - stdin: () => readline.read(data), + // branch logic for the worker + if (element.hasAttribute("worker")) { + // add a hook on the main thread to setup all sync helpers + // also bootstrapping the XTerm target on main *BUT* ... + hooks.main.onWorker.add(function worker(_, xworker) { + // ... as multiple workers will add multiple callbacks + // be sure no xworker is ever initialized twice! + if (bootstrapped.has(xworker)) return; + bootstrapped.add(xworker); + + // still cleanup this callback for future scripts/workers + hooks.main.onWorker.delete(worker); + + init({ + disableStdin: false, + cursorBlink: true, + cursorStyle: "block", + }); + + xworker.sync.is_pyterminal = () => true; + xworker.sync.pyterminal_read = readline.read.bind(readline); + xworker.sync.pyterminal_write = readline.write.bind(readline); }); - io.stderr = (error) => { - readline.write(`${error.message || error}\n`); - }; - }); + // setup remote thread JS/Python code for whenever the + // worker is ready to become a terminal + hooks.worker.onReady.add(workerReady); + } else { + // in the main case, just bootstrap XTerm without + // allowing any input as that's not possible / awkward + hooks.main.onReady.add(function main({ interpreter, io, run }) { + console.warn("py-terminal is read only on main thread"); + hooks.main.onReady.delete(main); + + // on main, it's easy to trash and clean the current terminal + globalThis.__py_terminal__ = init({ + disableStdin: true, + cursorBlink: false, + cursorStyle: "underline", + }); + run("from js import __py_terminal__ as __terminal__"); + delete globalThis.__py_terminal__; + + // This part is inevitably duplicated as external scope + // can't be reached by workers out of the box. + // The detail is that here we use readline here, not sync. + const decoder = new TextDecoder(); + let data = ""; + const generic = { + isatty: true, + write(buffer) { + data = decoder.decode(buffer); + readline.write(data); + return buffer.length; + }, + }; + interpreter.setStdout(generic); + interpreter.setStderr(generic); + interpreter.setStdin({ + isatty: true, + stdin: () => readline.read(data), + }); + + io.stderr = (error) => { + readline.write(`${error.message || error}\n`); + }; + }); + } } }; diff --git a/pyscript.core/src/sync.js b/pyscript.core/src/sync.js index 55519452873..3569c762de8 100644 --- a/pyscript.core/src/sync.js +++ b/pyscript.core/src/sync.js @@ -1,4 +1,7 @@ export default { + // allow pyterminal checks to bootstrap + is_pyterminal: () => false, + /** * 'Sleep' for the given number of seconds. Used to implement Python's time.sleep in Worker threads. * @param {number} seconds The number of seconds to sleep. diff --git a/pyscript.core/test/mpy.spec.js b/pyscript.core/test/mpy.spec.js index 7e89c0f76e9..b8889102e01 100644 --- a/pyscript.core/test/mpy.spec.js +++ b/pyscript.core/test/mpy.spec.js @@ -73,3 +73,8 @@ test('Pyodide + terminal on Worker', async ({ page }) => { await page.goto('http://localhost:8080/test/py-terminal-worker.html'); await page.waitForSelector('html.ok'); }); + +test('Pyodide + multiple terminals via Worker', async ({ page }) => { + await page.goto('http://localhost:8080/test/py-terminals.html'); + await page.waitForSelector('html.first.second'); +}); diff --git a/pyscript.core/test/py-terminal-worker.html b/pyscript.core/test/py-terminal-worker.html index 720e51e340f..1e4e138e9b3 100644 --- a/pyscript.core/test/py-terminal-worker.html +++ b/pyscript.core/test/py-terminal-worker.html @@ -9,6 +9,7 @@ - + + diff --git a/pyscript.core/test/py-terminals.html b/pyscript.core/test/py-terminals.html new file mode 100644 index 00000000000..ff72c5516a1 --- /dev/null +++ b/pyscript.core/test/py-terminals.html @@ -0,0 +1,27 @@ + + + + + + PyTerminal Main + + + + + + + + + diff --git a/pyscript.core/tests/integration/test_py_terminal.py b/pyscript.core/tests/integration/test_py_terminal.py index 8e5e3395860..45ee03c1d25 100644 --- a/pyscript.core/tests/integration/test_py_terminal.py +++ b/pyscript.core/tests/integration/test_py_terminal.py @@ -7,6 +7,7 @@ class TestPyTerminal(PyScriptTest): + @skip_worker("We do support multiple worker terminal now") def test_multiple_terminals(self): """ Multiple terminals are not currently supported @@ -19,9 +20,9 @@ def test_multiple_terminals(self): wait_for_pyscript=False, check_js_errors=False, ) - assert self.assert_banner_message("You can use at most 1 terminal") + assert self.assert_banner_message("You can use at most 1 main terminal") - with pytest.raises(PageErrors, match="You can use at most 1 terminal"): + with pytest.raises(PageErrors, match="You can use at most 1 main terminal"): self.check_js_errors() # TODO: interactive shell still unclear diff --git a/pyscript.core/types/sync.d.ts b/pyscript.core/types/sync.d.ts index 3dd526500ca..fb57cb15d7d 100644 --- a/pyscript.core/types/sync.d.ts +++ b/pyscript.core/types/sync.d.ts @@ -1,4 +1,5 @@ declare namespace _default { + function is_pyterminal(): boolean; /** * 'Sleep' for the given number of seconds. Used to implement Python's time.sleep in Worker threads. * @param {number} seconds The number of seconds to sleep. From 63f24530918459e2cbcb71ecc035482c8642f8c1 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Fri, 26 Jan 2024 15:04:02 +0100 Subject: [PATCH 003/179] Fix #1946 - Do not hold while bootstrapping (#1953) --- pyscript.core/package-lock.json | 4 +-- pyscript.core/package.json | 2 +- pyscript.core/src/plugins/py-editor.js | 10 ++++++-- pyscript.core/test/multiple-editors.html | 31 ++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 pyscript.core/test/multiple-editors.html diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 0fb24c5bbd6..5bf33a92756 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.3.20", + "version": "0.3.21", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.3.20", + "version": "0.3.21", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 07a92902d42..6f955f9471b 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.3.20", + "version": "0.3.21", "type": "module", "description": "PyScript", "module": "./index.js", diff --git a/pyscript.core/src/plugins/py-editor.js b/pyscript.core/src/plugins/py-editor.js index a5595d36bfb..ea2537a2d3c 100644 --- a/pyscript.core/src/plugins/py-editor.js +++ b/pyscript.core/src/plugins/py-editor.js @@ -200,6 +200,9 @@ const init = async (script, type, interpreter) => { // avoid too greedy MutationObserver operations at distance let timeout = 0; +// avoid delayed initialization +let queue = Promise.resolve(); + // reset interval value then check for new scripts const resetTimeout = () => { timeout = 0; @@ -213,11 +216,14 @@ const pyEditor = async () => { for (const [type, interpreter] of TYPES) { const selector = `script[type="${type}-editor"]`; for (const script of document.querySelectorAll(selector)) { - // avoid any further bootstrap + // avoid any further bootstrap by changing the type as active script.type += "-active"; - await init(script, type, interpreter); + // don't await in here or multiple calls might happen + // while the first script is being initialized + queue = queue.then(() => init(script, type, interpreter)); } } + return queue; }; new MutationObserver(pyEditor).observe(document, { diff --git a/pyscript.core/test/multiple-editors.html b/pyscript.core/test/multiple-editors.html new file mode 100644 index 00000000000..7ddf44a9ff0 --- /dev/null +++ b/pyscript.core/test/multiple-editors.html @@ -0,0 +1,31 @@ + + + + + + PyScript Test + + + + + + + + + + + + + From 2128572ce5d7f460f2900c6b423eccde5b84cc3e Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Fri, 26 Jan 2024 17:33:02 -0500 Subject: [PATCH 004/179] pyweb camera support (#1901) * add media module * add Device class to media * add camera test example * add snap, download and other convenience methods * load devices automagically * add draw method to canvas * add docstring for download * add docstrings to draw method * add docstrings to snap * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * load devices as soon as the page loads * solve conflict * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * remove display calls listing devices in camera example * fix typos and other small errors * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix typo in docstring * fix error message typo * replace setAttribute on JS properties with accessors * remove debug statement * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add docstrings * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add docstrings to camera example * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/src/stdlib/pyweb/media.py | 95 ++++++++++++++++++++++++ pyscript.core/src/stdlib/pyweb/pydom.py | 85 +++++++++++++++++++++ pyscript.core/test/camera.html | 24 ++++++ pyscript.core/test/camera.py | 32 ++++++++ pyscript.core/types/stdlib/pyscript.d.ts | 1 + 5 files changed, 237 insertions(+) create mode 100644 pyscript.core/src/stdlib/pyweb/media.py create mode 100644 pyscript.core/test/camera.html create mode 100644 pyscript.core/test/camera.py diff --git a/pyscript.core/src/stdlib/pyweb/media.py b/pyscript.core/src/stdlib/pyweb/media.py new file mode 100644 index 00000000000..9f0ffcda559 --- /dev/null +++ b/pyscript.core/src/stdlib/pyweb/media.py @@ -0,0 +1,95 @@ +from pyodide.ffi import to_js +from pyscript import window + + +class Device: + """Device represents a media input or output device, such as a microphone, + camera, or headset. + """ + + def __init__(self, device): + self._js = device + + @property + def id(self): + return self._js.deviceId + + @property + def group(self): + return self._js.groupId + + @property + def kind(self): + return self._js.kind + + @property + def label(self): + return self._js.label + + def __getitem__(self, key): + return getattr(self, key) + + @classmethod + async def load(cls, audio=False, video=True): + """Load the device stream.""" + options = window.Object.new() + options.audio = audio + if isinstance(video, bool): + options.video = video + else: + # TODO: Think this can be simplified but need to check it on the pyodide side + + # TODO: this is pyodide specific. shouldn't be! + options.video = window.Object.new() + for k in video: + setattr( + options.video, + k, + to_js(video[k], dict_converter=window.Object.fromEntries), + ) + + stream = await window.navigator.mediaDevices.getUserMedia(options) + return stream + + async def get_stream(self): + key = self.kind.replace("input", "").replace("output", "") + options = {key: {"deviceId": {"exact": self.id}}} + + return await self.load(**options) + + +async def list_devices() -> list[dict]: + """ + Return the list of the currently available media input and output devices, + such as microphones, cameras, headsets, and so forth. + + Output: + + list(dict) - list of dictionaries representing the available media devices. + Each dictionary has the following keys: + * deviceId: a string that is an identifier for the represented device + that is persisted across sessions. It is un-guessable by other + applications and unique to the origin of the calling application. + It is reset when the user clears cookies (for Private Browsing, a + different identifier is used that is not persisted across sessions). + + * groupId: a string that is a group identifier. Two devices have the same + group identifier if they belong to the same physical device — for + example a monitor with both a built-in camera and a microphone. + + * kind: an enumerated value that is either "videoinput", "audioinput" + or "audiooutput". + + * label: a string describing this device (for example "External USB + Webcam"). + + Note: the returned list will omit any devices that are blocked by the document + Permission Policy: microphone, camera, speaker-selection (for output devices), + and so on. Access to particular non-default devices is also gated by the + Permissions API, and the list will omit devices for which the user has not + granted explicit permission. + """ + # https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices + return [ + Device(obj) for obj in await window.navigator.mediaDevices.enumerateDevices() + ] diff --git a/pyscript.core/src/stdlib/pyweb/pydom.py b/pyscript.core/src/stdlib/pyweb/pydom.py index 340186fdc5e..2eadcc81a76 100644 --- a/pyscript.core/src/stdlib/pyweb/pydom.py +++ b/pyscript.core/src/stdlib/pyweb/pydom.py @@ -204,6 +204,91 @@ def classes(self): def show_me(self): self._js.scrollIntoView() + def snap( + self, + to: BaseElement | str = None, + width: int | None = None, + height: int | None = None, + ): + """ + Captures a snapshot of a video element. (Only available for video elements) + + Inputs: + + * to: element where to save the snapshot of the video frame to + * width: width of the image + * height: height of the image + + Output: + (Element) canvas element where the video frame snapshot was drawn into + """ + if self._js.tagName != "VIDEO": + raise AttributeError("Snap method is only available for video Elements") + + if to is None: + canvas = self.create("canvas") + if width is None: + width = self._js.width + if height is None: + height = self._js.height + canvas._js.width = width + canvas._js.height = height + + elif isistance(to, Element): + if to._js.tagName != "CANVAS": + raise TypeError("Element to snap to must a canvas.") + canvas = to + elif getattr(to, "tagName", "") == "CANVAS": + canvas = Element(to) + elif isinstance(to, str): + canvas = pydom[to][0] + if canvas._js.tagName != "CANVAS": + raise TypeError("Element to snap to must a be canvas.") + + canvas.draw(self, width, height) + + return canvas + + def download(self, filename: str = "snapped.png") -> None: + """Download the current element (only available for canvas elements) with the filename + provided in input. + + Inputs: + * filename (str): name of the file being downloaded + + Output: + None + """ + if self._js.tagName != "CANVAS": + raise AttributeError( + "The download method is only available for canvas Elements" + ) + + link = self.create("a") + link._js.download = filename + link._js.href = self._js.toDataURL() + link._js.click() + + def draw(self, what, width, height): + """Draw `what` on the current element (only available for canvas elements). + + Inputs: + + * what (canvas image source): An element to draw into the context. The specification permits any canvas + image source, specifically, an HTMLImageElement, an SVGImageElement, an HTMLVideoElement, + an HTMLCanvasElement, an ImageBitmap, an OffscreenCanvas, or a VideoFrame. + """ + if self._js.tagName != "CANVAS": + raise AttributeError( + "The draw method is only available for canvas Elements" + ) + + if isinstance(what, Element): + what = what._js + + # https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage + self._js.getContext("2d").drawImage(what, 0, 0, width, height) + class OptionsProxy: """This class represents the options of a select element. It diff --git a/pyscript.core/test/camera.html b/pyscript.core/test/camera.html new file mode 100644 index 00000000000..915d46b44b5 --- /dev/null +++ b/pyscript.core/test/camera.html @@ -0,0 +1,24 @@ + + + + + + PyScript Media Example + + + + + + + + + + + + + +
+ + + + diff --git a/pyscript.core/test/camera.py b/pyscript.core/test/camera.py new file mode 100644 index 00000000000..c352606e586 --- /dev/null +++ b/pyscript.core/test/camera.py @@ -0,0 +1,32 @@ +from pyodide.ffi import create_proxy +from pyscript import display, document, when, window +from pyweb import media, pydom + +devicesSelect = pydom["#devices"][0] +video = pydom["video"][0] +devices = {} + + +async def list_media_devices(event=None): + """List the available media devices.""" + global devices + for i, device in enumerate(await media.list_devices()): + devices[device.id] = device + label = f"{i} - ({device.kind}) {device.label} [{device.id}]" + devicesSelect.options.add(value=device.id, html=label) + + +@when("click", "#pick-device") +async def connect_to_device(e): + """Connect to the selected device.""" + device = devices[devicesSelect.value] + video._js.srcObject = await device.get_stream() + + +@when("click", "#snap") +async def camera_click(e): + """Take a picture and download it.""" + video.snap().download() + + +await list_media_devices() diff --git a/pyscript.core/types/stdlib/pyscript.d.ts b/pyscript.core/types/stdlib/pyscript.d.ts index fa33defe76c..9805e00882f 100644 --- a/pyscript.core/types/stdlib/pyscript.d.ts +++ b/pyscript.core/types/stdlib/pyscript.d.ts @@ -7,6 +7,7 @@ declare namespace _default { "util.py": string; }; let pyweb: { + "media.py": string; "pydom.py": string; }; } From 2b411fc635b7e7414abf313b1cdaa469f507c9c3 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Mon, 29 Jan 2024 12:00:37 +0100 Subject: [PATCH 005/179] Update Polyscript to its latest w/ experimental (#1955) --- pyscript.core/package-lock.json | 18 ++++++++++++------ pyscript.core/package.json | 4 ++-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 5bf33a92756..146ca21e514 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.3.21", + "version": "0.3.22", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.3.21", + "version": "0.3.22", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.6.15", + "polyscript": "^0.6.16", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -2403,21 +2403,27 @@ } }, "node_modules/polyscript": { - "version": "0.6.15", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.6.15.tgz", - "integrity": "sha512-ppkcEgNlH+/+S4+bxSy+oda/V9Qo/M7IA4ddhoCeVUObRMZBiOrvWkStZDI/xs/Mw3nbAZ4L772+TIz/RgfU2Q==", + "version": "0.6.16", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.6.16.tgz", + "integrity": "sha512-ri7tWBzsujlnltJ5jKjgpVes6eQWOkl9PdU0QS/EkaPAX406rGPE4/nRMQxI2iWoza6LrH5JpdUhgG6YTskEnA==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", "codedent": "^0.1.2", "coincident": "^1.1.0", + "gc-hook": "^0.3.0", "html-escaper": "^3.0.3", "proxy-target": "^3.0.1", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1" } }, + "node_modules/polyscript/node_modules/gc-hook": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/gc-hook/-/gc-hook-0.3.0.tgz", + "integrity": "sha512-Qkp0HM3z839Ns0LpXFJBXqClNW23wQo6JpUdJAjuf1/2jB+oUWSOMzeMv2yFq8Ur45z8IWw9hpRhkSjxSt5RWg==" + }, "node_modules/postcss": { "version": "8.4.33", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 6f955f9471b..150b451339e 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.3.21", + "version": "0.3.22", "type": "module", "description": "PyScript", "module": "./index.js", @@ -42,7 +42,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.6.15", + "polyscript": "^0.6.16", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" From 3ff0f84391e3fde85946e073aa5c10dc83f7df45 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Tue, 30 Jan 2024 12:31:44 +0100 Subject: [PATCH 006/179] Update polyscript + coincident to their latest (#1958) --- pyscript.core/package-lock.json | 35 ++++++++++++++------------------- pyscript.core/package.json | 4 ++-- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 146ca21e514..baf5fb738b6 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.3.22", + "version": "0.3.23", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.3.22", + "version": "0.3.23", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.6.16", + "polyscript": "^0.6.18", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -970,17 +970,17 @@ } }, "node_modules/coincident": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/coincident/-/coincident-1.1.0.tgz", - "integrity": "sha512-FXl7/KToJmtaWWEHOJljbco6NKuM9Hzo249p5gI+lvmxv1JRUCoS14SP195zeEW2WypBfTARGkmnE9MwJ1j0Yg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/coincident/-/coincident-1.1.1.tgz", + "integrity": "sha512-4i6bejrHuY6aOY8uhq56g/psUK2k99y5hImpavQz7yfPNCXuJkmtRYpvBOguC0mdYXPgQjvoz+Odw/WO6q4okg==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", - "gc-hook": "^0.2.5", + "gc-hook": "^0.3.0", "proxy-target": "^3.0.1" }, "optionalDependencies": { - "ws": "^8.14.2" + "ws": "^8.16.0" } }, "node_modules/color-convert": { @@ -1634,9 +1634,9 @@ } }, "node_modules/gc-hook": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/gc-hook/-/gc-hook-0.2.5.tgz", - "integrity": "sha512-808B9hJ1T7ak4HRYdXgQjDaHexlaUOBuNFuqOnYotxfKjOHTDxAy8r1Oe7LI+KBeb/H6XUBKzuYi626DjxhxIg==" + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/gc-hook/-/gc-hook-0.3.0.tgz", + "integrity": "sha512-Qkp0HM3z839Ns0LpXFJBXqClNW23wQo6JpUdJAjuf1/2jB+oUWSOMzeMv2yFq8Ur45z8IWw9hpRhkSjxSt5RWg==" }, "node_modules/generic-names": { "version": "4.0.0", @@ -2403,15 +2403,15 @@ } }, "node_modules/polyscript": { - "version": "0.6.16", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.6.16.tgz", - "integrity": "sha512-ri7tWBzsujlnltJ5jKjgpVes6eQWOkl9PdU0QS/EkaPAX406rGPE4/nRMQxI2iWoza6LrH5JpdUhgG6YTskEnA==", + "version": "0.6.18", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.6.18.tgz", + "integrity": "sha512-naU5tisWCt/a12kl1lIdtphaGUCEDf4mmlzuOcvjayqkmfXUlxLdc9A5VEEZLcleWr5Wtx34aU9IBBG8hfSI6Q==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", "codedent": "^0.1.2", - "coincident": "^1.1.0", + "coincident": "^1.1.1", "gc-hook": "^0.3.0", "html-escaper": "^3.0.3", "proxy-target": "^3.0.1", @@ -2419,11 +2419,6 @@ "to-json-callback": "^0.1.1" } }, - "node_modules/polyscript/node_modules/gc-hook": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/gc-hook/-/gc-hook-0.3.0.tgz", - "integrity": "sha512-Qkp0HM3z839Ns0LpXFJBXqClNW23wQo6JpUdJAjuf1/2jB+oUWSOMzeMv2yFq8Ur45z8IWw9hpRhkSjxSt5RWg==" - }, "node_modules/postcss": { "version": "8.4.33", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 150b451339e..87d5fdd9184 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.3.22", + "version": "0.3.23", "type": "module", "description": "PyScript", "module": "./index.js", @@ -42,7 +42,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.6.16", + "polyscript": "^0.6.18", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" From bcaab0eb9328519168e682dc6213e36be655c2f3 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Tue, 30 Jan 2024 14:30:16 -0500 Subject: [PATCH 007/179] PyDom compatibility with MicroPython (#1954) * fix pydom example * fix the pydom test example to use a python syntax that works with MicroPython by replacing datetime * add note about capturing errors importing when * patch event_handler to handle compat with micropython * turn pyweb into a package and remove hack to make pydom a sort of module with an ugly hack * add pydom example using micropython * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix select element test * change pydom test page to let pytest tests load it properly * add missing folders to test dev server so it can run examples in the manual tests folder * add pydom tests to the test suite as integration tests * lint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * improve fixes in event_handling * change when decorator to actually dynamically fail in micropython and support handlers with or without arguments * simplify when decorator code * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add type declaration back for the MP use case * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * removed code to access pydom get index as I can't think of any proper use case * remove old commented hack to replace pydom module with class * fix examples title * precommit checks * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/src/stdlib/pyscript/__init__.py | 2 + .../src/stdlib/pyscript/event_handling.py | 41 +++++++++++---- pyscript.core/src/stdlib/pyweb/__init__.py | 1 + pyscript.core/src/stdlib/pyweb/pydom.py | 52 ++++++++++++++----- pyscript.core/test/pydom.html | 2 +- pyscript.core/test/pydom.py | 22 +++++--- pyscript.core/test/pydom_mp.html | 19 +++++++ pyscript.core/test/pyscript_dom/index.html | 4 +- .../test/pyscript_dom/tests/test_dom.py | 2 +- pyscript.core/tests/integration/support.py | 9 ++++ .../tests/integration/test_integration.py | 30 +++++++++++ pyscript.core/types/stdlib/pyscript.d.ts | 1 + 12 files changed, 149 insertions(+), 36 deletions(-) create mode 100644 pyscript.core/src/stdlib/pyweb/__init__.py create mode 100644 pyscript.core/test/pydom_mp.html create mode 100644 pyscript.core/tests/integration/test_integration.py diff --git a/pyscript.core/src/stdlib/pyscript/__init__.py b/pyscript.core/src/stdlib/pyscript/__init__.py index 45d8e84fb2b..dcd42f62298 100644 --- a/pyscript.core/src/stdlib/pyscript/__init__.py +++ b/pyscript.core/src/stdlib/pyscript/__init__.py @@ -43,6 +43,8 @@ try: from pyscript.event_handling import when except: + # TODO: should we remove this? Or at the very least, we should capture + # the traceback otherwise it's very hard to debug from pyscript.util import NotSupported when = NotSupported( diff --git a/pyscript.core/src/stdlib/pyscript/event_handling.py b/pyscript.core/src/stdlib/pyscript/event_handling.py index 3fac89ea522..23f930ce9f6 100644 --- a/pyscript.core/src/stdlib/pyscript/event_handling.py +++ b/pyscript.core/src/stdlib/pyscript/event_handling.py @@ -1,6 +1,14 @@ import inspect -from pyodide.ffi.wrappers import add_event_listener +try: + from pyodide.ffi.wrappers import add_event_listener + +except ImportError: + + def add_event_listener(el, event_type, func): + el.addEventListener(event_type, func) + + from pyscript.magic_js import document @@ -27,19 +35,32 @@ def decorator(func): f"Invalid selector: {selector}. Selector must" " be a string, a pydom.Element or a pydom.ElementCollection." ) + try: + sig = inspect.signature(func) + # Function doesn't receive events + if not sig.parameters: - sig = inspect.signature(func) - # Function doesn't receive events - if not sig.parameters: + def wrapper(*args, **kwargs): + func() + else: + wrapper = func + + except AttributeError: + # TODO: this is currently an quick hack to get micropython working but we need + # to actually properly replace inspect.signature with something else def wrapper(*args, **kwargs): - func() + try: + return func(*args, **kwargs) + except TypeError as e: + if "takes 0 positional arguments" in str(e): + return func() + + raise + + for el in elements: + add_event_listener(el, event_type, wrapper) - for el in elements: - add_event_listener(el, event_type, wrapper) - else: - for el in elements: - add_event_listener(el, event_type, func) return func return decorator diff --git a/pyscript.core/src/stdlib/pyweb/__init__.py b/pyscript.core/src/stdlib/pyweb/__init__.py new file mode 100644 index 00000000000..0a5b12ffe4c --- /dev/null +++ b/pyscript.core/src/stdlib/pyweb/__init__.py @@ -0,0 +1 @@ +from .pydom import dom as pydom diff --git a/pyscript.core/src/stdlib/pyweb/pydom.py b/pyscript.core/src/stdlib/pyweb/pydom.py index 2eadcc81a76..a9110faa5ed 100644 --- a/pyscript.core/src/stdlib/pyweb/pydom.py +++ b/pyscript.core/src/stdlib/pyweb/pydom.py @@ -1,9 +1,34 @@ -import sys -import warnings -from functools import cached_property -from typing import Any +try: + from typing import Any +except ImportError: + Any = "Any" + +try: + import warnings +except ImportError: + # TODO: For now it probably means we are in MicroPython. We should figure + # out the "right" way to handle this. For now we just ignore the warning + # and logging to console + class warnings: + @staticmethod + def warn(*args, **kwargs): + print("WARNING: ", *args, **kwargs) + + +try: + from functools import cached_property +except ImportError: + # TODO: same comment about micropython as above + cached_property = property + +try: + from pyodide.ffi import JsProxy +except ImportError: + # TODO: same comment about micropython as above + def JsProxy(obj): + return obj + -from pyodide.ffi import JsProxy from pyscript import display, document, window alert = window.alert @@ -361,7 +386,7 @@ def __getitem__(self, key): return self.options[key] -class StyleProxy(dict): +class StyleProxy: # (dict): def __init__(self, element: Element) -> None: self._element = element @@ -480,7 +505,7 @@ def __repr__(self): class DomScope: - def __getattr__(self, __name: str) -> Any: + def __getattr__(self, __name: str): element = document[f"#{__name}"] if element: return element[0] @@ -494,7 +519,12 @@ class PyDom(BaseElement): ElementCollection = ElementCollection def __init__(self): - super().__init__(document) + # PyDom is a special case of BaseElement where we don't want to create a new JS element + # and it really doesn't have a need for styleproxy or parent to to call to __init__ + # (which actually fails in MP for some reason) + self._js = document + self._parent = None + self._proxies = {} self.ids = DomScope() self.body = Element(document.body) self.head = Element(document.head) @@ -503,10 +533,6 @@ def create(self, type_, classes=None, html=None): return super().create(type_, is_child=False, classes=classes, html=html) def __getitem__(self, key): - if isinstance(key, int): - indices = range(*key.indices(len(self.list))) - return [self.list[i] for i in indices] - elements = self._js.querySelectorAll(key) if not elements: return None @@ -514,5 +540,3 @@ def __getitem__(self, key): dom = PyDom() - -sys.modules[__name__] = dom diff --git a/pyscript.core/test/pydom.html b/pyscript.core/test/pydom.html index ff64738171a..cc959de4871 100644 --- a/pyscript.core/test/pydom.html +++ b/pyscript.core/test/pydom.html @@ -3,7 +3,7 @@ - PyScript Next Plugin + PyDom Example diff --git a/pyscript.core/test/pydom.py b/pyscript.core/test/pydom.py index e251b8b42f1..ab8d0377c5b 100644 --- a/pyscript.core/test/pydom.py +++ b/pyscript.core/test/pydom.py @@ -1,26 +1,32 @@ import random +import time from datetime import datetime as dt -from pyscript import display +from pyscript import display, when from pyweb import pydom -from pyweb.base import when @when("click", "#just-a-button") -def on_click(event): - print(f"Hello from Python! {dt.now()}") - display(f"Hello from Python! {dt.now()}", append=False, target="result") +def on_click(): + try: + timenow = dt.now() + except NotImplementedError: + # In this case we assume it's not implemented because we are using MycroPython + tnow = time.localtime() + tstr = "{:02d}/{:02d}/{:04d} {:02d}:{:02d}:{:02d}" + timenow = tstr.format(tnow[2], tnow[1], tnow[0], *tnow[2:]) + + display(f"Hello from PyScript, time is: {timenow}", append=False, target="result") @when("click", "#color-button") def on_color_click(event): - print("1") btn = pydom["#result"] - print("2") btn.style["background-color"] = f"#{random.randrange(0x1000000):06x}" -def reset_color(): +@when("click", "#color-reset-button") +def reset_color(*args, **kwargs): pydom["#result"].style["background-color"] = "white" diff --git a/pyscript.core/test/pydom_mp.html b/pyscript.core/test/pydom_mp.html new file mode 100644 index 00000000000..770e00b9c90 --- /dev/null +++ b/pyscript.core/test/pydom_mp.html @@ -0,0 +1,19 @@ + + + + + + PyDom Example (MicroPython) + + + + + + + + + + +
+ + diff --git a/pyscript.core/test/pyscript_dom/index.html b/pyscript.core/test/pyscript_dom/index.html index 63c88ee4ae7..60e044f54a9 100644 --- a/pyscript.core/test/pyscript_dom/index.html +++ b/pyscript.core/test/pyscript_dom/index.html @@ -1,6 +1,6 @@ - PyperCard PyTest Suite + PyDom Test Suite @@ -32,7 +32,7 @@ - +

pyscript.dom Tests

You can pass test parameters to this test suite by passing them as query params on the url. diff --git a/pyscript.core/test/pyscript_dom/tests/test_dom.py b/pyscript.core/test/pyscript_dom/tests/test_dom.py index 3172e1d9763..49c96a5a6ec 100644 --- a/pyscript.core/test/pyscript_dom/tests/test_dom.py +++ b/pyscript.core/test/pyscript_dom/tests/test_dom.py @@ -336,7 +336,7 @@ def test_select_element_add(self): assert select.options[0].html == "Option 1" # WHEN we add another option (blank this time) - select.options.add() + select.options.add("") # EXPECT the select element to have 2 options assert len(select.options) == 2 diff --git a/pyscript.core/tests/integration/support.py b/pyscript.core/tests/integration/support.py index 4cc40db72ff..b9aadf835e9 100644 --- a/pyscript.core/tests/integration/support.py +++ b/pyscript.core/tests/integration/support.py @@ -17,6 +17,7 @@ ROOT = py.path.local(__file__).dirpath("..", "..", "..") BUILD = ROOT.join("pyscript.core").join("dist") +TEST = ROOT.join("pyscript.core").join("test") def params_with_marks(params): @@ -206,6 +207,14 @@ def init(self, request, tmpdir, logger, page, execution_thread): self.tmpdir = tmpdir # create a symlink to BUILD inside tmpdir tmpdir.join("build").mksymlinkto(BUILD) + # create a symlink ALSO to dist folder so we can run the tests in + # the test folder + tmpdir.join("dist").mksymlinkto(BUILD) + # create a symlink to TEST inside tmpdir so we can run tests in that + # manual test folder + tmpdir.join("test").mksymlinkto(TEST) + + # create a symlink to the favicon, so that we can use it in the HTML self.tmpdir.chdir() self.tmpdir.join("favicon.ico").write("") self.logger = logger diff --git a/pyscript.core/tests/integration/test_integration.py b/pyscript.core/tests/integration/test_integration.py new file mode 100644 index 00000000000..4b9b0282679 --- /dev/null +++ b/pyscript.core/tests/integration/test_integration.py @@ -0,0 +1,30 @@ +from .support import PyScriptTest, with_execution_thread + + +@with_execution_thread(None) +class TestSmokeTests(PyScriptTest): + """ + Each example requires the same three tests: + + - Test that the initial markup loads properly (currently done by + testing the tag's content) + - Testing that pyscript is loading properly + - Testing that the page contains appropriate content after rendering + """ + + def test_pydom(self): + # Test the full pydom test suite by running it in the browser + self.goto("test/pyscript_dom/index.html?-v&-s") + assert self.page.title() == "PyDom Test Suite" + + # wait for the test suite to finish + self.wait_for_console( + "============================= test session starts ==============================" + ) + + self.assert_no_banners() + + results = self.page.inner_html("#tests-terminal") + assert results + assert "PASSED" in results + assert "FAILED" not in results diff --git a/pyscript.core/types/stdlib/pyscript.d.ts b/pyscript.core/types/stdlib/pyscript.d.ts index 9805e00882f..6bff2b5e014 100644 --- a/pyscript.core/types/stdlib/pyscript.d.ts +++ b/pyscript.core/types/stdlib/pyscript.d.ts @@ -7,6 +7,7 @@ declare namespace _default { "util.py": string; }; let pyweb: { + "__init__.py": string; "media.py": string; "pydom.py": string; }; From 181d276c8bc072e8bbc098214bf76034520ead3f Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi <andrea.giammarchi@gmail.com> Date: Fri, 2 Feb 2024 15:03:30 +0100 Subject: [PATCH 008/179] Allow Workers w/out SharedArrayBuffer (#1967) Allow Workers w/out SharedArrayBuffer --- pyscript.core/package-lock.json | 54 +++++++++---------- pyscript.core/package.json | 6 +-- pyscript.core/src/core.js | 49 +++++++++-------- pyscript.core/src/stdlib/pyscript/magic_js.py | 25 +++++++-- pyscript.core/test/no_sab/index.html | 23 ++++++++ pyscript.core/test/no_sab/worker.py | 3 ++ pyscript.core/test/test.html | 0 pyscript.core/types/core.d.ts | 22 ++++++-- 8 files changed, 122 insertions(+), 60 deletions(-) create mode 100644 pyscript.core/test/no_sab/index.html create mode 100644 pyscript.core/test/no_sab/worker.py create mode 100644 pyscript.core/test/test.html diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index baf5fb738b6..076229c8bcc 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.3.23", + "version": "0.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.3.23", + "version": "0.4.0", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.6.18", + "polyscript": "^0.7.0", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -22,7 +22,7 @@ "@codemirror/language": "^6.10.0", "@codemirror/state": "^6.4.0", "@codemirror/view": "^6.23.1", - "@playwright/test": "^1.41.1", + "@playwright/test": "^1.41.2", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", @@ -361,12 +361,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.41.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.1.tgz", - "integrity": "sha512-9g8EWTjiQ9yFBXc6HjCWe41msLpxEX0KhmfmPl9RPLJdfzL4F0lg2BdJ91O9azFdl11y1pmpwdjBiSxvqc+btw==", + "version": "1.41.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.2.tgz", + "integrity": "sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg==", "dev": true, "dependencies": { - "playwright": "1.41.1" + "playwright": "1.41.2" }, "bin": { "playwright": "cli.js" @@ -970,13 +970,13 @@ } }, "node_modules/coincident": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/coincident/-/coincident-1.1.1.tgz", - "integrity": "sha512-4i6bejrHuY6aOY8uhq56g/psUK2k99y5hImpavQz7yfPNCXuJkmtRYpvBOguC0mdYXPgQjvoz+Odw/WO6q4okg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/coincident/-/coincident-1.2.1.tgz", + "integrity": "sha512-OXlCJBtBC278tNueIEyc5I9dvh9qOOZh1YPUbSRFI+i0AK4ELT/Io67qUv3uPmemW6dPHNmTdr/WKmkmnuBU5g==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", - "gc-hook": "^0.3.0", + "gc-hook": "^0.3.1", "proxy-target": "^3.0.1" }, "optionalDependencies": { @@ -1634,9 +1634,9 @@ } }, "node_modules/gc-hook": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/gc-hook/-/gc-hook-0.3.0.tgz", - "integrity": "sha512-Qkp0HM3z839Ns0LpXFJBXqClNW23wQo6JpUdJAjuf1/2jB+oUWSOMzeMv2yFq8Ur45z8IWw9hpRhkSjxSt5RWg==" + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/gc-hook/-/gc-hook-0.3.1.tgz", + "integrity": "sha512-E5M+O/h2o7eZzGhzRZGex6hbB3k4NWqO0eA+OzLRLXxhdbYPajZnynPwAtphnh+cRHPwsj5Z80dqZlfI4eK55A==" }, "node_modules/generic-names": { "version": "4.0.0", @@ -2359,12 +2359,12 @@ "integrity": "sha512-yyVAOFKTAElc7KdLt2+UKGExNYwYb/Y/WE9i+1ezCQsJE8gbKSjewfpRqK2nQgZ4d4hhAAGgDCOcIZVilqE5UA==" }, "node_modules/playwright": { - "version": "1.41.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.1.tgz", - "integrity": "sha512-gdZAWG97oUnbBdRL3GuBvX3nDDmUOuqzV/D24dytqlKt+eI5KbwusluZRGljx1YoJKZ2NRPaeWiFTeGZO7SosQ==", + "version": "1.41.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.2.tgz", + "integrity": "sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==", "dev": true, "dependencies": { - "playwright-core": "1.41.1" + "playwright-core": "1.41.2" }, "bin": { "playwright": "cli.js" @@ -2377,9 +2377,9 @@ } }, "node_modules/playwright-core": { - "version": "1.41.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.1.tgz", - "integrity": "sha512-/KPO5DzXSMlxSX77wy+HihKGOunh3hqndhqeo/nMxfigiKzogn8kfL0ZBDu0L1RKgan5XHCPmn6zXd2NUJgjhg==", + "version": "1.41.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz", + "integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -2403,16 +2403,16 @@ } }, "node_modules/polyscript": { - "version": "0.6.18", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.6.18.tgz", - "integrity": "sha512-naU5tisWCt/a12kl1lIdtphaGUCEDf4mmlzuOcvjayqkmfXUlxLdc9A5VEEZLcleWr5Wtx34aU9IBBG8hfSI6Q==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.7.0.tgz", + "integrity": "sha512-cvxpvYY5JnHL59tE3Njje1sdDPcqHP7GITJnC8AsAOFAwZb+ucqyyS8gacyNEoyRArK0P3g50pZ4rcl/ojafow==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", "codedent": "^0.1.2", - "coincident": "^1.1.1", - "gc-hook": "^0.3.0", + "coincident": "^1.2.1", + "gc-hook": "^0.3.1", "html-escaper": "^3.0.3", "proxy-target": "^3.0.1", "sticky-module": "^0.1.1", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 87d5fdd9184..5c1b4f81e0f 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.3.23", + "version": "0.4.0", "type": "module", "description": "PyScript", "module": "./index.js", @@ -42,7 +42,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.6.18", + "polyscript": "^0.7.0", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -53,7 +53,7 @@ "@codemirror/language": "^6.10.0", "@codemirror/state": "^6.4.0", "@codemirror/view": "^6.23.1", - "@playwright/test": "^1.41.1", + "@playwright/test": "^1.41.2", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", diff --git a/pyscript.core/src/core.js b/pyscript.core/src/core.js index 05a111da625..44cc9096982 100644 --- a/pyscript.core/src/core.js +++ b/pyscript.core/src/core.js @@ -29,10 +29,36 @@ import { hooks, main, worker, codeFor, createFunction } from "./hooks.js"; // generic helper to disambiguate between custom element and script const isScript = ({ tagName }) => tagName === "SCRIPT"; +// Used to create either Pyodide or MicroPython workers +// with the PyScript module available within the code +const [PyWorker, MPWorker] = [...TYPES.entries()].map( + ([TYPE, interpreter]) => + /** + * A `Worker` facade able to bootstrap on the worker thread only a PyScript module. + * @param {string} file the python file to run ina worker. + * @param {{config?: string | object, async?: boolean}} [options] optional configuration for the worker. + * @returns {Promise<Worker & {sync: object}>} + */ + async function PyScriptWorker(file, options) { + await configs.get(TYPE).plugins; + const xworker = XWorker.call( + new Hook(null, hooked.get(TYPE)), + file, + { + ...options, + type: interpreter, + }, + ); + assign(xworker.sync, sync); + return xworker.ready; + }, +); + // avoid multiple initialization of the same library const [ { PyWorker: exportedPyWorker, + MPWorker: exportedMPWorker, hooks: exportedHooks, config: exportedConfig, whenDefined: exportedWhenDefined, @@ -40,6 +66,7 @@ const [ alreadyLive, ] = stickyModule("@pyscript/core", { PyWorker, + MPWorker, hooks, config: {}, whenDefined, @@ -48,6 +75,7 @@ const [ export { TYPES, exportedPyWorker as PyWorker, + exportedMPWorker as MPWorker, exportedHooks as hooks, exportedConfig as config, exportedWhenDefined as whenDefined, @@ -314,24 +342,3 @@ for (const [TYPE, interpreter] of TYPES) { // export the used config without allowing leaks through it exportedConfig[TYPE] = structuredClone(config); } - -/** - * A `Worker` facade able to bootstrap on the worker thread only a PyScript module. - * @param {string} file the python file to run ina worker. - * @param {{config?: string | object, async?: boolean}} [options] optional configuration for the worker. - * @returns {Worker & {sync: ProxyHandler<object>}} - */ -function PyWorker(file, options) { - const hooks = hooked.get("py"); - // this propagates pyscript worker hooks without needing a pyscript - // bootstrap + it passes arguments and it defaults to `pyodide` - // as the interpreter to use in the worker, as all hooks assume that - // and as `pyodide` is the only default interpreter that can deal with - // all the features we need to deliver pyscript out there. - const xworker = XWorker.call(new Hook(null, hooks), file, { - type: "pyodide", - ...options, - }); - assign(xworker.sync, sync); - return xworker; -} diff --git a/pyscript.core/src/stdlib/pyscript/magic_js.py b/pyscript.core/src/stdlib/pyscript/magic_js.py index 5a2b9b330cb..49fd9c96080 100644 --- a/pyscript.core/src/stdlib/pyscript/magic_js.py +++ b/pyscript.core/src/stdlib/pyscript/magic_js.py @@ -24,16 +24,33 @@ def __getattr__(self, field): sys.modules["pyscript.js_modules"] = js_modules if RUNNING_IN_WORKER: - import js import polyscript PyWorker = NotSupported( "pyscript.PyWorker", "pyscript.PyWorker works only when running in the main thread", ) - window = polyscript.xworker.window - document = window.document - js.document = document + + try: + globalThis.SharedArrayBuffer.new(4) + import js + + window = polyscript.xworker.window + document = window.document + js.document = document + except: + globalThis.console.debug("SharedArrayBuffer is not available") + # in this scenario none of the utilities would work + # as expected so we better export these as NotSupported + window = NotSupported( + "pyscript.window", + "pyscript.window in workers works only via SharedArrayBuffer", + ) + document = NotSupported( + "pyscript.document", + "pyscript.document in workers works only via SharedArrayBuffer", + ) + sync = polyscript.xworker.sync # in workers the display does not have a default ID diff --git a/pyscript.core/test/no_sab/index.html b/pyscript.core/test/no_sab/index.html new file mode 100644 index 00000000000..1277faac38c --- /dev/null +++ b/pyscript.core/test/no_sab/index.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" href="../../dist/core.css"> + <script type="module"> + import { PyWorker } from '../../dist/core.js'; + const { sync } = await PyWorker( + './worker.py', + { + config: { + sync_main_only: true + } + } + ); + + document.documentElement.classList.add( + await sync.get_class() + ); + </script> +</head> +</html> diff --git a/pyscript.core/test/no_sab/worker.py b/pyscript.core/test/no_sab/worker.py new file mode 100644 index 00000000000..ffdf6c02155 --- /dev/null +++ b/pyscript.core/test/no_sab/worker.py @@ -0,0 +1,3 @@ +from pyscript import sync + +sync.get_class = lambda: "ok" diff --git a/pyscript.core/test/test.html b/pyscript.core/test/test.html new file mode 100644 index 00000000000..e69de29bb2d diff --git a/pyscript.core/types/core.d.ts b/pyscript.core/types/core.d.ts index 371bfc43bbe..8f55f2511fb 100644 --- a/pyscript.core/types/core.d.ts +++ b/pyscript.core/types/core.d.ts @@ -3,14 +3,26 @@ import TYPES from "./types.js"; * A `Worker` facade able to bootstrap on the worker thread only a PyScript module. * @param {string} file the python file to run ina worker. * @param {{config?: string | object, async?: boolean}} [options] optional configuration for the worker. - * @returns {Worker & {sync: ProxyHandler<object>}} + * @returns {Promise<Worker & {sync: object}>} */ declare function exportedPyWorker(file: string, options?: { config?: string | object; async?: boolean; -}): Worker & { - sync: ProxyHandler<object>; -}; +}): Promise<Worker & { + sync: object; +}>; +/** + * A `Worker` facade able to bootstrap on the worker thread only a PyScript module. + * @param {string} file the python file to run ina worker. + * @param {{config?: string | object, async?: boolean}} [options] optional configuration for the worker. + * @returns {Promise<Worker & {sync: object}>} + */ +declare function exportedMPWorker(file: string, options?: { + config?: string | object; + async?: boolean; +}): Promise<Worker & { + sync: object; +}>; declare const exportedHooks: { main: { onWorker: Set<Function>; @@ -39,4 +51,4 @@ declare const exportedHooks: { declare const exportedConfig: {}; declare const exportedWhenDefined: (type: string) => Promise<any>; import sync from "./sync.js"; -export { TYPES, exportedPyWorker as PyWorker, exportedHooks as hooks, exportedConfig as config, exportedWhenDefined as whenDefined }; +export { TYPES, exportedPyWorker as PyWorker, exportedMPWorker as MPWorker, exportedHooks as hooks, exportedConfig as config, exportedWhenDefined as whenDefined }; From 53e945201dd573a1ff4d68d3e2ab7a295e4107a4 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi <andrea.giammarchi@gmail.com> Date: Fri, 2 Feb 2024 15:33:26 +0100 Subject: [PATCH 009/179] Update polyscript to fix a try/catch issue (#1968) --- pyscript.core/package-lock.json | 16 ++++++++-------- pyscript.core/package.json | 4 ++-- pyscript.core/types/core.d.ts | 6 +++++- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 076229c8bcc..65dc2fbc269 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.7.0", + "polyscript": "^0.7.1", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -19,7 +19,7 @@ "devDependencies": { "@codemirror/commands": "^6.3.3", "@codemirror/lang-python": "^6.1.3", - "@codemirror/language": "^6.10.0", + "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.0", "@codemirror/view": "^6.23.1", "@playwright/test": "^1.41.2", @@ -91,9 +91,9 @@ } }, "node_modules/@codemirror/language": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.0.tgz", - "integrity": "sha512-2vaNn9aPGCRFKWcHPFksctzJ8yS5p7YoaT+jHpc0UGKzNuAIx4qy6R5wiqbP+heEEdyaABA582mNqSHzSoYdmg==", + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.1.tgz", + "integrity": "sha512-5GrXzrhq6k+gL5fjkAwt90nYDmjlzTIJV8THnxNFtNKWotMIlzzN+CpqxqwXOECnUdOndmSeWntVrVcv5axWRQ==", "dev": true, "dependencies": { "@codemirror/state": "^6.0.0", @@ -2403,9 +2403,9 @@ } }, "node_modules/polyscript": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.7.0.tgz", - "integrity": "sha512-cvxpvYY5JnHL59tE3Njje1sdDPcqHP7GITJnC8AsAOFAwZb+ucqyyS8gacyNEoyRArK0P3g50pZ4rcl/ojafow==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.7.1.tgz", + "integrity": "sha512-wyexafAFyJM/lL5U1SXOcsUUlfN1uJizAqo+TxmmdjaIZATX836RZVr/ymazcIAkwUK5BChNQfUIggLXQodnxg==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 5c1b4f81e0f..ac44a47babd 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -42,7 +42,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.7.0", + "polyscript": "^0.7.1", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -50,7 +50,7 @@ "devDependencies": { "@codemirror/commands": "^6.3.3", "@codemirror/lang-python": "^6.1.3", - "@codemirror/language": "^6.10.0", + "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.0", "@codemirror/view": "^6.23.1", "@playwright/test": "^1.41.2", diff --git a/pyscript.core/types/core.d.ts b/pyscript.core/types/core.d.ts index 8f55f2511fb..c7b4f9f7d61 100644 --- a/pyscript.core/types/core.d.ts +++ b/pyscript.core/types/core.d.ts @@ -38,7 +38,11 @@ declare const exportedHooks: { }; worker: { onReady: Set<Function>; - onBeforeRun: Set<Function>; + onBeforeRun: Set<Function>; /** + * Given a generic DOM Element, tries to fetch the 'src' attribute, if present. + * It either throws an error if the 'src' can't be fetched or it returns a fallback + * content as source. + */ onBeforeRunAsync: Set<Function>; onAfterRun: Set<Function>; onAfterRunAsync: Set<Function>; From 81a26363a3b06e0644852ec87550e0cc503ed1d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Rosado?= <hello@fabiorosado.dev> Date: Tue, 6 Feb 2024 14:23:12 +0000 Subject: [PATCH 010/179] Update bug template to point users to pyscript.com issue tracker (#1971) * Update bug template to point users to pyscript.com issue tracker * add bold to make it more visible --- .github/ISSUE_TEMPLATE/bug-report.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 2c19cbee348..2e178927525 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -11,7 +11,9 @@ body: There will always be more issues than there is time to do them, and so we will need to selectively close issues that don't provide enough information, so we can focus our time on helping people like you who fill out the issue form completely. Thank you for your collaboration! - There are also already a lot of open issues, so please take 2 minutes and search through existing ones to see if what you are experiencing already exists + There are also already a lot of open issues, so please take 2 minutes and search through existing ones to see if what you are experiencing already exists. + + Finally, if you are opening **a bug report related to PyScript.com** please [use this repository instead](https://github.com/anaconda/pyscript-dot-com-issues/issues/new/choose). Thanks for helping PyScript be amazing. We are nothing without people like you helping build a better community 💐! - type: checkboxes From a87d2b3fea3b280186ad2a7d20ce900a00bd5c6b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 7 Feb 2024 11:13:05 +0100 Subject: [PATCH 011/179] [pre-commit.ci] pre-commit autoupdate (#1917) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 23.11.0 → 24.1.1](https://github.com/psf/black/compare/23.11.0...24.1.1) - [github.com/pycqa/isort: 5.12.0 → 5.13.2](https://github.com/pycqa/isort/compare/5.12.0...5.13.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Andrea Giammarchi <andrea.giammarchi@gmail.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5ae4bdb5fc6..7abd4181f7e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/psf/black - rev: 23.11.0 + rev: 24.1.1 hooks: - id: black exclude: pyscript\.core/src/stdlib/pyscript/__init__\.py @@ -46,7 +46,7 @@ repos: args: [--tab-width, "4"] - repo: https://github.com/pycqa/isort - rev: 5.12.0 + rev: 5.13.2 hooks: - id: isort name: isort (python) From d7084f7f55db1701de1e44173a911a73acf3bb09 Mon Sep 17 00:00:00 2001 From: Shubhal Gupta <107386458+shubhalgupta@users.noreply.github.com> Date: Wed, 7 Feb 2024 15:47:50 +0530 Subject: [PATCH 012/179] Fix: Restored the development docs #1783 (#1803) * Fix: Restored the development docs #1783 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Andrea Giammarchi <andrea.giammarchi@gmail.com> --- CONTRIBUTING.md | 100 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d9c498ceafd..d97fc485af0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -79,3 +79,103 @@ The Project abides by the Organization's [trademark policy](https://github.com/p Part of MVG-0.1-beta. Made with love by GitHub. Licensed under the [CC-BY 4.0 License](https://creativecommons.org/licenses/by-sa/4.0/). + +# Quick guide to pytest + +We make heavy usage of pytest. Here is a quick guide and collection of useful options: + +- To run all tests in the current directory and subdirectories: pytest + +- To run tests in a specific directory or file: pytest path/to/dir/test_foo.py + +- -s: disables output capturing + +- --pdb: in case of exception, enter a (Pdb) prompt so that you can inspect what went wrong. + +- -v: verbose mode + +- -x: stop the execution as soon as one test fails + +- -k foo: run only the tests whose full name contains foo + +- -k 'foo and bar' + +- -k 'foo and not bar' + +## Running integration tests under pytest + +make test is useful to run all the tests, but during the development is useful to have more control on how tests are run. The following guide assumes that you are in the directory pyscriptjs/tests/integration/. + +### To run all the integration tests, single or multi core + +$ pytest -xv +... + +test_00_support.py::TestSupport::test_basic[chromium] PASSED [ 0%] +test_00_support.py::TestSupport::test_console[chromium] PASSED [ 1%] +test_00_support.py::TestSupport::test_check_js_errors_simple[chromium] PASSED [ 2%] +test_00_support.py::TestSupport::test_check_js_errors_expected[chromium] PASSED [ 3%] +test_00_support.py::TestSupport::test_check_js_errors_expected_but_didnt_raise[chromium] PASSED [ 4%] +test_00_support.py::TestSupport::test_check_js_errors_multiple[chromium] PASSED [ 5%] +... + +-x means "stop at the first failure". -v means "verbose", so that you can see all the test names one by one. We try to keep tests in a reasonable order, from most basic to most complex. This way, if you introduced some bug in very basic things, you will notice immediately. + +If you have the pytest-xdist plugin installed, you can run all the integration tests on 4 cores in parallel: + +$ pytest -n 4 + +### To run a single test, headless + +$ pytest test_01_basic.py -k test_pyscript_hello -s +... +[ 0.00 page.goto ] pyscript_hello.html +[ 0.01 request ] 200 - fake_server - http://fake_server/pyscript_hello.html +... +[ 0.17 console.info ] [py-loader] Downloading pyodide-x.y.z... +[ 0.18 request ] 200 - CACHED - https://cdn.jsdelivr.net/pyodide/vx.y.z/full/pyodide.js +... +[ 3.59 console.info ] [pyscript/main] PyScript page fully initialized +[ 3.60 console.log ] hello pyscript + +-k selects tests by pattern matching as described above. -s instructs pytest to show the output to the terminal instead of capturing it. In the output you can see various useful things, including network requests and JS console messages. + +### To run a single test, headed + +$ pytest test_01_basic.py -k test_pyscript_hello -s --headed +... + +Same as above, but with --headed the browser is shown in a window, and you can interact with it. The browser uses a fake server, which means that HTTP requests are cached. + +Unfortunately, in this mode source maps does not seem to work, and you cannot debug the original typescript source code. This seems to be a bug in playwright, for which we have a workaround: + +$ pytest test_01_basic.py -k test_pyscript_hello -s --headed --no-fake-server +... + +As the name implies, -no-fake-server disables the fake server: HTTP requests are not cached, but source-level debugging works. + +Finally: + +$ pytest test_01_basic.py -k test_pyscript_hello -s --dev +... + +--dev implies --headed --no-fake-server. In addition, it also automatically open chrome dev tools. + +### To run only main thread or worker tests + +By default, we run each test twice: one with execution_thread = "main" and one with execution_thread = "worker". If you want to run only half of them, you can use -m: + +$ pytest -m main # run only the tests in the main thread +$ pytest -m worker # ron only the tests in the web worker + +## Fake server, HTTP cache + +By default, our test machinery uses a playwright router which intercepts and cache HTTP requests, so that for example you don't have to download pyodide again and again. This also enables the possibility of running tests in parallel on multiple cores. + +The cache is stored using the pytest-cache plugin, which means that it survives across sessions. + +If you want to temporarily disable the cache, the easiest thing is to use --no-fake-server, which bypasses it completely. + +If you want to clear the cache, you can use the special option --clear-http-cache: + +NOTE: this works only if you are inside tests/integration, or if you explicitly specify tests/integration from the command line. This is due to how pytest decides to search for and load the various conftest.py. From 30c6c830aed246c8acbe7f7ce7c53ea4c2c14626 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi <andrea.giammarchi@gmail.com> Date: Fri, 9 Feb 2024 15:52:29 +0100 Subject: [PATCH 013/179] Fix #1972 - Evaluate users' code a part (#1975) --- pyscript.core/package-lock.json | 47 ++++++++++++++--------------- pyscript.core/package.json | 10 +++--- pyscript.core/test/code-a-part.html | 19 ++++++++++++ 3 files changed, 47 insertions(+), 29 deletions(-) create mode 100644 pyscript.core/test/code-a-part.html diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 65dc2fbc269..e7979f8840f 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,34 +1,34 @@ { "name": "@pyscript/core", - "version": "0.4.0", + "version": "0.4.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.0", + "version": "0.4.3", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.7.1", + "polyscript": "^0.8.1", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" }, "devDependencies": { "@codemirror/commands": "^6.3.3", - "@codemirror/lang-python": "^6.1.3", + "@codemirror/lang-python": "^6.1.4", "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.23.1", + "@codemirror/view": "^6.24.0", "@playwright/test": "^1.41.2", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.9.0-beta.1", - "chokidar": "^3.5.3", + "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^8.56.0", "rollup": "^4.9.6", @@ -80,13 +80,15 @@ } }, "node_modules/@codemirror/lang-python": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.3.tgz", - "integrity": "sha512-S9w2Jl74hFlD5nqtUMIaXAq9t5WlM0acCkyuQWUUSvZclk1sV+UfnpFiZzuZSG+hfEaOmxKR5UxY/Uxswn7EhQ==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.4.tgz", + "integrity": "sha512-b6d1TDqrkCjFNvMO01SWldFiDoZ39yl3tDMC1Y5f8glA2eZpynPxJhwYVTlGFr0stizcJgrp6ojLEGH2myoZAw==", "dev": true, "dependencies": { "@codemirror/autocomplete": "^6.3.2", "@codemirror/language": "^6.8.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.1", "@lezer/python": "^1.1.4" } }, @@ -133,9 +135,9 @@ "dev": true }, "node_modules/@codemirror/view": { - "version": "6.23.1", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.23.1.tgz", - "integrity": "sha512-J2Xnn5lFYT1ZN/5ewEoMBCmLlL71lZ3mBdb7cUEuHhX2ESoSrNEucpsDXpX22EuTGm9LOgC9v4Z0wx+Ez8QmGA==", + "version": "6.24.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.24.0.tgz", + "integrity": "sha512-zK6m5pNkdhdJl8idPP1gA4N8JKTiSsOz8U/Iw+C1ChMwyLG7+MLiNXnH/wFuAk6KeGEe33/adOiAh5jMqee03w==", "dev": true, "dependencies": { "@codemirror/state": "^6.4.0", @@ -920,16 +922,10 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -942,6 +938,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -2403,9 +2402,9 @@ } }, "node_modules/polyscript": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.7.1.tgz", - "integrity": "sha512-wyexafAFyJM/lL5U1SXOcsUUlfN1uJizAqo+TxmmdjaIZATX836RZVr/ymazcIAkwUK5BChNQfUIggLXQodnxg==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.8.1.tgz", + "integrity": "sha512-ziLElKhO+NE233aNVb7Kcjbd1a3X7XMEjxLh8aUXFr9NZ9Al16zD6A0Q6XFX/m4GS2Jn69bWIeOGGeGMF6C+uA==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index ac44a47babd..6d7000afc61 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.0", + "version": "0.4.3", "type": "module", "description": "PyScript", "module": "./index.js", @@ -42,24 +42,24 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.7.1", + "polyscript": "^0.8.1", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" }, "devDependencies": { "@codemirror/commands": "^6.3.3", - "@codemirror/lang-python": "^6.1.3", + "@codemirror/lang-python": "^6.1.4", "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.23.1", + "@codemirror/view": "^6.24.0", "@playwright/test": "^1.41.2", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.9.0-beta.1", - "chokidar": "^3.5.3", + "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^8.56.0", "rollup": "^4.9.6", diff --git a/pyscript.core/test/code-a-part.html b/pyscript.core/test/code-a-part.html new file mode 100644 index 00000000000..2928f29df4b --- /dev/null +++ b/pyscript.core/test/code-a-part.html @@ -0,0 +1,19 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <link rel="stylesheet" href="../dist/core.css"> + <script type="module"> + import { hooks } from "../dist/core.js"; + hooks.main.codeBeforeRun.add('print(0)'); + hooks.main.codeAfterRun.add('print(2)'); + </script> + </head> + <body> + <script type="py"> + # raise an error instead to see it on line 1 + print(1) + </script> + </body> +</html> From f6d5cf06c8c09ffb502f0548a094c22c7411efc2 Mon Sep 17 00:00:00 2001 From: Fabio Pliger <fpliger@users.noreply.github.com> Date: Mon, 12 Feb 2024 14:50:36 -0500 Subject: [PATCH 014/179] Add text to pydom.Element (#1911) * add missing test for html attribute * add test for text attribute * fix text attribute test * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Andrea Giammarchi <andrea.giammarchi@gmail.com> --- pyscript.core/src/stdlib/pyweb/pydom.py | 8 +++++++ pyscript.core/test/pyscript_dom/index.html | 2 ++ .../test/pyscript_dom/tests/test_dom.py | 24 +++++++++++++++++++ pyscript.core/types/3rd-party/codemirror.d.ts | 2 +- .../types/3rd-party/codemirror_commands.d.ts | 2 +- .../3rd-party/codemirror_lang-python.d.ts | 2 +- .../types/3rd-party/codemirror_language.d.ts | 2 +- .../types/3rd-party/codemirror_state.d.ts | 2 +- .../types/3rd-party/codemirror_view.d.ts | 2 +- 9 files changed, 40 insertions(+), 6 deletions(-) diff --git a/pyscript.core/src/stdlib/pyweb/pydom.py b/pyscript.core/src/stdlib/pyweb/pydom.py index a9110faa5ed..6a2a4289f44 100644 --- a/pyscript.core/src/stdlib/pyweb/pydom.py +++ b/pyscript.core/src/stdlib/pyweb/pydom.py @@ -125,6 +125,14 @@ def html(self): def html(self, value): self._js.innerHTML = value + @property + def text(self): + return self._js.textContent + + @text.setter + def text(self, value): + self._js.textContent = value + @property def content(self): # TODO: This breaks with with standard template elements. Define how to best diff --git a/pyscript.core/test/pyscript_dom/index.html b/pyscript.core/test/pyscript_dom/index.html index 60e044f54a9..553be596634 100644 --- a/pyscript.core/test/pyscript_dom/index.html +++ b/pyscript.core/test/pyscript_dom/index.html @@ -98,6 +98,8 @@ <h2 id="multi-elem-h2" class="multi-elems">Content multi-elem-h2</h2> <p class="collection"></p> <div class="collection"></div> <h3 class="collection"></h3> + + <div id="element_attribute_tests"></div> </div> diff --git a/pyscript.core/test/pyscript_dom/tests/test_dom.py b/pyscript.core/test/pyscript_dom/tests/test_dom.py index 49c96a5a6ec..d3a23c805b2 100644 --- a/pyscript.core/test/pyscript_dom/tests/test_dom.py +++ b/pyscript.core/test/pyscript_dom/tests/test_dom.py @@ -163,6 +163,30 @@ def on_click(event): assert called + def test_html_attribute(self): + # GIVEN an existing element on the page with a known empty text content + div = pydom["#element_attribute_tests"][0] + + # WHEN we set the html attribute + div.html = "<b>New Content</b>" + + # EXPECT the element html and underlying JS Element innerHTML property + # to match what we expect and what + assert div.html == div._js.innerHTML == "<b>New Content</b>" + assert div.text == div._js.textContent == "New Content" + + def test_text_attribute(self): + # GIVEN an existing element on the page with a known empty text content + div = pydom["#element_attribute_tests"][0] + + # WHEN we set the html attribute + div.text = "<b>New Content</b>" + + # EXPECT the element html and underlying JS Element innerHTML property + # to match what we expect and what + assert div.html == div._js.innerHTML == "<b>New Content</b>" + assert div.text == div._js.textContent == "<b>New Content</b>" + class TestCollection: def test_iter_eq_children(self): diff --git a/pyscript.core/types/3rd-party/codemirror.d.ts b/pyscript.core/types/3rd-party/codemirror.d.ts index 2a1a953a9a0..cb0ff5c3b54 100644 --- a/pyscript.core/types/3rd-party/codemirror.d.ts +++ b/pyscript.core/types/3rd-party/codemirror.d.ts @@ -1 +1 @@ -export * from "codemirror"; +export {}; diff --git a/pyscript.core/types/3rd-party/codemirror_commands.d.ts b/pyscript.core/types/3rd-party/codemirror_commands.d.ts index 1862cebc7bb..cb0ff5c3b54 100644 --- a/pyscript.core/types/3rd-party/codemirror_commands.d.ts +++ b/pyscript.core/types/3rd-party/codemirror_commands.d.ts @@ -1 +1 @@ -export * from "@codemirror/commands"; +export {}; diff --git a/pyscript.core/types/3rd-party/codemirror_lang-python.d.ts b/pyscript.core/types/3rd-party/codemirror_lang-python.d.ts index 76b718d3b66..cb0ff5c3b54 100644 --- a/pyscript.core/types/3rd-party/codemirror_lang-python.d.ts +++ b/pyscript.core/types/3rd-party/codemirror_lang-python.d.ts @@ -1 +1 @@ -export * from "@codemirror/lang-python"; +export {}; diff --git a/pyscript.core/types/3rd-party/codemirror_language.d.ts b/pyscript.core/types/3rd-party/codemirror_language.d.ts index 632a9f72919..cb0ff5c3b54 100644 --- a/pyscript.core/types/3rd-party/codemirror_language.d.ts +++ b/pyscript.core/types/3rd-party/codemirror_language.d.ts @@ -1 +1 @@ -export * from "@codemirror/language"; +export {}; diff --git a/pyscript.core/types/3rd-party/codemirror_state.d.ts b/pyscript.core/types/3rd-party/codemirror_state.d.ts index 9dd5c97d8a1..cb0ff5c3b54 100644 --- a/pyscript.core/types/3rd-party/codemirror_state.d.ts +++ b/pyscript.core/types/3rd-party/codemirror_state.d.ts @@ -1 +1 @@ -export * from "@codemirror/state"; +export {}; diff --git a/pyscript.core/types/3rd-party/codemirror_view.d.ts b/pyscript.core/types/3rd-party/codemirror_view.d.ts index 3669d051e72..cb0ff5c3b54 100644 --- a/pyscript.core/types/3rd-party/codemirror_view.d.ts +++ b/pyscript.core/types/3rd-party/codemirror_view.d.ts @@ -1 +1 @@ -export * from "@codemirror/view"; +export {}; From 5bed5ede52aee780a810d40827ca0fc4069d8661 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi <andrea.giammarchi@gmail.com> Date: Wed, 14 Feb 2024 09:59:18 +0100 Subject: [PATCH 015/179] Fix #1974 - Use utf-8 encoding to bootstrap stdlib (#1981) --- pyscript.core/package-lock.json | 116 +++++++++--------- pyscript.core/package.json | 4 +- pyscript.core/src/stdlib.js | 2 +- pyscript.core/types/3rd-party/codemirror.d.ts | 2 +- .../types/3rd-party/codemirror_commands.d.ts | 2 +- .../3rd-party/codemirror_lang-python.d.ts | 2 +- .../types/3rd-party/codemirror_language.d.ts | 2 +- .../types/3rd-party/codemirror_state.d.ts | 2 +- .../types/3rd-party/codemirror_view.d.ts | 2 +- 9 files changed, 67 insertions(+), 67 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index e7979f8840f..eedb5939180 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.3", + "version": "0.4.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.3", + "version": "0.4.4", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", @@ -31,7 +31,7 @@ "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^8.56.0", - "rollup": "^4.9.6", + "rollup": "^4.10.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", @@ -472,9 +472,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.6.tgz", - "integrity": "sha512-MVNXSSYN6QXOulbHpLMKYi60ppyO13W9my1qogeiAqtjb2yR4LSmfU2+POvDkLzhjYLXz9Rf9+9a3zFHW1Lecg==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.10.0.tgz", + "integrity": "sha512-/MeDQmcD96nVoRumKUljsYOLqfv1YFJps+0pTrb2Z9Nl/w5qNUysMaWQsrd1mvAlNT4yza1iVyIu4Q4AgF6V3A==", "cpu": [ "arm" ], @@ -485,9 +485,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.6.tgz", - "integrity": "sha512-T14aNLpqJ5wzKNf5jEDpv5zgyIqcpn1MlwCrUXLrwoADr2RkWA0vOWP4XxbO9aiO3dvMCQICZdKeDrFl7UMClw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.10.0.tgz", + "integrity": "sha512-lvu0jK97mZDJdpZKDnZI93I0Om8lSDaiPx3OiCk0RXn3E8CMPJNS/wxjAvSJJzhhZpfjXsjLWL8LnS6qET4VNQ==", "cpu": [ "arm64" ], @@ -498,9 +498,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.6.tgz", - "integrity": "sha512-CqNNAyhRkTbo8VVZ5R85X73H3R5NX9ONnKbXuHisGWC0qRbTTxnF1U4V9NafzJbgGM0sHZpdO83pLPzq8uOZFw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.10.0.tgz", + "integrity": "sha512-uFpayx8I8tyOvDkD7X6n0PriDRWxcqEjqgtlxnUA/G9oS93ur9aZ8c8BEpzFmsed1TH5WZNG5IONB8IiW90TQg==", "cpu": [ "arm64" ], @@ -511,9 +511,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.6.tgz", - "integrity": "sha512-zRDtdJuRvA1dc9Mp6BWYqAsU5oeLixdfUvkTHuiYOHwqYuQ4YgSmi6+/lPvSsqc/I0Omw3DdICx4Tfacdzmhog==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.10.0.tgz", + "integrity": "sha512-nIdCX03qFKoR/MwQegQBK+qZoSpO3LESurVAC6s6jazLA1Mpmgzo3Nj3H1vydXp/JM29bkCiuF7tDuToj4+U9Q==", "cpu": [ "x64" ], @@ -524,9 +524,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.6.tgz", - "integrity": "sha512-oNk8YXDDnNyG4qlNb6is1ojTOGL/tRhbbKeE/YuccItzerEZT68Z9gHrY3ROh7axDc974+zYAPxK5SH0j/G+QQ==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.10.0.tgz", + "integrity": "sha512-Fz7a+y5sYhYZMQFRkOyCs4PLhICAnxRX/GnWYReaAoruUzuRtcf+Qnw+T0CoAWbHCuz2gBUwmWnUgQ67fb3FYw==", "cpu": [ "arm" ], @@ -537,9 +537,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.6.tgz", - "integrity": "sha512-Z3O60yxPtuCYobrtzjo0wlmvDdx2qZfeAWTyfOjEDqd08kthDKexLpV97KfAeUXPosENKd8uyJMRDfFMxcYkDQ==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.10.0.tgz", + "integrity": "sha512-yPtF9jIix88orwfTi0lJiqINnlWo6p93MtZEoaehZnmCzEmLL0eqjA3eGVeyQhMtxdV+Mlsgfwhh0+M/k1/V7Q==", "cpu": [ "arm64" ], @@ -550,9 +550,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.6.tgz", - "integrity": "sha512-gpiG0qQJNdYEVad+1iAsGAbgAnZ8j07FapmnIAQgODKcOTjLEWM9sRb+MbQyVsYCnA0Im6M6QIq6ax7liws6eQ==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.10.0.tgz", + "integrity": "sha512-9GW9yA30ib+vfFiwjX+N7PnjTnCMiUffhWj4vkG4ukYv1kJ4T9gHNg8zw+ChsOccM27G9yXrEtMScf1LaCuoWQ==", "cpu": [ "arm64" ], @@ -563,9 +563,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.6.tgz", - "integrity": "sha512-+uCOcvVmFUYvVDr27aiyun9WgZk0tXe7ThuzoUTAukZJOwS5MrGbmSlNOhx1j80GdpqbOty05XqSl5w4dQvcOA==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.10.0.tgz", + "integrity": "sha512-X1ES+V4bMq2ws5fF4zHornxebNxMXye0ZZjUrzOrf7UMx1d6wMQtfcchZ8SqUnQPPHdOyOLW6fTcUiFgHFadRA==", "cpu": [ "riscv64" ], @@ -576,9 +576,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.6.tgz", - "integrity": "sha512-HUNqM32dGzfBKuaDUBqFB7tP6VMN74eLZ33Q9Y1TBqRDn+qDonkAUyKWwF9BR9unV7QUzffLnz9GrnKvMqC/fw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.10.0.tgz", + "integrity": "sha512-w/5OpT2EnI/Xvypw4FIhV34jmNqU5PZjZue2l2Y3ty1Ootm3SqhI+AmfhlUYGBTd9JnpneZCDnt3uNOiOBkMyw==", "cpu": [ "x64" ], @@ -589,9 +589,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.6.tgz", - "integrity": "sha512-ch7M+9Tr5R4FK40FHQk8VnML0Szi2KRujUgHXd/HjuH9ifH72GUmw6lStZBo3c3GB82vHa0ZoUfjfcM7JiiMrQ==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.10.0.tgz", + "integrity": "sha512-q/meftEe3QlwQiGYxD9rWwB21DoKQ9Q8wA40of/of6yGHhZuGfZO0c3WYkN9dNlopHlNT3mf5BPsUSxoPuVQaw==", "cpu": [ "x64" ], @@ -602,9 +602,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.6.tgz", - "integrity": "sha512-VD6qnR99dhmTQ1mJhIzXsRcTBvTjbfbGGwKAHcu+52cVl15AC/kplkhxzW/uT0Xl62Y/meBKDZvoJSJN+vTeGA==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.10.0.tgz", + "integrity": "sha512-NrR6667wlUfP0BHaEIKgYM/2va+Oj+RjZSASbBMnszM9k+1AmliRjHc3lJIiOehtSSjqYiO7R6KLNrWOX+YNSQ==", "cpu": [ "arm64" ], @@ -615,9 +615,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.6.tgz", - "integrity": "sha512-J9AFDq/xiRI58eR2NIDfyVmTYGyIZmRcvcAoJ48oDld/NTR8wyiPUu2X/v1navJ+N/FGg68LEbX3Ejd6l8B7MQ==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.10.0.tgz", + "integrity": "sha512-FV0Tpt84LPYDduIDcXvEC7HKtyXxdvhdAOvOeWMWbQNulxViH2O07QXkT/FffX4FqEI02jEbCJbr+YcuKdyyMg==", "cpu": [ "ia32" ], @@ -628,9 +628,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.6.tgz", - "integrity": "sha512-jqzNLhNDvIZOrt69Ce4UjGRpXJBzhUBzawMwnaDAwyHriki3XollsewxWzOzz+4yOFDkuJHtTsZFwMxhYJWmLQ==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.10.0.tgz", + "integrity": "sha512-OZoJd+o5TaTSQeFFQ6WjFCiltiYVjIdsXxwu/XZ8qRpsvMQr4UsVrE5UyT9RIvsnuF47DqkJKhhVZ2Q9YW9IpQ==", "cpu": [ "x64" ], @@ -3123,9 +3123,9 @@ } }, "node_modules/rollup": { - "version": "4.9.6", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.6.tgz", - "integrity": "sha512-05lzkCS2uASX0CiLFybYfVkwNbKZG5NFQ6Go0VWyogFTXXbR039UVsegViTntkk4OglHBdF54ccApXRRuXRbsg==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.10.0.tgz", + "integrity": "sha512-t2v9G2AKxcQ8yrG+WGxctBes1AomT0M4ND7jTFBCVPXQ/WFTvNSefIrNSmLKhIKBrvN8SG+CZslimJcT3W2u2g==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -3138,19 +3138,19 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.9.6", - "@rollup/rollup-android-arm64": "4.9.6", - "@rollup/rollup-darwin-arm64": "4.9.6", - "@rollup/rollup-darwin-x64": "4.9.6", - "@rollup/rollup-linux-arm-gnueabihf": "4.9.6", - "@rollup/rollup-linux-arm64-gnu": "4.9.6", - "@rollup/rollup-linux-arm64-musl": "4.9.6", - "@rollup/rollup-linux-riscv64-gnu": "4.9.6", - "@rollup/rollup-linux-x64-gnu": "4.9.6", - "@rollup/rollup-linux-x64-musl": "4.9.6", - "@rollup/rollup-win32-arm64-msvc": "4.9.6", - "@rollup/rollup-win32-ia32-msvc": "4.9.6", - "@rollup/rollup-win32-x64-msvc": "4.9.6", + "@rollup/rollup-android-arm-eabi": "4.10.0", + "@rollup/rollup-android-arm64": "4.10.0", + "@rollup/rollup-darwin-arm64": "4.10.0", + "@rollup/rollup-darwin-x64": "4.10.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.10.0", + "@rollup/rollup-linux-arm64-gnu": "4.10.0", + "@rollup/rollup-linux-arm64-musl": "4.10.0", + "@rollup/rollup-linux-riscv64-gnu": "4.10.0", + "@rollup/rollup-linux-x64-gnu": "4.10.0", + "@rollup/rollup-linux-x64-musl": "4.10.0", + "@rollup/rollup-win32-arm64-msvc": "4.10.0", + "@rollup/rollup-win32-ia32-msvc": "4.10.0", + "@rollup/rollup-win32-x64-msvc": "4.10.0", "fsevents": "~2.3.2" } }, diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 6d7000afc61..6904e04635c 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.3", + "version": "0.4.4", "type": "module", "description": "PyScript", "module": "./index.js", @@ -62,7 +62,7 @@ "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^8.56.0", - "rollup": "^4.9.6", + "rollup": "^4.10.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", diff --git a/pyscript.core/src/stdlib.js b/pyscript.core/src/stdlib.js index 48187729eb8..ddc4efc2474 100644 --- a/pyscript.core/src/stdlib.js +++ b/pyscript.core/src/stdlib.js @@ -21,7 +21,7 @@ const write = (base, literal) => { python.push(`_path = _Path("${base}/${key}")`); if (typeof value === "string") { const code = JSON.stringify(value); - python.push(`_path.write_text(${code})`); + python.push(`_path.write_text(${code},encoding="utf-8")`); } else { // @see https://github.com/pyscript/pyscript/pull/1813#issuecomment-1781502909 python.push(`if not _os.path.exists("${base}/${key}"):`); diff --git a/pyscript.core/types/3rd-party/codemirror.d.ts b/pyscript.core/types/3rd-party/codemirror.d.ts index cb0ff5c3b54..2a1a953a9a0 100644 --- a/pyscript.core/types/3rd-party/codemirror.d.ts +++ b/pyscript.core/types/3rd-party/codemirror.d.ts @@ -1 +1 @@ -export {}; +export * from "codemirror"; diff --git a/pyscript.core/types/3rd-party/codemirror_commands.d.ts b/pyscript.core/types/3rd-party/codemirror_commands.d.ts index cb0ff5c3b54..1862cebc7bb 100644 --- a/pyscript.core/types/3rd-party/codemirror_commands.d.ts +++ b/pyscript.core/types/3rd-party/codemirror_commands.d.ts @@ -1 +1 @@ -export {}; +export * from "@codemirror/commands"; diff --git a/pyscript.core/types/3rd-party/codemirror_lang-python.d.ts b/pyscript.core/types/3rd-party/codemirror_lang-python.d.ts index cb0ff5c3b54..76b718d3b66 100644 --- a/pyscript.core/types/3rd-party/codemirror_lang-python.d.ts +++ b/pyscript.core/types/3rd-party/codemirror_lang-python.d.ts @@ -1 +1 @@ -export {}; +export * from "@codemirror/lang-python"; diff --git a/pyscript.core/types/3rd-party/codemirror_language.d.ts b/pyscript.core/types/3rd-party/codemirror_language.d.ts index cb0ff5c3b54..632a9f72919 100644 --- a/pyscript.core/types/3rd-party/codemirror_language.d.ts +++ b/pyscript.core/types/3rd-party/codemirror_language.d.ts @@ -1 +1 @@ -export {}; +export * from "@codemirror/language"; diff --git a/pyscript.core/types/3rd-party/codemirror_state.d.ts b/pyscript.core/types/3rd-party/codemirror_state.d.ts index cb0ff5c3b54..9dd5c97d8a1 100644 --- a/pyscript.core/types/3rd-party/codemirror_state.d.ts +++ b/pyscript.core/types/3rd-party/codemirror_state.d.ts @@ -1 +1 @@ -export {}; +export * from "@codemirror/state"; diff --git a/pyscript.core/types/3rd-party/codemirror_view.d.ts b/pyscript.core/types/3rd-party/codemirror_view.d.ts index cb0ff5c3b54..3669d051e72 100644 --- a/pyscript.core/types/3rd-party/codemirror_view.d.ts +++ b/pyscript.core/types/3rd-party/codemirror_view.d.ts @@ -1 +1 @@ -export {}; +export * from "@codemirror/view"; From 84f197b657a6fae5573b1b8b11b2dad1a05f5531 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi <andrea.giammarchi@gmail.com> Date: Thu, 15 Feb 2024 17:49:09 +0100 Subject: [PATCH 016/179] Updated polyscript to its latest (#1982) --- pyscript.core/package-lock.json | 244 ++++++++++++++++---------------- pyscript.core/package.json | 6 +- pyscript.core/src/fetch.js | 7 +- pyscript.core/types/fetch.d.ts | 3 +- 4 files changed, 134 insertions(+), 126 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index eedb5939180..fd9193ab9a4 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.4.4", + "version": "0.4.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.4", + "version": "0.4.5", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.8.1", + "polyscript": "^0.9.0", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -31,7 +31,7 @@ "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^8.56.0", - "rollup": "^4.10.0", + "rollup": "^4.11.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", @@ -107,9 +107,9 @@ } }, "node_modules/@codemirror/lint": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.4.2.tgz", - "integrity": "sha512-wzRkluWb1ptPKdzlsrbwwjYCPLgzU6N88YBAmlZi8WFyuiEduSd05MnJYNogzyc8rPK7pj6m95ptUApc8sHKVA==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.5.0.tgz", + "integrity": "sha512-+5YyicIaaAZKU8K43IQi8TBy6mF6giGeWAH7N96Z5LC30Wm5JMjqxOYIE9mxwMG1NbhT2mA3l9hA4uuKUM3E5g==", "dev": true, "dependencies": { "@codemirror/state": "^6.0.0", @@ -118,9 +118,9 @@ } }, "node_modules/@codemirror/search": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.5.tgz", - "integrity": "sha512-PIEN3Ke1buPod2EHbJsoQwlbpkz30qGZKcnmH1eihq9+bPQx8gelauUwLYaY4vBOuBAuEhmpDLii4rj/uO0yMA==", + "version": "6.5.6", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz", + "integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==", "dev": true, "dependencies": { "@codemirror/state": "^6.0.0", @@ -249,9 +249,9 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" @@ -283,9 +283,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz", - "integrity": "sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==", + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -308,9 +308,9 @@ } }, "node_modules/@lezer/lr": { - "version": "1.3.14", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.14.tgz", - "integrity": "sha512-z5mY4LStlA3yL7aHT/rqgG614cfcvklS+8oFRFBYrs4YaWLJyKKM4+nN6KopToX0o9Hj6zmH6M5kinOYuy06ug==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.0.tgz", + "integrity": "sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==", "dev": true, "dependencies": { "@lezer/common": "^1.0.0" @@ -472,9 +472,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.10.0.tgz", - "integrity": "sha512-/MeDQmcD96nVoRumKUljsYOLqfv1YFJps+0pTrb2Z9Nl/w5qNUysMaWQsrd1mvAlNT4yza1iVyIu4Q4AgF6V3A==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.11.0.tgz", + "integrity": "sha512-BV+u2QSfK3i1o6FucqJh5IK9cjAU6icjFFhvknzFgu472jzl0bBojfDAkJLBEsHFMo+YZg6rthBvBBt8z12IBQ==", "cpu": [ "arm" ], @@ -485,9 +485,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.10.0.tgz", - "integrity": "sha512-lvu0jK97mZDJdpZKDnZI93I0Om8lSDaiPx3OiCk0RXn3E8CMPJNS/wxjAvSJJzhhZpfjXsjLWL8LnS6qET4VNQ==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.11.0.tgz", + "integrity": "sha512-0ij3iw7sT5jbcdXofWO2NqDNjSVVsf6itcAkV2I6Xsq4+6wjW1A8rViVB67TfBEan7PV2kbLzT8rhOVWLI2YXw==", "cpu": [ "arm64" ], @@ -498,9 +498,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.10.0.tgz", - "integrity": "sha512-uFpayx8I8tyOvDkD7X6n0PriDRWxcqEjqgtlxnUA/G9oS93ur9aZ8c8BEpzFmsed1TH5WZNG5IONB8IiW90TQg==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.11.0.tgz", + "integrity": "sha512-yPLs6RbbBMupArf6qv1UDk6dzZvlH66z6NLYEwqTU0VHtss1wkI4UYeeMS7TVj5QRVvaNAWYKP0TD/MOeZ76Zg==", "cpu": [ "arm64" ], @@ -511,9 +511,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.10.0.tgz", - "integrity": "sha512-nIdCX03qFKoR/MwQegQBK+qZoSpO3LESurVAC6s6jazLA1Mpmgzo3Nj3H1vydXp/JM29bkCiuF7tDuToj4+U9Q==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.11.0.tgz", + "integrity": "sha512-OvqIgwaGAwnASzXaZEeoJY3RltOFg+WUbdkdfoluh2iqatd090UeOG3A/h0wNZmE93dDew9tAtXgm3/+U/B6bw==", "cpu": [ "x64" ], @@ -524,9 +524,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.10.0.tgz", - "integrity": "sha512-Fz7a+y5sYhYZMQFRkOyCs4PLhICAnxRX/GnWYReaAoruUzuRtcf+Qnw+T0CoAWbHCuz2gBUwmWnUgQ67fb3FYw==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.11.0.tgz", + "integrity": "sha512-X17s4hZK3QbRmdAuLd2EE+qwwxL8JxyVupEqAkxKPa/IgX49ZO+vf0ka69gIKsaYeo6c1CuwY3k8trfDtZ9dFg==", "cpu": [ "arm" ], @@ -537,9 +537,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.10.0.tgz", - "integrity": "sha512-yPtF9jIix88orwfTi0lJiqINnlWo6p93MtZEoaehZnmCzEmLL0eqjA3eGVeyQhMtxdV+Mlsgfwhh0+M/k1/V7Q==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.11.0.tgz", + "integrity": "sha512-673Lu9EJwxVB9NfYeA4AdNu0FOHz7g9t6N1DmT7bZPn1u6bTF+oZjj+fuxUcrfxWXE0r2jxl5QYMa9cUOj9NFg==", "cpu": [ "arm64" ], @@ -550,9 +550,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.10.0.tgz", - "integrity": "sha512-9GW9yA30ib+vfFiwjX+N7PnjTnCMiUffhWj4vkG4ukYv1kJ4T9gHNg8zw+ChsOccM27G9yXrEtMScf1LaCuoWQ==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.11.0.tgz", + "integrity": "sha512-yFW2msTAQNpPJaMmh2NpRalr1KXI7ZUjlN6dY/FhWlOclMrZezm5GIhy3cP4Ts2rIAC+IPLAjNibjp1BsxCVGg==", "cpu": [ "arm64" ], @@ -563,9 +563,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.10.0.tgz", - "integrity": "sha512-X1ES+V4bMq2ws5fF4zHornxebNxMXye0ZZjUrzOrf7UMx1d6wMQtfcchZ8SqUnQPPHdOyOLW6fTcUiFgHFadRA==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.11.0.tgz", + "integrity": "sha512-kKT9XIuhbvYgiA3cPAGntvrBgzhWkGpBMzuk1V12Xuoqg7CI41chye4HU0vLJnGf9MiZzfNh4I7StPeOzOWJfA==", "cpu": [ "riscv64" ], @@ -576,9 +576,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.10.0.tgz", - "integrity": "sha512-w/5OpT2EnI/Xvypw4FIhV34jmNqU5PZjZue2l2Y3ty1Ootm3SqhI+AmfhlUYGBTd9JnpneZCDnt3uNOiOBkMyw==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.11.0.tgz", + "integrity": "sha512-6q4ESWlyTO+erp1PSCmASac+ixaDv11dBk1fqyIuvIUc/CmRAX2Zk+2qK1FGo5q7kyDcjHCFVwgGFCGIZGVwCA==", "cpu": [ "x64" ], @@ -589,9 +589,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.10.0.tgz", - "integrity": "sha512-q/meftEe3QlwQiGYxD9rWwB21DoKQ9Q8wA40of/of6yGHhZuGfZO0c3WYkN9dNlopHlNT3mf5BPsUSxoPuVQaw==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.11.0.tgz", + "integrity": "sha512-vIAQUmXeMLmaDN78HSE4Kh6xqof2e3TJUKr+LPqXWU4NYNON0MDN9h2+t4KHrPAQNmU3w1GxBQ/n01PaWFwa5w==", "cpu": [ "x64" ], @@ -602,9 +602,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.10.0.tgz", - "integrity": "sha512-NrR6667wlUfP0BHaEIKgYM/2va+Oj+RjZSASbBMnszM9k+1AmliRjHc3lJIiOehtSSjqYiO7R6KLNrWOX+YNSQ==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.11.0.tgz", + "integrity": "sha512-LVXo9dDTGPr0nezMdqa1hK4JeoMZ02nstUxGYY/sMIDtTYlli1ZxTXBYAz3vzuuvKO4X6NBETciIh7N9+abT1g==", "cpu": [ "arm64" ], @@ -615,9 +615,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.10.0.tgz", - "integrity": "sha512-FV0Tpt84LPYDduIDcXvEC7HKtyXxdvhdAOvOeWMWbQNulxViH2O07QXkT/FffX4FqEI02jEbCJbr+YcuKdyyMg==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.11.0.tgz", + "integrity": "sha512-xZVt6K70Gr3I7nUhug2dN6VRR1ibot3rXqXS3wo+8JP64t7djc3lBFyqO4GiVrhNaAIhUCJtwQ/20dr0h0thmQ==", "cpu": [ "ia32" ], @@ -628,9 +628,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.10.0.tgz", - "integrity": "sha512-OZoJd+o5TaTSQeFFQ6WjFCiltiYVjIdsXxwu/XZ8qRpsvMQr4UsVrE5UyT9RIvsnuF47DqkJKhhVZ2Q9YW9IpQ==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.11.0.tgz", + "integrity": "sha512-f3I7h9oTg79UitEco9/2bzwdciYkWr8pITs3meSDSlr1TdvQ7IxkQaaYN2YqZXX5uZhiYL+VuYDmHwNzhx+HOg==", "cpu": [ "x64" ], @@ -671,6 +671,11 @@ "resolved": "https://registry.npmjs.org/@ungap/with-resolvers/-/with-resolvers-0.1.0.tgz", "integrity": "sha512-g7f0IkJdPW2xhY7H4iE72DAsIyfuwEFc6JWc2tYFwKDMWWAF699vGjrM348cwQuOXgHpe1gWFe+Eiyjx/ewvvw==" }, + "node_modules/@webreflection/fetch": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@webreflection/fetch/-/fetch-0.1.4.tgz", + "integrity": "sha512-oKjhwcg0Phu4e9UcAEnpwHFhnywZfcPQfP6erP4T4EGSquAX8ub8+b7lYaQ80yLG3YAV51a0Bu5hsypti6oK8w==" + }, "node_modules/@webreflection/toml-j0.4": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@webreflection/toml-j0.4/-/toml-j0.4-1.1.3.tgz", @@ -815,9 +820,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ { @@ -834,8 +839,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, @@ -886,9 +891,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001578", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001578.tgz", - "integrity": "sha512-J/jkFgsQ3NEl4w2lCoM9ZPxrD+FoBNJ7uJUpGVjIg/j0OwJosWM36EPDv+Yyi0V4twBk9pPmlFS+PLykgEvUmg==", + "version": "1.0.30001587", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz", + "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==", "dev": true, "funding": [ { @@ -969,9 +974,9 @@ } }, "node_modules/coincident": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/coincident/-/coincident-1.2.1.tgz", - "integrity": "sha512-OXlCJBtBC278tNueIEyc5I9dvh9qOOZh1YPUbSRFI+i0AK4ELT/Io67qUv3uPmemW6dPHNmTdr/WKmkmnuBU5g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/coincident/-/coincident-1.2.2.tgz", + "integrity": "sha512-6gL6Rk6NFsRDb8IniRrx43srnoybZzbIfC6jAzPipNAOOZkOZcf+2CYofNq1gypp0zalauGw0dIyqrkTrU1j8A==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", @@ -1309,9 +1314,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.635", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.635.tgz", - "integrity": "sha512-iu/2D0zolKU3iDGXXxdOzNf72Jnokn+K1IN6Kk4iV6l1Tr2g/qy+mvmtfAiBwZe5S3aB5r92vp+zSZ69scYRrg==", + "version": "1.4.670", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.670.tgz", + "integrity": "sha512-hcijYOWjOtjKrKPtNA6tuLlA/bTLO3heFG8pQA6mLpq7dRydSWicXova5lyxDzp1iVJaYhK7J2OQlGE52KYn7A==", "dev": true }, "node_modules/emoji-regex": { @@ -1330,9 +1335,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" @@ -1535,9 +1540,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", - "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -1729,9 +1734,9 @@ } }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", "dev": true, "dependencies": { "function-bind": "^1.1.2" @@ -1764,9 +1769,9 @@ } }, "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" @@ -2064,9 +2069,9 @@ "dev": true }, "node_modules/magic-string": { - "version": "0.30.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", - "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "version": "0.30.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz", + "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==", "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" @@ -2402,15 +2407,16 @@ } }, "node_modules/polyscript": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.8.1.tgz", - "integrity": "sha512-ziLElKhO+NE233aNVb7Kcjbd1a3X7XMEjxLh8aUXFr9NZ9Al16zD6A0Q6XFX/m4GS2Jn69bWIeOGGeGMF6C+uA==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.9.0.tgz", + "integrity": "sha512-oyLH0jjuwZTln9v+43IJ04QR9AFTUL+n8EfEfkdbavbcMcUd9b25Evai+ZEESFnm/YU1P5ZhCglHRLTJMY4z8w==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", + "@webreflection/fetch": "^0.1.4", "basic-devtools": "^0.1.6", "codedent": "^0.1.2", - "coincident": "^1.2.1", + "coincident": "^1.2.2", "gc-hook": "^0.3.1", "html-escaper": "^3.0.3", "proxy-target": "^3.0.1", @@ -2419,9 +2425,9 @@ } }, "node_modules/postcss": { - "version": "8.4.33", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", - "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", "dev": true, "funding": [ { @@ -2701,9 +2707,9 @@ } }, "node_modules/postcss-modules-local-by-default": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", - "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.4.tgz", + "integrity": "sha512-L4QzMnOdVwRm1Qb8m4x8jsZzKAaPAgrUF1r/hjDR2Xj7R+8Zsf97jAlSQzWtKx5YNiNGN8QxmPFIc/sh+RQl+Q==", "dev": true, "dependencies": { "icss-utils": "^5.0.0", @@ -2718,9 +2724,9 @@ } }, "node_modules/postcss-modules-scope": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.1.0.tgz", - "integrity": "sha512-SaIbK8XW+MZbd0xHPf7kdfA/3eOt7vxJ72IRecn3EzuZVLr1r0orzf0MX/pN8m+NMDoo6X/SQd8oeKqGZd8PXg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.1.1.tgz", + "integrity": "sha512-uZgqzdTleelWjzJY+Fhti6F3C9iF1JR/dODLs/JDefozYcKTBCdD8BIl6nNPbTbcLnGrk56hzwZC2DaGNvYjzA==", "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.4" @@ -3123,9 +3129,9 @@ } }, "node_modules/rollup": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.10.0.tgz", - "integrity": "sha512-t2v9G2AKxcQ8yrG+WGxctBes1AomT0M4ND7jTFBCVPXQ/WFTvNSefIrNSmLKhIKBrvN8SG+CZslimJcT3W2u2g==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.11.0.tgz", + "integrity": "sha512-2xIbaXDXjf3u2tajvA5xROpib7eegJ9Y/uPlSFhXLNpK9ampCczXAhLEb5yLzJyG3LAdI1NWtNjDXiLyniNdjQ==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -3138,19 +3144,19 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.10.0", - "@rollup/rollup-android-arm64": "4.10.0", - "@rollup/rollup-darwin-arm64": "4.10.0", - "@rollup/rollup-darwin-x64": "4.10.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.10.0", - "@rollup/rollup-linux-arm64-gnu": "4.10.0", - "@rollup/rollup-linux-arm64-musl": "4.10.0", - "@rollup/rollup-linux-riscv64-gnu": "4.10.0", - "@rollup/rollup-linux-x64-gnu": "4.10.0", - "@rollup/rollup-linux-x64-musl": "4.10.0", - "@rollup/rollup-win32-arm64-msvc": "4.10.0", - "@rollup/rollup-win32-ia32-msvc": "4.10.0", - "@rollup/rollup-win32-x64-msvc": "4.10.0", + "@rollup/rollup-android-arm-eabi": "4.11.0", + "@rollup/rollup-android-arm64": "4.11.0", + "@rollup/rollup-darwin-arm64": "4.11.0", + "@rollup/rollup-darwin-x64": "4.11.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.11.0", + "@rollup/rollup-linux-arm64-gnu": "4.11.0", + "@rollup/rollup-linux-arm64-musl": "4.11.0", + "@rollup/rollup-linux-riscv64-gnu": "4.11.0", + "@rollup/rollup-linux-x64-gnu": "4.11.0", + "@rollup/rollup-linux-x64-musl": "4.11.0", + "@rollup/rollup-win32-arm64-msvc": "4.11.0", + "@rollup/rollup-win32-ia32-msvc": "4.11.0", + "@rollup/rollup-win32-x64-msvc": "4.11.0", "fsevents": "~2.3.2" } }, @@ -3464,9 +3470,9 @@ } }, "node_modules/terser": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.26.0.tgz", - "integrity": "sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==", + "version": "5.27.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.1.tgz", + "integrity": "sha512-29wAr6UU/oQpnTw5HoadwjUZnFQXGdOfj0LjZ4sVxzqwHh/QVkvr7m8y9WoR4iN3FRitVduTc6KdjcW38Npsug==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 6904e04635c..506f720d4ad 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.4", + "version": "0.4.5", "type": "module", "description": "PyScript", "module": "./index.js", @@ -42,7 +42,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.8.1", + "polyscript": "^0.9.0", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -62,7 +62,7 @@ "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^8.56.0", - "rollup": "^4.10.0", + "rollup": "^4.11.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", diff --git a/pyscript.core/src/fetch.js b/pyscript.core/src/fetch.js index 4b8e60ba8ea..00879cae030 100644 --- a/pyscript.core/src/fetch.js +++ b/pyscript.core/src/fetch.js @@ -1,7 +1,10 @@ import { FetchError, ErrorCode } from "./exceptions.js"; -import { getText } from "polyscript/exports"; -export { getText }; +/** + * @param {Response} response + * @returns + */ +export const getText = (response) => response.text(); /** * This is a fetch wrapper that handles any non 200 responses and throws a diff --git a/pyscript.core/types/fetch.d.ts b/pyscript.core/types/fetch.d.ts index 83b6bed2bd1..fc3849ddeee 100644 --- a/pyscript.core/types/fetch.d.ts +++ b/pyscript.core/types/fetch.d.ts @@ -8,5 +8,4 @@ * @returns {Promise<Response>} */ export function robustFetch(url: string, options?: Request): Promise<Response>; -export { getText }; -import { getText } from "polyscript/exports"; +export function getText(response: Response): Promise<string>; From df1d699fe6c50ca3f098718488344a0b4d1acfee Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi <andrea.giammarchi@gmail.com> Date: Wed, 13 Mar 2024 12:25:30 +0100 Subject: [PATCH 017/179] [feature] py-editor setup (#1989) --- pyscript.core/package-lock.json | 207 ++++++++++++------------ pyscript.core/package.json | 18 +-- pyscript.core/src/plugins/py-editor.js | 57 ++++--- pyscript.core/test/py-editor/index.html | 21 +++ pyscript.core/test/py-editor/task1.py | 1 + 5 files changed, 174 insertions(+), 130 deletions(-) create mode 100644 pyscript.core/test/py-editor/index.html create mode 100644 pyscript.core/test/py-editor/task1.py diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index fd9193ab9a4..6a4b94ef54b 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.4.5", + "version": "0.4.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.5", + "version": "0.4.6", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.9.0", + "polyscript": "^0.11.0", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -20,22 +20,22 @@ "@codemirror/commands": "^6.3.3", "@codemirror/lang-python": "^6.1.4", "@codemirror/language": "^6.10.1", - "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.24.0", - "@playwright/test": "^1.41.2", + "@codemirror/state": "^6.4.1", + "@codemirror/view": "^6.25.1", + "@playwright/test": "^1.42.1", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", "@webreflection/toml-j0.4": "^1.1.3", - "@xterm/addon-fit": "^0.9.0-beta.1", + "@xterm/addon-fit": "^0.9.0", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^8.56.0", - "rollup": "^4.11.0", + "eslint": "^8.57.0", + "rollup": "^4.12.1", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", - "typescript": "^5.3.3", + "typescript": "^5.4.2", "xterm": "^5.3.0", "xterm-readline": "^1.1.1" } @@ -129,15 +129,15 @@ } }, "node_modules/@codemirror/state": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.0.tgz", - "integrity": "sha512-hm8XshYj5Fo30Bb922QX9hXB/bxOAVH+qaqHBzw5TKa72vOeslyGwd4X8M0c1dJ9JqxlaMceOQ8RsL9tC7gU0A==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz", + "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==", "dev": true }, "node_modules/@codemirror/view": { - "version": "6.24.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.24.0.tgz", - "integrity": "sha512-zK6m5pNkdhdJl8idPP1gA4N8JKTiSsOz8U/Iw+C1ChMwyLG7+MLiNXnH/wFuAk6KeGEe33/adOiAh5jMqee03w==", + "version": "6.25.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.25.1.tgz", + "integrity": "sha512-2LXLxsQnHDdfGzDvjzAwZh2ZviNJm7im6tGpa0IONIDnFd8RZ80D2SNi8PDi6YjKcMoMRK20v6OmKIdsrwsyoQ==", "dev": true, "dependencies": { "@codemirror/state": "^6.4.0", @@ -193,9 +193,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -363,12 +363,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.41.2", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.2.tgz", - "integrity": "sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg==", + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.1.tgz", + "integrity": "sha512-Gq9rmS54mjBL/7/MvBaNOBwbfnh7beHvS6oS4srqXFcQHpQCV1+c8JXWE8VLPyRDhgS3H8x8A7hztqI9VnwrAQ==", "dev": true, "dependencies": { - "playwright": "1.41.2" + "playwright": "1.42.1" }, "bin": { "playwright": "cli.js" @@ -472,9 +472,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.11.0.tgz", - "integrity": "sha512-BV+u2QSfK3i1o6FucqJh5IK9cjAU6icjFFhvknzFgu472jzl0bBojfDAkJLBEsHFMo+YZg6rthBvBBt8z12IBQ==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.1.tgz", + "integrity": "sha512-iU2Sya8hNn1LhsYyf0N+L4Gf9Qc+9eBTJJJsaOGUp+7x4n2M9dxTt8UvhJl3oeftSjblSlpCfvjA/IfP3g5VjQ==", "cpu": [ "arm" ], @@ -485,9 +485,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.11.0.tgz", - "integrity": "sha512-0ij3iw7sT5jbcdXofWO2NqDNjSVVsf6itcAkV2I6Xsq4+6wjW1A8rViVB67TfBEan7PV2kbLzT8rhOVWLI2YXw==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.1.tgz", + "integrity": "sha512-wlzcWiH2Ir7rdMELxFE5vuM7D6TsOcJ2Yw0c3vaBR3VOsJFVTx9xvwnAvhgU5Ii8Gd6+I11qNHwndDscIm0HXg==", "cpu": [ "arm64" ], @@ -498,9 +498,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.11.0.tgz", - "integrity": "sha512-yPLs6RbbBMupArf6qv1UDk6dzZvlH66z6NLYEwqTU0VHtss1wkI4UYeeMS7TVj5QRVvaNAWYKP0TD/MOeZ76Zg==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.1.tgz", + "integrity": "sha512-YRXa1+aZIFN5BaImK+84B3uNK8C6+ynKLPgvn29X9s0LTVCByp54TB7tdSMHDR7GTV39bz1lOmlLDuedgTwwHg==", "cpu": [ "arm64" ], @@ -511,9 +511,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.11.0.tgz", - "integrity": "sha512-OvqIgwaGAwnASzXaZEeoJY3RltOFg+WUbdkdfoluh2iqatd090UeOG3A/h0wNZmE93dDew9tAtXgm3/+U/B6bw==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.1.tgz", + "integrity": "sha512-opjWJ4MevxeA8FhlngQWPBOvVWYNPFkq6/25rGgG+KOy0r8clYwL1CFd+PGwRqqMFVQ4/Qd3sQu5t7ucP7C/Uw==", "cpu": [ "x64" ], @@ -524,9 +524,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.11.0.tgz", - "integrity": "sha512-X17s4hZK3QbRmdAuLd2EE+qwwxL8JxyVupEqAkxKPa/IgX49ZO+vf0ka69gIKsaYeo6c1CuwY3k8trfDtZ9dFg==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.1.tgz", + "integrity": "sha512-uBkwaI+gBUlIe+EfbNnY5xNyXuhZbDSx2nzzW8tRMjUmpScd6lCQYKY2V9BATHtv5Ef2OBq6SChEP8h+/cxifQ==", "cpu": [ "arm" ], @@ -537,9 +537,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.11.0.tgz", - "integrity": "sha512-673Lu9EJwxVB9NfYeA4AdNu0FOHz7g9t6N1DmT7bZPn1u6bTF+oZjj+fuxUcrfxWXE0r2jxl5QYMa9cUOj9NFg==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.1.tgz", + "integrity": "sha512-0bK9aG1kIg0Su7OcFTlexkVeNZ5IzEsnz1ept87a0TUgZ6HplSgkJAnFpEVRW7GRcikT4GlPV0pbtVedOaXHQQ==", "cpu": [ "arm64" ], @@ -550,9 +550,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.11.0.tgz", - "integrity": "sha512-yFW2msTAQNpPJaMmh2NpRalr1KXI7ZUjlN6dY/FhWlOclMrZezm5GIhy3cP4Ts2rIAC+IPLAjNibjp1BsxCVGg==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.1.tgz", + "integrity": "sha512-qB6AFRXuP8bdkBI4D7UPUbE7OQf7u5OL+R94JE42Z2Qjmyj74FtDdLGeriRyBDhm4rQSvqAGCGC01b8Fu2LthQ==", "cpu": [ "arm64" ], @@ -563,9 +563,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.11.0.tgz", - "integrity": "sha512-kKT9XIuhbvYgiA3cPAGntvrBgzhWkGpBMzuk1V12Xuoqg7CI41chye4HU0vLJnGf9MiZzfNh4I7StPeOzOWJfA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.1.tgz", + "integrity": "sha512-sHig3LaGlpNgDj5o8uPEoGs98RII8HpNIqFtAI8/pYABO8i0nb1QzT0JDoXF/pxzqO+FkxvwkHZo9k0NJYDedg==", "cpu": [ "riscv64" ], @@ -576,9 +576,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.11.0.tgz", - "integrity": "sha512-6q4ESWlyTO+erp1PSCmASac+ixaDv11dBk1fqyIuvIUc/CmRAX2Zk+2qK1FGo5q7kyDcjHCFVwgGFCGIZGVwCA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.1.tgz", + "integrity": "sha512-nD3YcUv6jBJbBNFvSbp0IV66+ba/1teuBcu+fBBPZ33sidxitc6ErhON3JNavaH8HlswhWMC3s5rgZpM4MtPqQ==", "cpu": [ "x64" ], @@ -589,9 +589,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.11.0.tgz", - "integrity": "sha512-vIAQUmXeMLmaDN78HSE4Kh6xqof2e3TJUKr+LPqXWU4NYNON0MDN9h2+t4KHrPAQNmU3w1GxBQ/n01PaWFwa5w==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.1.tgz", + "integrity": "sha512-7/XVZqgBby2qp/cO0TQ8uJK+9xnSdJ9ct6gSDdEr4MfABrjTyrW6Bau7HQ73a2a5tPB7hno49A0y1jhWGDN9OQ==", "cpu": [ "x64" ], @@ -602,9 +602,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.11.0.tgz", - "integrity": "sha512-LVXo9dDTGPr0nezMdqa1hK4JeoMZ02nstUxGYY/sMIDtTYlli1ZxTXBYAz3vzuuvKO4X6NBETciIh7N9+abT1g==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.1.tgz", + "integrity": "sha512-CYc64bnICG42UPL7TrhIwsJW4QcKkIt9gGlj21gq3VV0LL6XNb1yAdHVp1pIi9gkts9gGcT3OfUYHjGP7ETAiw==", "cpu": [ "arm64" ], @@ -615,9 +615,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.11.0.tgz", - "integrity": "sha512-xZVt6K70Gr3I7nUhug2dN6VRR1ibot3rXqXS3wo+8JP64t7djc3lBFyqO4GiVrhNaAIhUCJtwQ/20dr0h0thmQ==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.1.tgz", + "integrity": "sha512-LN+vnlZ9g0qlHGlS920GR4zFCqAwbv2lULrR29yGaWP9u7wF5L7GqWu9Ah6/kFZPXPUkpdZwd//TNR+9XC9hvA==", "cpu": [ "ia32" ], @@ -628,9 +628,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.11.0.tgz", - "integrity": "sha512-f3I7h9oTg79UitEco9/2bzwdciYkWr8pITs3meSDSlr1TdvQ7IxkQaaYN2YqZXX5uZhiYL+VuYDmHwNzhx+HOg==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.1.tgz", + "integrity": "sha512-n+vkrSyphvmU0qkQ6QBNXCGr2mKjhP08mPRM/Xp5Ck2FV4NrHU+y6axzDeixUrCBHVUS51TZhjqrKBBsHLKb2Q==", "cpu": [ "x64" ], @@ -683,14 +683,21 @@ "dev": true }, "node_modules/@xterm/addon-fit": { - "version": "0.9.0-beta.1", - "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.9.0-beta.1.tgz", - "integrity": "sha512-HmGRUMMamUpQYuQBF2VP1LJ0xzqF85LMFfpaNu84t1Tsrl1lPKJWtqX9FDZ22Rf5q6bnKdbj44TRVAUHgDRbLA==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.9.0.tgz", + "integrity": "sha512-hDlPPbTVPYyvwXu/asW8HbJkI/2RMi0cMaJnBZYVeJB0SWP2NeESMCNr+I7CvBlyI0sAxpxOg8Wk4OMkxBz9WA==", "dev": true, "peerDependencies": { - "xterm": "^5.0.0" + "@xterm/xterm": "^5.0.0" } }, + "node_modules/@xterm/xterm": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.4.0.tgz", + "integrity": "sha512-GlyzcZZ7LJjhFevthHtikhiDIl8lnTSgol6eTM4aoSNLcuXu3OEhnbqdCVIjtIil3jjabf3gDtb1S8FGahsuEw==", + "dev": true, + "peer": true + }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -1356,16 +1363,16 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -2363,12 +2370,12 @@ "integrity": "sha512-yyVAOFKTAElc7KdLt2+UKGExNYwYb/Y/WE9i+1ezCQsJE8gbKSjewfpRqK2nQgZ4d4hhAAGgDCOcIZVilqE5UA==" }, "node_modules/playwright": { - "version": "1.41.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.41.2.tgz", - "integrity": "sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==", + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.1.tgz", + "integrity": "sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg==", "dev": true, "dependencies": { - "playwright-core": "1.41.2" + "playwright-core": "1.42.1" }, "bin": { "playwright": "cli.js" @@ -2381,9 +2388,9 @@ } }, "node_modules/playwright-core": { - "version": "1.41.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.41.2.tgz", - "integrity": "sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==", + "version": "1.42.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.1.tgz", + "integrity": "sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -2407,9 +2414,9 @@ } }, "node_modules/polyscript": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.9.0.tgz", - "integrity": "sha512-oyLH0jjuwZTln9v+43IJ04QR9AFTUL+n8EfEfkdbavbcMcUd9b25Evai+ZEESFnm/YU1P5ZhCglHRLTJMY4z8w==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.11.0.tgz", + "integrity": "sha512-Nl5Wy8GluitucwZpO206abHO61vWWwe9NEvtdp8Z6ClYNb2BjogtUaj98TzwFUq1N8n7NH882P3h8R+RLfAmoQ==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", @@ -3129,9 +3136,9 @@ } }, "node_modules/rollup": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.11.0.tgz", - "integrity": "sha512-2xIbaXDXjf3u2tajvA5xROpib7eegJ9Y/uPlSFhXLNpK9ampCczXAhLEb5yLzJyG3LAdI1NWtNjDXiLyniNdjQ==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.1.tgz", + "integrity": "sha512-ggqQKvx/PsB0FaWXhIvVkSWh7a/PCLQAsMjBc+nA2M8Rv2/HG0X6zvixAB7KyZBRtifBUhy5k8voQX/mRnABPg==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -3144,19 +3151,19 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.11.0", - "@rollup/rollup-android-arm64": "4.11.0", - "@rollup/rollup-darwin-arm64": "4.11.0", - "@rollup/rollup-darwin-x64": "4.11.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.11.0", - "@rollup/rollup-linux-arm64-gnu": "4.11.0", - "@rollup/rollup-linux-arm64-musl": "4.11.0", - "@rollup/rollup-linux-riscv64-gnu": "4.11.0", - "@rollup/rollup-linux-x64-gnu": "4.11.0", - "@rollup/rollup-linux-x64-musl": "4.11.0", - "@rollup/rollup-win32-arm64-msvc": "4.11.0", - "@rollup/rollup-win32-ia32-msvc": "4.11.0", - "@rollup/rollup-win32-x64-msvc": "4.11.0", + "@rollup/rollup-android-arm-eabi": "4.12.1", + "@rollup/rollup-android-arm64": "4.12.1", + "@rollup/rollup-darwin-arm64": "4.12.1", + "@rollup/rollup-darwin-x64": "4.12.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.12.1", + "@rollup/rollup-linux-arm64-gnu": "4.12.1", + "@rollup/rollup-linux-arm64-musl": "4.12.1", + "@rollup/rollup-linux-riscv64-gnu": "4.12.1", + "@rollup/rollup-linux-x64-gnu": "4.12.1", + "@rollup/rollup-linux-x64-musl": "4.12.1", + "@rollup/rollup-win32-arm64-msvc": "4.12.1", + "@rollup/rollup-win32-ia32-msvc": "4.12.1", + "@rollup/rollup-win32-x64-msvc": "4.12.1", "fsevents": "~2.3.2" } }, @@ -3546,9 +3553,9 @@ } }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 506f720d4ad..e0b62bbe7a3 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.5", + "version": "0.4.6", "type": "module", "description": "PyScript", "module": "./index.js", @@ -42,7 +42,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.9.0", + "polyscript": "^0.11.0", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -51,22 +51,22 @@ "@codemirror/commands": "^6.3.3", "@codemirror/lang-python": "^6.1.4", "@codemirror/language": "^6.10.1", - "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.24.0", - "@playwright/test": "^1.41.2", + "@codemirror/state": "^6.4.1", + "@codemirror/view": "^6.25.1", + "@playwright/test": "^1.42.1", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", "@webreflection/toml-j0.4": "^1.1.3", - "@xterm/addon-fit": "^0.9.0-beta.1", + "@xterm/addon-fit": "^0.9.0", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^8.56.0", - "rollup": "^4.11.0", + "eslint": "^8.57.0", + "rollup": "^4.12.1", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", - "typescript": "^5.3.3", + "typescript": "^5.4.2", "xterm": "^5.3.0", "xterm-readline": "^1.1.1" }, diff --git a/pyscript.core/src/plugins/py-editor.js b/pyscript.core/src/plugins/py-editor.js index ea2537a2d3c..47ce3ee9c99 100644 --- a/pyscript.core/src/plugins/py-editor.js +++ b/pyscript.core/src/plugins/py-editor.js @@ -23,9 +23,12 @@ const hooks = { async function execute({ currentTarget }) { const { env, pySrc, outDiv } = this; + const hasRunButton = !!currentTarget; - currentTarget.disabled = true; - outDiv.innerHTML = ""; + if (hasRunButton) { + currentTarget.disabled = true; + outDiv.innerHTML = ""; + } if (!envs.has(env)) { const srcLink = URL.createObjectURL(new Blob([""])); @@ -46,21 +49,25 @@ async function execute({ currentTarget }) { // before executing the current code envs.get(env).then((xworker) => { xworker.onerror = ({ error }) => { - outDiv.innerHTML += `<span style='color:red'>${ - error.message || error - }</span>\n`; + if (hasRunButton) { + outDiv.innerHTML += `<span style='color:red'>${ + error.message || error + }</span>\n`; + } console.error(error); }; const enable = () => { - currentTarget.disabled = false; + if (hasRunButton) currentTarget.disabled = false; }; const { sync } = xworker; sync.write = (str) => { - outDiv.innerText += `${str}\n`; + if (hasRunButton) outDiv.innerText += `${str}\n`; }; sync.writeErr = (str) => { - outDiv.innerHTML += `<span style='color:red'>${str}</span>\n`; + if (hasRunButton) { + outDiv.innerHTML += `<span style='color:red'>${str}</span>\n`; + } }; sync.runAsync(pySrc).then(enable, enable); }); @@ -120,7 +127,6 @@ const init = async (script, type, interpreter) => { { keymap }, { defaultKeymap }, ] = await Promise.all([ - // TODO: find a way to actually produce these bundles locally import(/* webpackIgnore: true */ "../3rd-party/codemirror.js"), import(/* webpackIgnore: true */ "../3rd-party/codemirror_state.js"), import( @@ -131,6 +137,27 @@ const init = async (script, type, interpreter) => { import(/* webpackIgnore: true */ "../3rd-party/codemirror_commands.js"), ]); + const isSetup = script.hasAttribute("setup"); + const env = `${interpreter}-${script.getAttribute("env") || getID(type)}`; + const source = script.src + ? await fetch(script.src).then((b) => b.text()) + : script.textContent; + const context = { + interpreter, + env, + get pySrc() { + return isSetup ? source : editor.state.doc.toString(); + }, + get outDiv() { + return isSetup ? null : outDiv; + }, + }; + + if (isSetup) { + execute.call(context, { currentTarget: null }); + return; + } + const selector = script.getAttribute("target"); let target; @@ -149,18 +176,6 @@ const init = async (script, type, interpreter) => { if (!target.hasAttribute("exec-id")) target.setAttribute("exec-id", 0); if (!target.hasAttribute("root")) target.setAttribute("root", target.id); - const env = `${interpreter}-${script.getAttribute("env") || getID(type)}`; - const context = { - interpreter, - env, - get pySrc() { - return editor.state.doc.toString(); - }, - get outDiv() { - return outDiv; - }, - }; - // @see https://github.com/JeffersGlass/mkdocs-pyscript/blob/main/mkdocs_pyscript/js/makeblocks.js const listener = execute.bind(context); const [boxDiv, outDiv] = makeBoxDiv(listener, type); diff --git a/pyscript.core/test/py-editor/index.html b/pyscript.core/test/py-editor/index.html new file mode 100644 index 00000000000..f58b8694fad --- /dev/null +++ b/pyscript.core/test/py-editor/index.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" href="../../dist/core.css"> + <script type="module" src="../../dist/core.js"></script> +</head> +<body> + <script type="mpy-editor" src="task1.py" env="task1" setup></script> + <script type="mpy-editor" env="task1"> + print(a) + </script> + <script type="mpy-editor" env="task2" setup> + b = 2 + </script> + <script type="mpy-editor" env="task2"> + print(b) + </script> +</body> +</html> diff --git a/pyscript.core/test/py-editor/task1.py b/pyscript.core/test/py-editor/task1.py new file mode 100644 index 00000000000..1337a530cbc --- /dev/null +++ b/pyscript.core/test/py-editor/task1.py @@ -0,0 +1 @@ +a = 1 From 69b8884045c42b7254fc8e8e89ca32180e07b13c Mon Sep 17 00:00:00 2001 From: Christian Clauss <cclauss@me.com> Date: Thu, 14 Mar 2024 15:36:18 +0100 Subject: [PATCH 018/179] Keep GitHub Actions up to date with GitHub's Dependabot (#1992) * Keep GitHub Actions up to date with GitHub's Dependabot Fix the warning like at the bottom right of https://github.com/pyscript/pyscript/actions/runs/8263920642 # https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/dependabot.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000000..e29bff2bead --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +# Keep GitHub Actions up to date with GitHub's Dependabot... +# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + groups: + github-actions: + patterns: + - "*" # Group all Actions updates into a single larger pull request + schedule: + interval: weekly From a1268f1aa2b3b1c5c3796ebc68b6f90c295eb6c1 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi <andrea.giammarchi@gmail.com> Date: Thu, 14 Mar 2024 19:36:23 +0100 Subject: [PATCH 019/179] Fix #1993 - Expose a handy fetch API (#1994) --- pyscript.core/src/stdlib/pyscript/__init__.py | 1 + pyscript.core/src/stdlib/pyscript/fetch.py | 64 ++++++++++++++++ pyscript.core/test/fetch.html | 75 +++++++++++++++++++ pyscript.core/test/mpy.spec.js | 5 ++ pyscript.core/types/stdlib/pyscript.d.ts | 1 + 5 files changed, 146 insertions(+) create mode 100644 pyscript.core/src/stdlib/pyscript/fetch.py create mode 100644 pyscript.core/test/fetch.html diff --git a/pyscript.core/src/stdlib/pyscript/__init__.py b/pyscript.core/src/stdlib/pyscript/__init__.py index dcd42f62298..8e3c53ee22b 100644 --- a/pyscript.core/src/stdlib/pyscript/__init__.py +++ b/pyscript.core/src/stdlib/pyscript/__init__.py @@ -30,6 +30,7 @@ # as it works transparently in both the main thread and worker cases. from pyscript.display import HTML, display +from pyscript.fetch import fetch from pyscript.magic_js import ( RUNNING_IN_WORKER, PyWorker, diff --git a/pyscript.core/src/stdlib/pyscript/fetch.py b/pyscript.core/src/stdlib/pyscript/fetch.py new file mode 100644 index 00000000000..087f4898fec --- /dev/null +++ b/pyscript.core/src/stdlib/pyscript/fetch.py @@ -0,0 +1,64 @@ +import json + +import js + + +def _as_bytearray(buffer): + ui8a = js.Uint8Array.new(buffer) + size = ui8a.length + ba = bytearray(size) + for i in range(0, size): + ba[i] = ui8a[i] + return ba + + +class _Fetch: + def __init__(self, url, **kw): + # avoid both Pyodide and MicroPython FFI + options = js.JSON.parse(json.dumps(kw)) + self._url = url + self._fetch = js.fetch(url, options) + + async def _arrayBuffer(self): + response = await self._response() + return await response.arrayBuffer() + + async def _response(self): + response = await self._fetch + if not response.ok: + msg = f"URL {self._url} failed with status {response.status}" + raise Exception(msg) + return response + + # https://developer.mozilla.org/en-US/docs/Web/API/Response/arrayBuffer + # returns a memoryview of the buffer + async def arrayBuffer(self): + buffer = await self._arrayBuffer() + # works in Pyodide + if hasattr(buffer, "to_py"): + return buffer.to_py() + # shims in MicroPython + return memoryview(_as_bytearray(buffer)) + + # https://developer.mozilla.org/en-US/docs/Web/API/Response/blob + async def blob(self): + response = await self._response() + return await response.blob() + + # return a bytearray from the uint8 view of the buffer + async def bytearray(self): + buffer = await self._arrayBuffer() + return _as_bytearray(buffer) + + # https://developer.mozilla.org/en-US/docs/Web/API/Response/json + async def json(self): + return json.loads(await self.text()) + + # https://developer.mozilla.org/en-US/docs/Web/API/Response/text + async def text(self): + response = await self._response() + return await response.text() + + +def fetch(url, **kw): + return _Fetch(url, **kw) diff --git a/pyscript.core/test/fetch.html b/pyscript.core/test/fetch.html new file mode 100644 index 00000000000..2c10413a01d --- /dev/null +++ b/pyscript.core/test/fetch.html @@ -0,0 +1,75 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <link rel="stylesheet" href="../dist/core.css"> + </head> + <body> + <script type="module"> + import fetch from 'https://esm.run/@webreflection/fetch'; + + globalThis.fetch_text = await fetch("config.json").text(); + globalThis.fetch_json = JSON.stringify(await fetch("config.json").json()); + globalThis.fetch_buffer = new Uint8Array((await fetch("config.json").arrayBuffer())).length; + + document.head.appendChild( + Object.assign( + document.createElement('script'), + { + type: 'module', + src: '../dist/core.js' + } + ) + ); + </script> + <script type="mpy" async> + import js, json + from pyscript import document, fetch + + fetch_text = await fetch("config.json").text() + if (fetch_text != js.fetch_text): + raise Exception("fetch_text") + + fetch_json = await fetch("config.json").json() + if (json.dumps(fetch_json).replace(" ", "") != js.fetch_json): + raise Exception("fetch_json") + + fetch_buffer = await fetch("config.json").bytearray() + if (len(fetch_buffer) != js.fetch_buffer): + raise Exception("fetch_buffer") + + print(await fetch("config.json").bytearray()) + print(await fetch("config.json").blob()) + + try: + await fetch("shenanigans.nope").text() + except: + document.documentElement.classList.add('mpy') + </script> + <script type="py" async> + import js, json + from pyscript import document, fetch + + fetch_text = await fetch("config.json").text() + if (fetch_text != js.fetch_text): + raise Exception("fetch_text") + + fetch_json = await fetch("config.json").json() + if (json.dumps(fetch_json).replace(" ", "") != js.fetch_json): + raise Exception("fetch_json") + + fetch_buffer = await fetch("config.json").bytearray() + if (len(fetch_buffer) != js.fetch_buffer): + raise Exception("fetch_buffer") + + print(await fetch("config.json").bytearray()) + print(await fetch("config.json").blob()) + + try: + await fetch("shenanigans.nope").text() + except: + document.documentElement.classList.add('py') + </script> + </body> +</html> diff --git a/pyscript.core/test/mpy.spec.js b/pyscript.core/test/mpy.spec.js index b8889102e01..c1efc70b017 100644 --- a/pyscript.core/test/mpy.spec.js +++ b/pyscript.core/test/mpy.spec.js @@ -78,3 +78,8 @@ test('Pyodide + multiple terminals via Worker', async ({ page }) => { await page.goto('http://localhost:8080/test/py-terminals.html'); await page.waitForSelector('html.first.second'); }); + +test('MicroPython + Pyodide fetch', async ({ page }) => { + await page.goto('http://localhost:8080/test/fetch.html'); + await page.waitForSelector('html.mpy.py'); +}); diff --git a/pyscript.core/types/stdlib/pyscript.d.ts b/pyscript.core/types/stdlib/pyscript.d.ts index 6bff2b5e014..47116fa59be 100644 --- a/pyscript.core/types/stdlib/pyscript.d.ts +++ b/pyscript.core/types/stdlib/pyscript.d.ts @@ -3,6 +3,7 @@ declare namespace _default { "__init__.py": string; "display.py": string; "event_handling.py": string; + "fetch.py": string; "magic_js.py": string; "util.py": string; }; From 98c0f5e50d5e0a38347fafd416f1084a20b529b2 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi <andrea.giammarchi@gmail.com> Date: Wed, 20 Mar 2024 16:40:24 +0100 Subject: [PATCH 020/179] Fix #2000 - Allow advanced users to deal themselves with responses (#2001) * Fix #2000 - Allow advanced users to deal themselves with responses * rolled back the direct utility idea * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated to latest MicroPython and latest way to have direct access with fetch * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/package-lock.json | 158 ++++++++++----------- pyscript.core/package.json | 8 +- pyscript.core/src/stdlib/pyscript/fetch.py | 106 +++++++++----- pyscript.core/test/fetch.html | 66 ++++++--- 4 files changed, 194 insertions(+), 144 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 6a4b94ef54b..3166819de04 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.4.6", + "version": "0.4.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.6", + "version": "0.4.7", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.11.0", + "polyscript": "^0.11.1", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -21,7 +21,7 @@ "@codemirror/lang-python": "^6.1.4", "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.25.1", + "@codemirror/view": "^6.26.0", "@playwright/test": "^1.42.1", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", @@ -31,7 +31,7 @@ "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^8.57.0", - "rollup": "^4.12.1", + "rollup": "^4.13.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", @@ -135,9 +135,9 @@ "dev": true }, "node_modules/@codemirror/view": { - "version": "6.25.1", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.25.1.tgz", - "integrity": "sha512-2LXLxsQnHDdfGzDvjzAwZh2ZviNJm7im6tGpa0IONIDnFd8RZ80D2SNi8PDi6YjKcMoMRK20v6OmKIdsrwsyoQ==", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.0.tgz", + "integrity": "sha512-nSSmzONpqsNzshPOxiKhK203R6BvABepugAe34QfQDbNDslyjkqBuKgrK5ZBvqNXpfxz5iLrlGTmEfhbQyH46A==", "dev": true, "dependencies": { "@codemirror/state": "^6.4.0", @@ -472,9 +472,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.1.tgz", - "integrity": "sha512-iU2Sya8hNn1LhsYyf0N+L4Gf9Qc+9eBTJJJsaOGUp+7x4n2M9dxTt8UvhJl3oeftSjblSlpCfvjA/IfP3g5VjQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.0.tgz", + "integrity": "sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg==", "cpu": [ "arm" ], @@ -485,9 +485,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.1.tgz", - "integrity": "sha512-wlzcWiH2Ir7rdMELxFE5vuM7D6TsOcJ2Yw0c3vaBR3VOsJFVTx9xvwnAvhgU5Ii8Gd6+I11qNHwndDscIm0HXg==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.0.tgz", + "integrity": "sha512-BSbaCmn8ZadK3UAQdlauSvtaJjhlDEjS5hEVVIN3A4bbl3X+otyf/kOJV08bYiRxfejP3DXFzO2jz3G20107+Q==", "cpu": [ "arm64" ], @@ -498,9 +498,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.1.tgz", - "integrity": "sha512-YRXa1+aZIFN5BaImK+84B3uNK8C6+ynKLPgvn29X9s0LTVCByp54TB7tdSMHDR7GTV39bz1lOmlLDuedgTwwHg==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.0.tgz", + "integrity": "sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g==", "cpu": [ "arm64" ], @@ -511,9 +511,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.1.tgz", - "integrity": "sha512-opjWJ4MevxeA8FhlngQWPBOvVWYNPFkq6/25rGgG+KOy0r8clYwL1CFd+PGwRqqMFVQ4/Qd3sQu5t7ucP7C/Uw==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.0.tgz", + "integrity": "sha512-U+Jcxm89UTK592vZ2J9st9ajRv/hrwHdnvyuJpa5A2ngGSVHypigidkQJP+YiGL6JODiUeMzkqQzbCG3At81Gg==", "cpu": [ "x64" ], @@ -524,9 +524,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.1.tgz", - "integrity": "sha512-uBkwaI+gBUlIe+EfbNnY5xNyXuhZbDSx2nzzW8tRMjUmpScd6lCQYKY2V9BATHtv5Ef2OBq6SChEP8h+/cxifQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.0.tgz", + "integrity": "sha512-8wZidaUJUTIR5T4vRS22VkSMOVooG0F4N+JSwQXWSRiC6yfEsFMLTYRFHvby5mFFuExHa/yAp9juSphQQJAijQ==", "cpu": [ "arm" ], @@ -537,9 +537,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.1.tgz", - "integrity": "sha512-0bK9aG1kIg0Su7OcFTlexkVeNZ5IzEsnz1ept87a0TUgZ6HplSgkJAnFpEVRW7GRcikT4GlPV0pbtVedOaXHQQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.0.tgz", + "integrity": "sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w==", "cpu": [ "arm64" ], @@ -550,9 +550,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.1.tgz", - "integrity": "sha512-qB6AFRXuP8bdkBI4D7UPUbE7OQf7u5OL+R94JE42Z2Qjmyj74FtDdLGeriRyBDhm4rQSvqAGCGC01b8Fu2LthQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.0.tgz", + "integrity": "sha512-C31QrW47llgVyrRjIwiOwsHFcaIwmkKi3PCroQY5aVq4H0A5v/vVVAtFsI1nfBngtoRpeREvZOkIhmRwUKkAdw==", "cpu": [ "arm64" ], @@ -563,9 +563,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.1.tgz", - "integrity": "sha512-sHig3LaGlpNgDj5o8uPEoGs98RII8HpNIqFtAI8/pYABO8i0nb1QzT0JDoXF/pxzqO+FkxvwkHZo9k0NJYDedg==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.0.tgz", + "integrity": "sha512-Oq90dtMHvthFOPMl7pt7KmxzX7E71AfyIhh+cPhLY9oko97Zf2C9tt/XJD4RgxhaGeAraAXDtqxvKE1y/j35lA==", "cpu": [ "riscv64" ], @@ -576,9 +576,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.1.tgz", - "integrity": "sha512-nD3YcUv6jBJbBNFvSbp0IV66+ba/1teuBcu+fBBPZ33sidxitc6ErhON3JNavaH8HlswhWMC3s5rgZpM4MtPqQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz", + "integrity": "sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA==", "cpu": [ "x64" ], @@ -589,9 +589,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.1.tgz", - "integrity": "sha512-7/XVZqgBby2qp/cO0TQ8uJK+9xnSdJ9ct6gSDdEr4MfABrjTyrW6Bau7HQ73a2a5tPB7hno49A0y1jhWGDN9OQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.0.tgz", + "integrity": "sha512-9RyNqoFNdF0vu/qqX63fKotBh43fJQeYC98hCaf89DYQpv+xu0D8QFSOS0biA7cGuqJFOc1bJ+m2rhhsKcw1hw==", "cpu": [ "x64" ], @@ -602,9 +602,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.1.tgz", - "integrity": "sha512-CYc64bnICG42UPL7TrhIwsJW4QcKkIt9gGlj21gq3VV0LL6XNb1yAdHVp1pIi9gkts9gGcT3OfUYHjGP7ETAiw==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.0.tgz", + "integrity": "sha512-46ue8ymtm/5PUU6pCvjlic0z82qWkxv54GTJZgHrQUuZnVH+tvvSP0LsozIDsCBFO4VjJ13N68wqrKSeScUKdA==", "cpu": [ "arm64" ], @@ -615,9 +615,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.1.tgz", - "integrity": "sha512-LN+vnlZ9g0qlHGlS920GR4zFCqAwbv2lULrR29yGaWP9u7wF5L7GqWu9Ah6/kFZPXPUkpdZwd//TNR+9XC9hvA==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.0.tgz", + "integrity": "sha512-P5/MqLdLSlqxbeuJ3YDeX37srC8mCflSyTrUsgbU1c/U9j6l2g2GiIdYaGD9QjdMQPMSgYm7hgg0551wHyIluw==", "cpu": [ "ia32" ], @@ -628,9 +628,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.1.tgz", - "integrity": "sha512-n+vkrSyphvmU0qkQ6QBNXCGr2mKjhP08mPRM/Xp5Ck2FV4NrHU+y6axzDeixUrCBHVUS51TZhjqrKBBsHLKb2Q==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.0.tgz", + "integrity": "sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==", "cpu": [ "x64" ], @@ -672,9 +672,9 @@ "integrity": "sha512-g7f0IkJdPW2xhY7H4iE72DAsIyfuwEFc6JWc2tYFwKDMWWAF699vGjrM348cwQuOXgHpe1gWFe+Eiyjx/ewvvw==" }, "node_modules/@webreflection/fetch": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@webreflection/fetch/-/fetch-0.1.4.tgz", - "integrity": "sha512-oKjhwcg0Phu4e9UcAEnpwHFhnywZfcPQfP6erP4T4EGSquAX8ub8+b7lYaQ80yLG3YAV51a0Bu5hsypti6oK8w==" + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@webreflection/fetch/-/fetch-0.1.5.tgz", + "integrity": "sha512-zCcqCJoNLvdeF41asAK71XPlwSPieeRDsE09albBunJEksuYPYNillKNQjf8p5BqSoTKTuKrW3lUm3MNodUC4g==" }, "node_modules/@webreflection/toml-j0.4": { "version": "1.1.3", @@ -981,14 +981,14 @@ } }, "node_modules/coincident": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/coincident/-/coincident-1.2.2.tgz", - "integrity": "sha512-6gL6Rk6NFsRDb8IniRrx43srnoybZzbIfC6jAzPipNAOOZkOZcf+2CYofNq1gypp0zalauGw0dIyqrkTrU1j8A==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/coincident/-/coincident-1.2.3.tgz", + "integrity": "sha512-Uxz3BMTWIslzeWjuQnizGWVg0j6khbvHUQ8+5BdM7WuJEm4ALXwq3wluYoB+uF68uPBz/oUOeJnYURKyfjexlA==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", "gc-hook": "^0.3.1", - "proxy-target": "^3.0.1" + "proxy-target": "^3.0.2" }, "optionalDependencies": { "ws": "^8.16.0" @@ -2414,19 +2414,19 @@ } }, "node_modules/polyscript": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.11.0.tgz", - "integrity": "sha512-Nl5Wy8GluitucwZpO206abHO61vWWwe9NEvtdp8Z6ClYNb2BjogtUaj98TzwFUq1N8n7NH882P3h8R+RLfAmoQ==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.11.1.tgz", + "integrity": "sha512-zSmzaK55Wxe2tRNeX5cb/w1Swl63YNprhGGkUbtc1jCN6W8wsOjaChFh4blvfl/g+QiL/tf+/uX7mFnanREzsA==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", - "@webreflection/fetch": "^0.1.4", + "@webreflection/fetch": "^0.1.5", "basic-devtools": "^0.1.6", "codedent": "^0.1.2", - "coincident": "^1.2.2", + "coincident": "^1.2.3", "gc-hook": "^0.3.1", "html-escaper": "^3.0.3", - "proxy-target": "^3.0.1", + "proxy-target": "^3.0.2", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1" } @@ -3010,9 +3010,9 @@ } }, "node_modules/proxy-target": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/proxy-target/-/proxy-target-3.0.1.tgz", - "integrity": "sha512-EGskR5UV9bsY3eFXBFJqq/rsDUXw/WAjeuW5YuyYaxd+0F2zgMpuZ/l5NQtju4FBHKIJnBXNGEptGqyisUgdcg==" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/proxy-target/-/proxy-target-3.0.2.tgz", + "integrity": "sha512-FFE1XNwXX/FNC3/P8HiKaJSy/Qk68RitG/QEcLy/bVnTAPlgTAWPZKh0pARLAnpfXQPKyalBhk009NRTgsk8vQ==" }, "node_modules/punycode": { "version": "2.3.1", @@ -3136,9 +3136,9 @@ } }, "node_modules/rollup": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.1.tgz", - "integrity": "sha512-ggqQKvx/PsB0FaWXhIvVkSWh7a/PCLQAsMjBc+nA2M8Rv2/HG0X6zvixAB7KyZBRtifBUhy5k8voQX/mRnABPg==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.0.tgz", + "integrity": "sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -3151,19 +3151,19 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.12.1", - "@rollup/rollup-android-arm64": "4.12.1", - "@rollup/rollup-darwin-arm64": "4.12.1", - "@rollup/rollup-darwin-x64": "4.12.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.12.1", - "@rollup/rollup-linux-arm64-gnu": "4.12.1", - "@rollup/rollup-linux-arm64-musl": "4.12.1", - "@rollup/rollup-linux-riscv64-gnu": "4.12.1", - "@rollup/rollup-linux-x64-gnu": "4.12.1", - "@rollup/rollup-linux-x64-musl": "4.12.1", - "@rollup/rollup-win32-arm64-msvc": "4.12.1", - "@rollup/rollup-win32-ia32-msvc": "4.12.1", - "@rollup/rollup-win32-x64-msvc": "4.12.1", + "@rollup/rollup-android-arm-eabi": "4.13.0", + "@rollup/rollup-android-arm64": "4.13.0", + "@rollup/rollup-darwin-arm64": "4.13.0", + "@rollup/rollup-darwin-x64": "4.13.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.13.0", + "@rollup/rollup-linux-arm64-gnu": "4.13.0", + "@rollup/rollup-linux-arm64-musl": "4.13.0", + "@rollup/rollup-linux-riscv64-gnu": "4.13.0", + "@rollup/rollup-linux-x64-gnu": "4.13.0", + "@rollup/rollup-linux-x64-musl": "4.13.0", + "@rollup/rollup-win32-arm64-msvc": "4.13.0", + "@rollup/rollup-win32-ia32-msvc": "4.13.0", + "@rollup/rollup-win32-x64-msvc": "4.13.0", "fsevents": "~2.3.2" } }, diff --git a/pyscript.core/package.json b/pyscript.core/package.json index e0b62bbe7a3..7b82224ab3b 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.6", + "version": "0.4.7", "type": "module", "description": "PyScript", "module": "./index.js", @@ -42,7 +42,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.11.0", + "polyscript": "^0.11.1", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -52,7 +52,7 @@ "@codemirror/lang-python": "^6.1.4", "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.25.1", + "@codemirror/view": "^6.26.0", "@playwright/test": "^1.42.1", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", @@ -62,7 +62,7 @@ "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^8.57.0", - "rollup": "^4.12.1", + "rollup": "^4.13.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", diff --git a/pyscript.core/src/stdlib/pyscript/fetch.py b/pyscript.core/src/stdlib/pyscript/fetch.py index 087f4898fec..28764f551c9 100644 --- a/pyscript.core/src/stdlib/pyscript/fetch.py +++ b/pyscript.core/src/stdlib/pyscript/fetch.py @@ -3,62 +3,92 @@ import js -def _as_bytearray(buffer): - ui8a = js.Uint8Array.new(buffer) - size = ui8a.length - ba = bytearray(size) - for i in range(0, size): - ba[i] = ui8a[i] - return ba - - -class _Fetch: - def __init__(self, url, **kw): - # avoid both Pyodide and MicroPython FFI - options = js.JSON.parse(json.dumps(kw)) - self._url = url - self._fetch = js.fetch(url, options) - - async def _arrayBuffer(self): - response = await self._response() - return await response.arrayBuffer() +### wrap the response to grant Pythonic results +class _Response: + def __init__(self, response): + self._response = response - async def _response(self): - response = await self._fetch - if not response.ok: - msg = f"URL {self._url} failed with status {response.status}" - raise Exception(msg) - return response - - # https://developer.mozilla.org/en-US/docs/Web/API/Response/arrayBuffer - # returns a memoryview of the buffer + # grant access to response.ok and other fields + def __getattr__(self, attr): + return getattr(self._response, attr) + + def _as_bytearray(self, buffer): + ui8a = js.Uint8Array.new(buffer) + size = ui8a.length + ba = bytearray(size) + for i in range(0, size): + ba[i] = ui8a[i] + return ba + + # exposed methods with Pythonic results async def arrayBuffer(self): - buffer = await self._arrayBuffer() + buffer = await self._response.arrayBuffer() # works in Pyodide if hasattr(buffer, "to_py"): return buffer.to_py() # shims in MicroPython - return memoryview(_as_bytearray(buffer)) + return memoryview(self._as_bytearray(buffer)) + + async def blob(self): + return await self._response.blob() + + async def bytearray(self): + buffer = await self._response.arrayBuffer() + return self._as_bytearray(buffer) + + async def json(self): + return json.loads(await self.text()) + + async def text(self): + return await self._response.text() + + +### allow direct await to _Response methods +class _DirectResponse: + @staticmethod + def setup(promise, response): + promise._response = _Response(response) + return promise._response + + def __init__(self, promise): + self._promise = promise + promise._response = None + promise.arrayBuffer = self.arrayBuffer + promise.blob = self.blob + promise.bytearray = self.bytearray + promise.json = self.json + promise.text = self.text + + async def _response(self): + if not self._promise._response: + await self._promise + return self._promise._response + + async def arrayBuffer(self): + response = await self._response() + return await response.arrayBuffer() - # https://developer.mozilla.org/en-US/docs/Web/API/Response/blob async def blob(self): response = await self._response() return await response.blob() - # return a bytearray from the uint8 view of the buffer async def bytearray(self): - buffer = await self._arrayBuffer() - return _as_bytearray(buffer) + response = await self._response() + return await response.bytearray() - # https://developer.mozilla.org/en-US/docs/Web/API/Response/json async def json(self): - return json.loads(await self.text()) + response = await self._response() + return await response.json() - # https://developer.mozilla.org/en-US/docs/Web/API/Response/text async def text(self): response = await self._response() return await response.text() def fetch(url, **kw): - return _Fetch(url, **kw) + # workaround Pyodide / MicroPython dict <-> js conversion + options = js.JSON.parse(json.dumps(kw)) + awaited = lambda response, *args: _DirectResponse.setup(promise, response) + promise = js.fetch(url, options).then(awaited) + _DirectResponse(promise) + return promise diff --git a/pyscript.core/test/fetch.html b/pyscript.core/test/fetch.html index 2c10413a01d..35f8fb79a70 100644 --- a/pyscript.core/test/fetch.html +++ b/pyscript.core/test/fetch.html @@ -24,51 +24,71 @@ ); </script> <script type="mpy" async> - import js, json - from pyscript import document, fetch + import js, json + from pyscript import document, fetch + + fetch_text = await (await fetch("config.json")).text() + if (fetch_text != js.fetch_text): + raise Exception("fetch_text") + + fetch_text = await fetch("config.json").text() + if (fetch_text != js.fetch_text): + raise Exception("fetch_text") - fetch_text = await fetch("config.json").text() - if (fetch_text != js.fetch_text): - raise Exception("fetch_text") + fetch_json = await (await fetch("config.json")).json() + if (json.dumps(fetch_json).replace(" ", "") != js.fetch_json): + raise Exception("fetch_json") + + fetch_json = await fetch("config.json").json() + if (json.dumps(fetch_json).replace(" ", "") != js.fetch_json): + raise Exception("fetch_json") - fetch_json = await fetch("config.json").json() - if (json.dumps(fetch_json).replace(" ", "") != js.fetch_json): - raise Exception("fetch_json") + fetch_buffer = await (await fetch("config.json")).arrayBuffer() + if (len(fetch_buffer) != js.fetch_buffer): + raise Exception("fetch_buffer") - fetch_buffer = await fetch("config.json").bytearray() - if (len(fetch_buffer) != js.fetch_buffer): - raise Exception("fetch_buffer") + fetch_buffer = await fetch("config.json").arrayBuffer() + if (len(fetch_buffer) != js.fetch_buffer): + raise Exception("fetch_buffer") - print(await fetch("config.json").bytearray()) - print(await fetch("config.json").blob()) + print(await (await fetch("config.json")).bytearray()) + print(await (await fetch("config.json")).blob()) - try: - await fetch("shenanigans.nope").text() - except: - document.documentElement.classList.add('mpy') + if (await fetch("shenanigans.nope")).ok == False: + document.documentElement.classList.add('mpy') </script> <script type="py" async> import js, json from pyscript import document, fetch + fetch_text = await (await fetch("config.json")).text() + if (fetch_text != js.fetch_text): + raise Exception("fetch_text") + fetch_text = await fetch("config.json").text() if (fetch_text != js.fetch_text): raise Exception("fetch_text") + fetch_json = await (await fetch("config.json")).json() + if (json.dumps(fetch_json).replace(" ", "") != js.fetch_json): + raise Exception("fetch_json") + fetch_json = await fetch("config.json").json() if (json.dumps(fetch_json).replace(" ", "") != js.fetch_json): raise Exception("fetch_json") - fetch_buffer = await fetch("config.json").bytearray() + fetch_buffer = await (await fetch("config.json")).arrayBuffer() + if (len(fetch_buffer) != js.fetch_buffer): + raise Exception("fetch_buffer") + + fetch_buffer = await fetch("config.json").arrayBuffer() if (len(fetch_buffer) != js.fetch_buffer): raise Exception("fetch_buffer") - print(await fetch("config.json").bytearray()) - print(await fetch("config.json").blob()) + print(await (await fetch("config.json")).bytearray()) + print(await (await fetch("config.json")).blob()) - try: - await fetch("shenanigans.nope").text() - except: + if (await fetch("shenanigans.nope")).ok == False: document.documentElement.classList.add('py') </script> </body> From d080246a0f4a5b3663b4e4d669b58115e5e771aa Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi <andrea.giammarchi@gmail.com> Date: Thu, 21 Mar 2024 11:47:47 +0100 Subject: [PATCH 021/179] Update MicroPython to its latest (#2003) --- pyscript.core/package-lock.json | 20 ++++++++++---------- pyscript.core/package.json | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 3166819de04..9428c2b2047 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.4.7", + "version": "0.4.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.7", + "version": "0.4.8", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.11.1", + "polyscript": "^0.11.2", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -35,7 +35,7 @@ "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", - "typescript": "^5.4.2", + "typescript": "^5.4.3", "xterm": "^5.3.0", "xterm-readline": "^1.1.1" } @@ -2414,9 +2414,9 @@ } }, "node_modules/polyscript": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.11.1.tgz", - "integrity": "sha512-zSmzaK55Wxe2tRNeX5cb/w1Swl63YNprhGGkUbtc1jCN6W8wsOjaChFh4blvfl/g+QiL/tf+/uX7mFnanREzsA==", + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.11.2.tgz", + "integrity": "sha512-ITDUPvb63iuew2PxET8UQV/NduCTMesB6EHdbuBtESapJ21+WFyDAyIttXKc0W9fzFRUn1j9udEEH7vDbz6MKg==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", @@ -3553,9 +3553,9 @@ } }, "node_modules/typescript": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", - "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 7b82224ab3b..f2775a775b7 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.7", + "version": "0.4.8", "type": "module", "description": "PyScript", "module": "./index.js", @@ -42,7 +42,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.11.1", + "polyscript": "^0.11.2", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -66,7 +66,7 @@ "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", - "typescript": "^5.4.2", + "typescript": "^5.4.3", "xterm": "^5.3.0", "xterm-readline": "^1.1.1" }, From eee2f64c1d49c54089ec4f815721fe2c77e52562 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi <andrea.giammarchi@gmail.com> Date: Fri, 22 Mar 2024 10:42:01 +0100 Subject: [PATCH 022/179] Update Polyscript with its latest untar.gz and unzip abilities (#2004) --- pyscript.core/package-lock.json | 12 ++++++------ pyscript.core/package.json | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 9428c2b2047..6db70a3d9b5 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.4.8", + "version": "0.4.9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.8", + "version": "0.4.9", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.11.2", + "polyscript": "^0.11.3", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -2414,9 +2414,9 @@ } }, "node_modules/polyscript": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.11.2.tgz", - "integrity": "sha512-ITDUPvb63iuew2PxET8UQV/NduCTMesB6EHdbuBtESapJ21+WFyDAyIttXKc0W9fzFRUn1j9udEEH7vDbz6MKg==", + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.11.3.tgz", + "integrity": "sha512-0wzunsH9b/h+EoB0tZKMRUg0YoFHraRuBuPK+cJsmUmNr1bVM1LvzFk21grDstXjo6Ah78dEC7SjaA0sSBsJeQ==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index f2775a775b7..7adf11301ef 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.8", + "version": "0.4.9", "type": "module", "description": "PyScript", "module": "./index.js", @@ -42,7 +42,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.11.2", + "polyscript": "^0.11.3", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" From 910c666319969a33e729be8f30d9257226ab77d1 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi <andrea.giammarchi@gmail.com> Date: Fri, 22 Mar 2024 17:41:06 +0100 Subject: [PATCH 023/179] pyscript.ffi - expose most essential utilities (#2005) pyscript.ffi - expose most essential utilities --- pyscript.core/package-lock.json | 4 ++-- pyscript.core/package.json | 2 +- pyscript.core/src/stdlib/pyscript/ffi.py | 18 ++++++++++++++++ pyscript.core/test/ffi.html | 26 ++++++++++++++++++++++++ pyscript.core/test/mpy.spec.js | 5 +++++ pyscript.core/types/stdlib/pyscript.d.ts | 1 + 6 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 pyscript.core/src/stdlib/pyscript/ffi.py create mode 100644 pyscript.core/test/ffi.html diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 6db70a3d9b5..bd395b4d66d 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.9", + "version": "0.4.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.9", + "version": "0.4.10", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 7adf11301ef..691f4c8620d 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.9", + "version": "0.4.10", "type": "module", "description": "PyScript", "module": "./index.js", diff --git a/pyscript.core/src/stdlib/pyscript/ffi.py b/pyscript.core/src/stdlib/pyscript/ffi.py new file mode 100644 index 00000000000..fd6ae658614 --- /dev/null +++ b/pyscript.core/src/stdlib/pyscript/ffi.py @@ -0,0 +1,18 @@ +try: + import js + from pyodide.ffi import create_proxy as _cp + from pyodide.ffi import to_js as _py_tjs + + from_entries = js.Object.fromEntries + + def _tjs(value, **kw): + if not hasattr(kw, "dict_converter"): + kw["dict_converter"] = from_entries + return _py_tjs(value, **kw) + +except: + from jsffi import create_proxy as _cp + from jsffi import to_js as _tjs + +create_proxy = _cp +to_js = _tjs diff --git a/pyscript.core/test/ffi.html b/pyscript.core/test/ffi.html new file mode 100644 index 00000000000..1c29ccb82c4 --- /dev/null +++ b/pyscript.core/test/ffi.html @@ -0,0 +1,26 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>PyScript FFI + + + + + + + + diff --git a/pyscript.core/test/mpy.spec.js b/pyscript.core/test/mpy.spec.js index c1efc70b017..fe94019c4f5 100644 --- a/pyscript.core/test/mpy.spec.js +++ b/pyscript.core/test/mpy.spec.js @@ -83,3 +83,8 @@ test('MicroPython + Pyodide fetch', async ({ page }) => { await page.goto('http://localhost:8080/test/fetch.html'); await page.waitForSelector('html.mpy.py'); }); + +test('MicroPython + Pyodide ffi', async ({ page }) => { + await page.goto('http://localhost:8080/test/ffi.html'); + await page.waitForSelector('html.mpy.py'); +}); diff --git a/pyscript.core/types/stdlib/pyscript.d.ts b/pyscript.core/types/stdlib/pyscript.d.ts index 47116fa59be..648b493ef12 100644 --- a/pyscript.core/types/stdlib/pyscript.d.ts +++ b/pyscript.core/types/stdlib/pyscript.d.ts @@ -4,6 +4,7 @@ declare namespace _default { "display.py": string; "event_handling.py": string; "fetch.py": string; + "ffi.py": string; "magic_js.py": string; "util.py": string; }; From 2f3659b676902553c187663ce975d48d66af49e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 11:00:29 +0100 Subject: [PATCH 024/179] Bump the github-actions group with 6 updates (#1995) Bumps the github-actions group with 6 updates: | Package | From | To | | --- | --- | --- | | [actions/setup-node](https://github.com/actions/setup-node) | `3` | `4` | | [actions/cache](https://github.com/actions/cache) | `3` | `4` | | [softprops/action-gh-release](https://github.com/softprops/action-gh-release) | `1` | `2` | | [conda-incubator/setup-miniconda](https://github.com/conda-incubator/setup-miniconda) | `2` | `3` | | [actions/upload-artifact](https://github.com/actions/upload-artifact) | `3` | `4` | | [dorny/test-reporter](https://github.com/dorny/test-reporter) | `1.6.0` | `1.8.0` | Updates `actions/setup-node` from 3 to 4 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v3...v4) Updates `actions/cache` from 3 to 4 - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) Updates `softprops/action-gh-release` from 1 to 2 - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2) Updates `conda-incubator/setup-miniconda` from 2 to 3 - [Release notes](https://github.com/conda-incubator/setup-miniconda/releases) - [Changelog](https://github.com/conda-incubator/setup-miniconda/blob/main/CHANGELOG.md) - [Commits](https://github.com/conda-incubator/setup-miniconda/compare/v2...v3) Updates `actions/upload-artifact` from 3 to 4 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) Updates `dorny/test-reporter` from 1.6.0 to 1.8.0 - [Release notes](https://github.com/dorny/test-reporter/releases) - [Changelog](https://github.com/dorny/test-reporter/blob/main/CHANGELOG.md) - [Commits](https://github.com/dorny/test-reporter/compare/v1.6.0...v1.8.0) --- updated-dependencies: - dependency-name: actions/setup-node dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: softprops/action-gh-release dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: conda-incubator/setup-miniconda dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: dorny/test-reporter dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/prepare-release.yml | 6 +++--- .github/workflows/publish-release.yml | 4 ++-- .github/workflows/publish-snapshot.yml | 4 ++-- .github/workflows/publish-unstable.yml | 4 ++-- .github/workflows/test.yml | 10 +++++----- .github/workflows/test_report.yml | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 6bbb666f2cd..56d5ff3c5a2 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -17,12 +17,12 @@ jobs: uses: actions/checkout@v4 - name: Install node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18.x - name: Cache node modules - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-node-modules with: @@ -48,7 +48,7 @@ jobs: run: zip -r -q ./build.zip ./dist - name: Prepare Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: draft: true prerelease: true diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 36828477dc5..64f4f9ef693 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -19,12 +19,12 @@ jobs: uses: actions/checkout@v4 - name: Install node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18.x - name: Cache node modules - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-node-modules with: diff --git a/.github/workflows/publish-snapshot.yml b/.github/workflows/publish-snapshot.yml index 944a26f3981..c270fa7651e 100644 --- a/.github/workflows/publish-snapshot.yml +++ b/.github/workflows/publish-snapshot.yml @@ -23,12 +23,12 @@ jobs: uses: actions/checkout@v4 - name: Install node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18.x - name: Cache node modules - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-node-modules with: diff --git a/.github/workflows/publish-unstable.yml b/.github/workflows/publish-unstable.yml index f2a1df45491..2a81b52f3b5 100644 --- a/.github/workflows/publish-unstable.yml +++ b/.github/workflows/publish-unstable.yml @@ -24,12 +24,12 @@ jobs: uses: actions/checkout@v4 - name: Install node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18.x - name: Cache node modules - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-node-modules with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f7b83be7730..116f36fcd09 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,12 +37,12 @@ jobs: run: git log --graph -3 - name: Install node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 20.x - name: Cache node modules - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-node-modules with: @@ -55,7 +55,7 @@ jobs: ${{ runner.os }}- - name: setup Miniconda - uses: conda-incubator/setup-miniconda@v2 + uses: conda-incubator/setup-miniconda@v3 - name: Create and activate virtual environment run: | @@ -76,7 +76,7 @@ jobs: run: | make test-integration - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: pyscript path: | @@ -84,7 +84,7 @@ jobs: if-no-files-found: error retention-days: 7 - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 if: success() || failure() with: name: test_results diff --git a/.github/workflows/test_report.yml b/.github/workflows/test_report.yml index 6debdbdce4d..dde23ce4e1a 100644 --- a/.github/workflows/test_report.yml +++ b/.github/workflows/test_report.yml @@ -8,7 +8,7 @@ jobs: report: runs-on: ubuntu-latest-8core steps: - - uses: dorny/test-reporter@v1.6.0 + - uses: dorny/test-reporter@v1.8.0 with: artifact: test_results name: Test reports From 1447cb3094abdb1f4d974445635b2adaee7174cc Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Thu, 28 Mar 2024 10:43:26 +0100 Subject: [PATCH 025/179] Fix #1997 - Bring pyscript stdlib to the PyEditor (#2010) * Fix #1997 - Bring pyscript stdlib to the PyEditor --- pyscript.core/package-lock.json | 130 +++++++++++++---------- pyscript.core/package.json | 4 +- pyscript.core/src/core.js | 3 + pyscript.core/src/plugins/py-editor.js | 35 +++++- pyscript.core/test/py-editor/config.toml | 2 + pyscript.core/test/py-editor/index.html | 28 ++++- pyscript.core/test/py-editor/task1.py | 4 + pyscript.core/types/core.d.ts | 9 +- 8 files changed, 140 insertions(+), 75 deletions(-) create mode 100644 pyscript.core/test/py-editor/config.toml diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index bd395b4d66d..95eaa1fd0d5 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.10", + "version": "0.4.11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.10", + "version": "0.4.11", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", @@ -31,7 +31,7 @@ "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^8.57.0", - "rollup": "^4.13.0", + "rollup": "^4.13.1", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", @@ -472,9 +472,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.0.tgz", - "integrity": "sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.1.tgz", + "integrity": "sha512-4C4UERETjXpC4WpBXDbkgNVgHyWfG3B/NKY46e7w5H134UDOFqUJKpsLm0UYmuupW+aJmRgeScrDNfvZ5WV80A==", "cpu": [ "arm" ], @@ -485,9 +485,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.0.tgz", - "integrity": "sha512-BSbaCmn8ZadK3UAQdlauSvtaJjhlDEjS5hEVVIN3A4bbl3X+otyf/kOJV08bYiRxfejP3DXFzO2jz3G20107+Q==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.1.tgz", + "integrity": "sha512-TrTaFJ9pXgfXEiJKQ3yQRelpQFqgRzVR9it8DbeRzG0RX7mKUy0bqhCFsgevwXLJepQKTnLl95TnPGf9T9AMOA==", "cpu": [ "arm64" ], @@ -498,9 +498,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.0.tgz", - "integrity": "sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.1.tgz", + "integrity": "sha512-fz7jN6ahTI3cKzDO2otQuybts5cyu0feymg0bjvYCBrZQ8tSgE8pc0sSNEuGvifrQJWiwx9F05BowihmLxeQKw==", "cpu": [ "arm64" ], @@ -511,9 +511,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.0.tgz", - "integrity": "sha512-U+Jcxm89UTK592vZ2J9st9ajRv/hrwHdnvyuJpa5A2ngGSVHypigidkQJP+YiGL6JODiUeMzkqQzbCG3At81Gg==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.1.tgz", + "integrity": "sha512-WTvdz7SLMlJpektdrnWRUN9C0N2qNHwNbWpNo0a3Tod3gb9leX+yrYdCeB7VV36OtoyiPAivl7/xZ3G1z5h20g==", "cpu": [ "x64" ], @@ -524,9 +524,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.0.tgz", - "integrity": "sha512-8wZidaUJUTIR5T4vRS22VkSMOVooG0F4N+JSwQXWSRiC6yfEsFMLTYRFHvby5mFFuExHa/yAp9juSphQQJAijQ==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.1.tgz", + "integrity": "sha512-dBHQl+7wZzBYcIF6o4k2XkAfwP2ks1mYW2q/Gzv9n39uDcDiAGDqEyml08OdY0BIct0yLSPkDTqn4i6czpBLLw==", "cpu": [ "arm" ], @@ -537,9 +537,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.0.tgz", - "integrity": "sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.1.tgz", + "integrity": "sha512-bur4JOxvYxfrAmocRJIW0SADs3QdEYK6TQ7dTNz6Z4/lySeu3Z1H/+tl0a4qDYv0bCdBpUYM0sYa/X+9ZqgfSQ==", "cpu": [ "arm64" ], @@ -550,9 +550,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.0.tgz", - "integrity": "sha512-C31QrW47llgVyrRjIwiOwsHFcaIwmkKi3PCroQY5aVq4H0A5v/vVVAtFsI1nfBngtoRpeREvZOkIhmRwUKkAdw==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.1.tgz", + "integrity": "sha512-ssp77SjcDIUSoUyj7DU7/5iwM4ZEluY+N8umtCT9nBRs3u045t0KkW02LTyHouHDomnMXaXSZcCSr2bdMK63kA==", "cpu": [ "arm64" ], @@ -563,9 +563,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.0.tgz", - "integrity": "sha512-Oq90dtMHvthFOPMl7pt7KmxzX7E71AfyIhh+cPhLY9oko97Zf2C9tt/XJD4RgxhaGeAraAXDtqxvKE1y/j35lA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.1.tgz", + "integrity": "sha512-Jv1DkIvwEPAb+v25/Unrnnq9BO3F5cbFPT821n3S5litkz+O5NuXuNhqtPx5KtcwOTtaqkTsO+IVzJOsxd11aQ==", "cpu": [ "riscv64" ], @@ -575,10 +575,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.13.1.tgz", + "integrity": "sha512-U564BrhEfaNChdATQaEODtquCC7Ez+8Hxz1h5MAdMYj0AqD0GA9rHCpElajb/sQcaFL6NXmHc5O+7FXpWMa73Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz", - "integrity": "sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.1.tgz", + "integrity": "sha512-zGRDulLTeDemR8DFYyFIQ8kMP02xpUsX4IBikc7lwL9PrwR3gWmX2NopqiGlI2ZVWMl15qZeUjumTwpv18N7sQ==", "cpu": [ "x64" ], @@ -589,9 +602,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.0.tgz", - "integrity": "sha512-9RyNqoFNdF0vu/qqX63fKotBh43fJQeYC98hCaf89DYQpv+xu0D8QFSOS0biA7cGuqJFOc1bJ+m2rhhsKcw1hw==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.1.tgz", + "integrity": "sha512-VTk/MveyPdMFkYJJPCkYBw07KcTkGU2hLEyqYMsU4NjiOfzoaDTW9PWGRsNwiOA3qI0k/JQPjkl/4FCK1smskQ==", "cpu": [ "x64" ], @@ -602,9 +615,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.0.tgz", - "integrity": "sha512-46ue8ymtm/5PUU6pCvjlic0z82qWkxv54GTJZgHrQUuZnVH+tvvSP0LsozIDsCBFO4VjJ13N68wqrKSeScUKdA==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.1.tgz", + "integrity": "sha512-L+hX8Dtibb02r/OYCsp4sQQIi3ldZkFI0EUkMTDwRfFykXBPptoz/tuuGqEd3bThBSLRWPR6wsixDSgOx/U3Zw==", "cpu": [ "arm64" ], @@ -615,9 +628,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.0.tgz", - "integrity": "sha512-P5/MqLdLSlqxbeuJ3YDeX37srC8mCflSyTrUsgbU1c/U9j6l2g2GiIdYaGD9QjdMQPMSgYm7hgg0551wHyIluw==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.1.tgz", + "integrity": "sha512-+dI2jVPfM5A8zme8riEoNC7UKk0Lzc7jCj/U89cQIrOjrZTCWZl/+IXUeRT2rEZ5j25lnSA9G9H1Ob9azaF/KQ==", "cpu": [ "ia32" ], @@ -628,9 +641,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.0.tgz", - "integrity": "sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.1.tgz", + "integrity": "sha512-YY1Exxo2viZ/O2dMHuwQvimJ0SqvL+OAWQLLY6rvXavgQKjhQUzn7nc1Dd29gjB5Fqi00nrBWctJBOyfVMIVxw==", "cpu": [ "x64" ], @@ -3136,9 +3149,9 @@ } }, "node_modules/rollup": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.0.tgz", - "integrity": "sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.1.tgz", + "integrity": "sha512-hFi+fU132IvJ2ZuihN56dwgpltpmLZHZWsx27rMCTZ2sYwrqlgL5sECGy1eeV2lAihD8EzChBVVhsXci0wD4Tg==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -3151,19 +3164,20 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.13.0", - "@rollup/rollup-android-arm64": "4.13.0", - "@rollup/rollup-darwin-arm64": "4.13.0", - "@rollup/rollup-darwin-x64": "4.13.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.13.0", - "@rollup/rollup-linux-arm64-gnu": "4.13.0", - "@rollup/rollup-linux-arm64-musl": "4.13.0", - "@rollup/rollup-linux-riscv64-gnu": "4.13.0", - "@rollup/rollup-linux-x64-gnu": "4.13.0", - "@rollup/rollup-linux-x64-musl": "4.13.0", - "@rollup/rollup-win32-arm64-msvc": "4.13.0", - "@rollup/rollup-win32-ia32-msvc": "4.13.0", - "@rollup/rollup-win32-x64-msvc": "4.13.0", + "@rollup/rollup-android-arm-eabi": "4.13.1", + "@rollup/rollup-android-arm64": "4.13.1", + "@rollup/rollup-darwin-arm64": "4.13.1", + "@rollup/rollup-darwin-x64": "4.13.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.13.1", + "@rollup/rollup-linux-arm64-gnu": "4.13.1", + "@rollup/rollup-linux-arm64-musl": "4.13.1", + "@rollup/rollup-linux-riscv64-gnu": "4.13.1", + "@rollup/rollup-linux-s390x-gnu": "4.13.1", + "@rollup/rollup-linux-x64-gnu": "4.13.1", + "@rollup/rollup-linux-x64-musl": "4.13.1", + "@rollup/rollup-win32-arm64-msvc": "4.13.1", + "@rollup/rollup-win32-ia32-msvc": "4.13.1", + "@rollup/rollup-win32-x64-msvc": "4.13.1", "fsevents": "~2.3.2" } }, diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 691f4c8620d..f7b04a6de66 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.10", + "version": "0.4.11", "type": "module", "description": "PyScript", "module": "./index.js", @@ -62,7 +62,7 @@ "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^8.57.0", - "rollup": "^4.13.0", + "rollup": "^4.13.1", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", diff --git a/pyscript.core/src/core.js b/pyscript.core/src/core.js index 44cc9096982..d3955557918 100644 --- a/pyscript.core/src/core.js +++ b/pyscript.core/src/core.js @@ -26,6 +26,9 @@ import { ErrorCode } from "./exceptions.js"; import { robustFetch as fetch, getText } from "./fetch.js"; import { hooks, main, worker, codeFor, createFunction } from "./hooks.js"; +import stdlib from "./stdlib.js"; +export { stdlib }; + // generic helper to disambiguate between custom element and script const isScript = ({ tagName }) => tagName === "SCRIPT"; diff --git a/pyscript.core/src/plugins/py-editor.js b/pyscript.core/src/plugins/py-editor.js index 47ce3ee9c99..8b1bb8d5e3d 100644 --- a/pyscript.core/src/plugins/py-editor.js +++ b/pyscript.core/src/plugins/py-editor.js @@ -1,6 +1,6 @@ // PyScript py-editor plugin import { Hook, XWorker, dedent } from "polyscript/exports"; -import { TYPES } from "../core.js"; +import { TYPES, stdlib } from "../core.js"; const RUN_BUTTON = ``; @@ -8,9 +8,11 @@ let id = 0; const getID = (type) => `${type}-editor-${id++}`; const envs = new Map(); +const configs = new Map(); const hooks = { worker: { + codeBeforeRun: () => stdlib, // works on both Pyodide and MicroPython onReady: ({ runAsync, io }, { sync }) => { io.stdout = (line) => sync.write(line); @@ -32,9 +34,17 @@ async function execute({ currentTarget }) { if (!envs.has(env)) { const srcLink = URL.createObjectURL(new Blob([""])); - const xworker = XWorker.call(new Hook(null, hooks), srcLink, { - type: this.interpreter, - }); + const details = { type: this.interpreter }; + const { config } = this; + if (config) { + details.configURL = config; + const { parse } = config.endsWith(".toml") + ? await import(/* webpackIgnore: true */ "../3rd-party/toml.js") + : JSON; + details.config = parse(await fetch(config).then((r) => r.text())); + } + + const xworker = XWorker.call(new Hook(null, hooks), srcLink, details); const { sync } = xworker; const { promise, resolve } = Promise.withResolvers(); @@ -138,13 +148,28 @@ const init = async (script, type, interpreter) => { ]); const isSetup = script.hasAttribute("setup"); + const hasConfig = script.hasAttribute("config"); const env = `${interpreter}-${script.getAttribute("env") || getID(type)}`; + + if (hasConfig && configs.has(env)) { + throw new SyntaxError( + configs.get(env) + ? `duplicated config for env: ${env}` + : `unable to add a config to the env: ${env}`, + ); + } + + configs.set(env, hasConfig); + const source = script.src ? await fetch(script.src).then((b) => b.text()) : script.textContent; const context = { interpreter, env, + config: + hasConfig && + new URL(script.getAttribute("config"), location.href).href, get pySrc() { return isSetup ? source : editor.state.doc.toString(); }, @@ -225,7 +250,7 @@ const resetTimeout = () => { }; // triggered both ASAP on the living DOM and via MutationObserver later -const pyEditor = async () => { +const pyEditor = () => { if (timeout) return; timeout = setTimeout(resetTimeout, 250); for (const [type, interpreter] of TYPES) { diff --git a/pyscript.core/test/py-editor/config.toml b/pyscript.core/test/py-editor/config.toml new file mode 100644 index 00000000000..2c8a09a6454 --- /dev/null +++ b/pyscript.core/test/py-editor/config.toml @@ -0,0 +1,2 @@ +[js_modules.worker] +"https://cdn.jsdelivr.net/npm/html-escaper/+esm" = "html_escaper" diff --git a/pyscript.core/test/py-editor/index.html b/pyscript.core/test/py-editor/index.html index f58b8694fad..ec46bc61192 100644 --- a/pyscript.core/test/py-editor/index.html +++ b/pyscript.core/test/py-editor/index.html @@ -7,15 +7,35 @@ - + + - + + diff --git a/pyscript.core/test/py-editor/task1.py b/pyscript.core/test/py-editor/task1.py index 1337a530cbc..014e073d39a 100644 --- a/pyscript.core/test/py-editor/task1.py +++ b/pyscript.core/test/py-editor/task1.py @@ -1 +1,5 @@ +from pyscript import window + +window.console.log("OK") + a = 1 diff --git a/pyscript.core/types/core.d.ts b/pyscript.core/types/core.d.ts index c7b4f9f7d61..4bddbbc75f1 100644 --- a/pyscript.core/types/core.d.ts +++ b/pyscript.core/types/core.d.ts @@ -1,3 +1,4 @@ +import stdlib from "./stdlib.js"; import TYPES from "./types.js"; /** * A `Worker` facade able to bootstrap on the worker thread only a PyScript module. @@ -38,11 +39,7 @@ declare const exportedHooks: { }; worker: { onReady: Set; - onBeforeRun: Set; /** - * Given a generic DOM Element, tries to fetch the 'src' attribute, if present. - * It either throws an error if the 'src' can't be fetched or it returns a fallback - * content as source. - */ + onBeforeRun: Set; onBeforeRunAsync: Set; onAfterRun: Set; onAfterRunAsync: Set; @@ -55,4 +52,4 @@ declare const exportedHooks: { declare const exportedConfig: {}; declare const exportedWhenDefined: (type: string) => Promise; import sync from "./sync.js"; -export { TYPES, exportedPyWorker as PyWorker, exportedMPWorker as MPWorker, exportedHooks as hooks, exportedConfig as config, exportedWhenDefined as whenDefined }; +export { stdlib, TYPES, exportedPyWorker as PyWorker, exportedMPWorker as MPWorker, exportedHooks as hooks, exportedConfig as config, exportedWhenDefined as whenDefined }; From 4e4ac56729457306a74f2a9109a2ea49132bf139 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Wed, 3 Apr 2024 15:50:20 +0200 Subject: [PATCH 026/179] Fix #1998 - Allow lazy terminal bootstrap + MicroPython terminal * Fix #1998 - Allow lazy PyTerminal bootstrap * Fix #1998 - Allow lazy terminal bootstrap / runtime * Implemented mpy terminal in both main and worker * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/package-lock.json | 162 +++++---- pyscript.core/package.json | 10 +- pyscript.core/src/plugins/py-terminal.js | 335 +++++++++++-------- pyscript.core/test/py-terminal.html | 10 +- pyscript.core/types/plugins/py-terminal.d.ts | 3 +- 5 files changed, 292 insertions(+), 228 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 95eaa1fd0d5..4533ba03f90 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,27 +1,27 @@ { "name": "@pyscript/core", - "version": "0.4.11", + "version": "0.4.12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.11", + "version": "0.4.12", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.11.3", + "polyscript": "^0.12.1", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" }, "devDependencies": { "@codemirror/commands": "^6.3.3", - "@codemirror/lang-python": "^6.1.4", + "@codemirror/lang-python": "^6.1.5", "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.26.0", + "@codemirror/view": "^6.26.1", "@playwright/test": "^1.42.1", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", @@ -31,7 +31,7 @@ "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^8.57.0", - "rollup": "^4.13.1", + "rollup": "^4.13.2", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", @@ -80,9 +80,9 @@ } }, "node_modules/@codemirror/lang-python": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.4.tgz", - "integrity": "sha512-b6d1TDqrkCjFNvMO01SWldFiDoZ39yl3tDMC1Y5f8glA2eZpynPxJhwYVTlGFr0stizcJgrp6ojLEGH2myoZAw==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.5.tgz", + "integrity": "sha512-hCm+8X6wrnXJCGf+QhmFu1AXkdTVG7dHy0Ly6SI1N3SRPptaMvwX6oNQonOXOMPvmcjiB0xq342KAxX3BYpijw==", "dev": true, "dependencies": { "@codemirror/autocomplete": "^6.3.2", @@ -135,9 +135,9 @@ "dev": true }, "node_modules/@codemirror/view": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.0.tgz", - "integrity": "sha512-nSSmzONpqsNzshPOxiKhK203R6BvABepugAe34QfQDbNDslyjkqBuKgrK5ZBvqNXpfxz5iLrlGTmEfhbQyH46A==", + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.1.tgz", + "integrity": "sha512-wLw0t3R9AwOSQThdZ5Onw8QQtem5asE7+bPlnzc57eubPqiuJKIzwjMZ+C42vQett+iva+J8VgFV4RYWDBh5FA==", "dev": true, "dependencies": { "@codemirror/state": "^6.4.0", @@ -472,9 +472,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.1.tgz", - "integrity": "sha512-4C4UERETjXpC4WpBXDbkgNVgHyWfG3B/NKY46e7w5H134UDOFqUJKpsLm0UYmuupW+aJmRgeScrDNfvZ5WV80A==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.2.tgz", + "integrity": "sha512-3XFIDKWMFZrMnao1mJhnOT1h2g0169Os848NhhmGweEcfJ4rCi+3yMCOLG4zA61rbJdkcrM/DjVZm9Hg5p5w7g==", "cpu": [ "arm" ], @@ -485,9 +485,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.1.tgz", - "integrity": "sha512-TrTaFJ9pXgfXEiJKQ3yQRelpQFqgRzVR9it8DbeRzG0RX7mKUy0bqhCFsgevwXLJepQKTnLl95TnPGf9T9AMOA==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.2.tgz", + "integrity": "sha512-GdxxXbAuM7Y/YQM9/TwwP+L0omeE/lJAR1J+olu36c3LqqZEBdsIWeQ91KBe6nxwOnb06Xh7JS2U5ooWU5/LgQ==", "cpu": [ "arm64" ], @@ -498,9 +498,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.1.tgz", - "integrity": "sha512-fz7jN6ahTI3cKzDO2otQuybts5cyu0feymg0bjvYCBrZQ8tSgE8pc0sSNEuGvifrQJWiwx9F05BowihmLxeQKw==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.2.tgz", + "integrity": "sha512-mCMlpzlBgOTdaFs83I4XRr8wNPveJiJX1RLfv4hggyIVhfB5mJfN4P8Z6yKh+oE4Luz+qq1P3kVdWrCKcMYrrA==", "cpu": [ "arm64" ], @@ -511,9 +511,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.1.tgz", - "integrity": "sha512-WTvdz7SLMlJpektdrnWRUN9C0N2qNHwNbWpNo0a3Tod3gb9leX+yrYdCeB7VV36OtoyiPAivl7/xZ3G1z5h20g==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.2.tgz", + "integrity": "sha512-yUoEvnH0FBef/NbB1u6d3HNGyruAKnN74LrPAfDQL3O32e3k3OSfLrPgSJmgb3PJrBZWfPyt6m4ZhAFa2nZp2A==", "cpu": [ "x64" ], @@ -524,9 +524,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.1.tgz", - "integrity": "sha512-dBHQl+7wZzBYcIF6o4k2XkAfwP2ks1mYW2q/Gzv9n39uDcDiAGDqEyml08OdY0BIct0yLSPkDTqn4i6czpBLLw==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.2.tgz", + "integrity": "sha512-GYbLs5ErswU/Xs7aGXqzc3RrdEjKdmoCrgzhJWyFL0r5fL3qd1NPcDKDowDnmcoSiGJeU68/Vy+OMUluRxPiLQ==", "cpu": [ "arm" ], @@ -537,9 +537,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.1.tgz", - "integrity": "sha512-bur4JOxvYxfrAmocRJIW0SADs3QdEYK6TQ7dTNz6Z4/lySeu3Z1H/+tl0a4qDYv0bCdBpUYM0sYa/X+9ZqgfSQ==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.2.tgz", + "integrity": "sha512-L1+D8/wqGnKQIlh4Zre9i4R4b4noxzH5DDciyahX4oOz62CphY7WDWqJoQ66zNR4oScLNOqQJfNSIAe/6TPUmQ==", "cpu": [ "arm64" ], @@ -550,9 +550,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.1.tgz", - "integrity": "sha512-ssp77SjcDIUSoUyj7DU7/5iwM4ZEluY+N8umtCT9nBRs3u045t0KkW02LTyHouHDomnMXaXSZcCSr2bdMK63kA==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.2.tgz", + "integrity": "sha512-tK5eoKFkXdz6vjfkSTCupUzCo40xueTOiOO6PeEIadlNBkadH1wNOH8ILCPIl8by/Gmb5AGAeQOFeLev7iZDOA==", "cpu": [ "arm64" ], @@ -562,10 +562,23 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.13.2.tgz", + "integrity": "sha512-zvXvAUGGEYi6tYhcDmb9wlOckVbuD+7z3mzInCSTACJ4DQrdSLPNUeDIcAQW39M3q6PDquqLWu7pnO39uSMRzQ==", + "cpu": [ + "ppc64le" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.1.tgz", - "integrity": "sha512-Jv1DkIvwEPAb+v25/Unrnnq9BO3F5cbFPT821n3S5litkz+O5NuXuNhqtPx5KtcwOTtaqkTsO+IVzJOsxd11aQ==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.2.tgz", + "integrity": "sha512-C3GSKvMtdudHCN5HdmAMSRYR2kkhgdOfye4w0xzyii7lebVr4riCgmM6lRiSCnJn2w1Xz7ZZzHKuLrjx5620kw==", "cpu": [ "riscv64" ], @@ -576,9 +589,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.13.1.tgz", - "integrity": "sha512-U564BrhEfaNChdATQaEODtquCC7Ez+8Hxz1h5MAdMYj0AqD0GA9rHCpElajb/sQcaFL6NXmHc5O+7FXpWMa73Q==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.13.2.tgz", + "integrity": "sha512-l4U0KDFwzD36j7HdfJ5/TveEQ1fUTjFFQP5qIt9gBqBgu1G8/kCaq5Ok05kd5TG9F8Lltf3MoYsUMw3rNlJ0Yg==", "cpu": [ "s390x" ], @@ -589,9 +602,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.1.tgz", - "integrity": "sha512-zGRDulLTeDemR8DFYyFIQ8kMP02xpUsX4IBikc7lwL9PrwR3gWmX2NopqiGlI2ZVWMl15qZeUjumTwpv18N7sQ==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.2.tgz", + "integrity": "sha512-xXMLUAMzrtsvh3cZ448vbXqlUa7ZL8z0MwHp63K2IIID2+DeP5iWIT6g1SN7hg1VxPzqx0xZdiDM9l4n9LRU1A==", "cpu": [ "x64" ], @@ -602,9 +615,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.1.tgz", - "integrity": "sha512-VTk/MveyPdMFkYJJPCkYBw07KcTkGU2hLEyqYMsU4NjiOfzoaDTW9PWGRsNwiOA3qI0k/JQPjkl/4FCK1smskQ==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.2.tgz", + "integrity": "sha512-M/JYAWickafUijWPai4ehrjzVPKRCyDb1SLuO+ZyPfoXgeCEAlgPkNXewFZx0zcnoIe3ay4UjXIMdXQXOZXWqA==", "cpu": [ "x64" ], @@ -615,9 +628,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.1.tgz", - "integrity": "sha512-L+hX8Dtibb02r/OYCsp4sQQIi3ldZkFI0EUkMTDwRfFykXBPptoz/tuuGqEd3bThBSLRWPR6wsixDSgOx/U3Zw==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.2.tgz", + "integrity": "sha512-2YWwoVg9KRkIKaXSh0mz3NmfurpmYoBBTAXA9qt7VXk0Xy12PoOP40EFuau+ajgALbbhi4uTj3tSG3tVseCjuA==", "cpu": [ "arm64" ], @@ -628,9 +641,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.1.tgz", - "integrity": "sha512-+dI2jVPfM5A8zme8riEoNC7UKk0Lzc7jCj/U89cQIrOjrZTCWZl/+IXUeRT2rEZ5j25lnSA9G9H1Ob9azaF/KQ==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.2.tgz", + "integrity": "sha512-2FSsE9aQ6OWD20E498NYKEQLneShWes0NGMPQwxWOdws35qQXH+FplabOSP5zEe1pVjurSDOGEVCE2agFwSEsw==", "cpu": [ "ia32" ], @@ -641,9 +654,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.1.tgz", - "integrity": "sha512-YY1Exxo2viZ/O2dMHuwQvimJ0SqvL+OAWQLLY6rvXavgQKjhQUzn7nc1Dd29gjB5Fqi00nrBWctJBOyfVMIVxw==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.2.tgz", + "integrity": "sha512-7h7J2nokcdPePdKykd8wtc8QqqkqxIrUz7MHj6aNr8waBRU//NLDVnNjQnqQO6fqtjrtCdftpbTuOKAyrAQETQ==", "cpu": [ "x64" ], @@ -2427,9 +2440,9 @@ } }, "node_modules/polyscript": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.11.3.tgz", - "integrity": "sha512-0wzunsH9b/h+EoB0tZKMRUg0YoFHraRuBuPK+cJsmUmNr1bVM1LvzFk21grDstXjo6Ah78dEC7SjaA0sSBsJeQ==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.1.tgz", + "integrity": "sha512-fQtpelwephyl34UMHxPwKNpGkUDbAIEMa09EFLthBpvThRSmrNQrus/WuouGKjqedK5dv+qCwP5RU1Lbe1bQLA==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", @@ -3149,9 +3162,9 @@ } }, "node_modules/rollup": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.1.tgz", - "integrity": "sha512-hFi+fU132IvJ2ZuihN56dwgpltpmLZHZWsx27rMCTZ2sYwrqlgL5sECGy1eeV2lAihD8EzChBVVhsXci0wD4Tg==", + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.2.tgz", + "integrity": "sha512-MIlLgsdMprDBXC+4hsPgzWUasLO9CE4zOkj/u6j+Z6j5A4zRY+CtiXAdJyPtgCsc42g658Aeh1DlrdVEJhsL2g==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -3164,20 +3177,21 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.13.1", - "@rollup/rollup-android-arm64": "4.13.1", - "@rollup/rollup-darwin-arm64": "4.13.1", - "@rollup/rollup-darwin-x64": "4.13.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.13.1", - "@rollup/rollup-linux-arm64-gnu": "4.13.1", - "@rollup/rollup-linux-arm64-musl": "4.13.1", - "@rollup/rollup-linux-riscv64-gnu": "4.13.1", - "@rollup/rollup-linux-s390x-gnu": "4.13.1", - "@rollup/rollup-linux-x64-gnu": "4.13.1", - "@rollup/rollup-linux-x64-musl": "4.13.1", - "@rollup/rollup-win32-arm64-msvc": "4.13.1", - "@rollup/rollup-win32-ia32-msvc": "4.13.1", - "@rollup/rollup-win32-x64-msvc": "4.13.1", + "@rollup/rollup-android-arm-eabi": "4.13.2", + "@rollup/rollup-android-arm64": "4.13.2", + "@rollup/rollup-darwin-arm64": "4.13.2", + "@rollup/rollup-darwin-x64": "4.13.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.13.2", + "@rollup/rollup-linux-arm64-gnu": "4.13.2", + "@rollup/rollup-linux-arm64-musl": "4.13.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.13.2", + "@rollup/rollup-linux-riscv64-gnu": "4.13.2", + "@rollup/rollup-linux-s390x-gnu": "4.13.2", + "@rollup/rollup-linux-x64-gnu": "4.13.2", + "@rollup/rollup-linux-x64-musl": "4.13.2", + "@rollup/rollup-win32-arm64-msvc": "4.13.2", + "@rollup/rollup-win32-ia32-msvc": "4.13.2", + "@rollup/rollup-win32-x64-msvc": "4.13.2", "fsevents": "~2.3.2" } }, diff --git a/pyscript.core/package.json b/pyscript.core/package.json index f7b04a6de66..0b1e7fc860f 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.11", + "version": "0.4.12", "type": "module", "description": "PyScript", "module": "./index.js", @@ -42,17 +42,17 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.11.3", + "polyscript": "^0.12.1", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" }, "devDependencies": { "@codemirror/commands": "^6.3.3", - "@codemirror/lang-python": "^6.1.4", + "@codemirror/lang-python": "^6.1.5", "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.26.0", + "@codemirror/view": "^6.26.1", "@playwright/test": "^1.42.1", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", @@ -62,7 +62,7 @@ "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^8.57.0", - "rollup": "^4.13.1", + "rollup": "^4.13.2", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", diff --git a/pyscript.core/src/plugins/py-terminal.js b/pyscript.core/src/plugins/py-terminal.js index bd66156bf22..83301d0d92b 100644 --- a/pyscript.core/src/plugins/py-terminal.js +++ b/pyscript.core/src/plugins/py-terminal.js @@ -1,11 +1,10 @@ // PyScript py-terminal plugin import { TYPES, hooks } from "../core.js"; import { notify } from "./error.js"; -import { defineProperty } from "polyscript/exports"; +import { customObserver, defineProperty } from "polyscript/exports"; -const SELECTOR = [...TYPES.keys()] - .map((type) => `script[type="${type}"][terminal],${type}-script[terminal]`) - .join(","); +// will contain all valid selectors +const SELECTORS = []; // show the error on main and // stops the module from keep executing @@ -14,8 +13,6 @@ const notifyAndThrow = (message) => { throw new Error(message); }; -const notParsedYet = (script) => !bootstrapped.has(script); - const onceOnMain = ({ attributes: { worker } }) => !worker; const bootstrapped = new WeakSet(); @@ -25,11 +22,68 @@ let addStyle = true; // this callback will be serialized as string and it never needs // to be invoked multiple times. Each xworker here is bootstrapped // only once thanks to the `sync.is_pyterminal()` check. -const workerReady = ({ interpreter, io, run }, { sync }) => { +const workerReady = ({ interpreter, io, run, type }, { sync }) => { if (!sync.is_pyterminal()) return; // in workers it's always safe to grab the polyscript currentScript - run("from polyscript.currentScript import terminal as __terminal__"); + // the ugly `_` dance is due MicroPython not able to import via: + // `from polyscript.currentScript import terminal as __terminal__` + run( + "from polyscript import currentScript as _; __terminal__ = _.terminal; del _", + ); + + // This part is shared among both Pyodide and MicroPython + io.stderr = (error) => { + sync.pyterminal_write(`${error.message || error}\n`); + }; + + const isMicroPython = type === "mpy"; + + // MicroPython has no code or code.interact() + // This part patches it in a way that simulate + // the code.interact() module in Pyodide. + if (isMicroPython) { + const encoder = new TextEncoder(); + const processData = () => { + if (data.length) { + for ( + let i = 0, b = encoder.encode(`${data}\r`); + i < b.length; + i++ + ) { + const code = interpreter.replProcessChar(b[i]); + if (code) { + throw new Error( + `replProcessChar failed with code ${code}`, + ); + } + } + } + data = ">>> "; + data = io.stdin(); + processData(); + }; + interpreter.setStderr = Object; // as no-op + interpreter.setStdout = ({ write }) => { + io.stdout = (str) => { + // avoid duplicated outcome due i/o + readline + const ignore = str.startsWith(`>>> ${data}`); + return ignore ? 0 : write(`${str}\n`); + }; + }; + interpreter.setStdin = ({ stdin }) => { + io.stdin = stdin; + }; + // tiny shim of the code module with only interact + // to bootstrap a REPL like environment + interpreter.registerJsModule("code", { + interact() { + interpreter.replInit(); + data = ""; + processData(); + }, + }); + } // This part is inevitably duplicated as external scope // can't be reached by workers out of the box. @@ -39,7 +93,7 @@ const workerReady = ({ interpreter, io, run }, { sync }) => { const generic = { isatty: true, write(buffer) { - data = decoder.decode(buffer); + data = isMicroPython ? buffer : decoder.decode(buffer); sync.pyterminal_write(data); return buffer.length; }, @@ -50,38 +104,9 @@ const workerReady = ({ interpreter, io, run }, { sync }) => { isatty: true, stdin: () => sync.pyterminal_read(data), }); - - io.stderr = (error) => { - sync.pyterminal_write(`${error.message || error}\n`); - }; }; -const pyTerminal = async () => { - const terminals = document.querySelectorAll(SELECTOR); - - const unknown = [].filter.call(terminals, notParsedYet); - - // no results will look further for runtime nodes - if (!unknown.length) return; - // early flag elements as known to avoid concurrent - // MutationObserver invokes of this async handler - else unknown.forEach(bootstrapped.add, bootstrapped); - - // we currently support only one terminal as in "classic" - if ([].filter.call(terminals, onceOnMain).length > 1) - notifyAndThrow("You can use at most 1 main terminal"); - - // import styles lazily - if (addStyle) { - addStyle = false; - document.head.append( - Object.assign(document.createElement("link"), { - rel: "stylesheet", - href: new URL("./xterm.css", import.meta.url), - }), - ); - } - +const pyTerminal = async (element) => { // lazy load these only when a valid terminal is found const [{ Terminal }, { Readline }, { FitAddon }] = await Promise.all([ import(/* webpackIgnore: true */ "../3rd-party/xterm.js"), @@ -89,118 +114,140 @@ const pyTerminal = async () => { import(/* webpackIgnore: true */ "../3rd-party/xterm_addon-fit.js"), ]); - for (const element of unknown) { - // hopefully to be removed in the near future! - if (element.matches('script[type="mpy"],mpy-script')) - notifyAndThrow("Unsupported terminal."); - - const readline = new Readline(); - - // common main thread initialization for both worker - // or main case, bootstrapping the terminal on its target - const init = (options) => { - let target = element; - const selector = element.getAttribute("target"); - if (selector) { - target = - document.getElementById(selector) || - document.querySelector(selector); - if (!target) throw new Error(`Unknown target ${selector}`); - } else { - target = document.createElement("py-terminal"); - target.style.display = "block"; - element.after(target); - } - const terminal = new Terminal({ - theme: { - background: "#191A19", - foreground: "#F5F2E7", - }, - ...options, + const readline = new Readline(); + + // common main thread initialization for both worker + // or main case, bootstrapping the terminal on its target + const init = (options) => { + let target = element; + const selector = element.getAttribute("target"); + if (selector) { + target = + document.getElementById(selector) || + document.querySelector(selector); + if (!target) throw new Error(`Unknown target ${selector}`); + } else { + target = document.createElement("py-terminal"); + target.style.display = "block"; + element.after(target); + } + const terminal = new Terminal({ + theme: { + background: "#191A19", + foreground: "#F5F2E7", + }, + ...options, + }); + const fitAddon = new FitAddon(); + terminal.loadAddon(fitAddon); + terminal.loadAddon(readline); + terminal.open(target); + fitAddon.fit(); + terminal.focus(); + defineProperty(element, "terminal", { value: terminal }); + return terminal; + }; + + // branch logic for the worker + if (element.hasAttribute("worker")) { + // add a hook on the main thread to setup all sync helpers + // also bootstrapping the XTerm target on main *BUT* ... + hooks.main.onWorker.add(function worker(_, xworker) { + // ... as multiple workers will add multiple callbacks + // be sure no xworker is ever initialized twice! + if (bootstrapped.has(xworker)) return; + bootstrapped.add(xworker); + + // still cleanup this callback for future scripts/workers + hooks.main.onWorker.delete(worker); + + init({ + disableStdin: false, + cursorBlink: true, + cursorStyle: "block", }); - const fitAddon = new FitAddon(); - terminal.loadAddon(fitAddon); - terminal.loadAddon(readline); - terminal.open(target); - fitAddon.fit(); - terminal.focus(); - defineProperty(element, "terminal", { value: terminal }); - return terminal; - }; - // branch logic for the worker - if (element.hasAttribute("worker")) { - // add a hook on the main thread to setup all sync helpers - // also bootstrapping the XTerm target on main *BUT* ... - hooks.main.onWorker.add(function worker(_, xworker) { - // ... as multiple workers will add multiple callbacks - // be sure no xworker is ever initialized twice! - if (bootstrapped.has(xworker)) return; - bootstrapped.add(xworker); - - // still cleanup this callback for future scripts/workers - hooks.main.onWorker.delete(worker); - - init({ - disableStdin: false, - cursorBlink: true, - cursorStyle: "block", - }); - - xworker.sync.is_pyterminal = () => true; - xworker.sync.pyterminal_read = readline.read.bind(readline); - xworker.sync.pyterminal_write = readline.write.bind(readline); + xworker.sync.is_pyterminal = () => true; + xworker.sync.pyterminal_read = readline.read.bind(readline); + xworker.sync.pyterminal_write = readline.write.bind(readline); + }); + + // setup remote thread JS/Python code for whenever the + // worker is ready to become a terminal + hooks.worker.onReady.add(workerReady); + } else { + // in the main case, just bootstrap XTerm without + // allowing any input as that's not possible / awkward + hooks.main.onReady.add(function main({ interpreter, io, run, type }) { + console.warn("py-terminal is read only on main thread"); + hooks.main.onReady.delete(main); + + // on main, it's easy to trash and clean the current terminal + globalThis.__py_terminal__ = init({ + disableStdin: true, + cursorBlink: false, + cursorStyle: "underline", }); + run("from js import __py_terminal__ as __terminal__"); + delete globalThis.__py_terminal__; - // setup remote thread JS/Python code for whenever the - // worker is ready to become a terminal - hooks.worker.onReady.add(workerReady); - } else { - // in the main case, just bootstrap XTerm without - // allowing any input as that's not possible / awkward - hooks.main.onReady.add(function main({ interpreter, io, run }) { - console.warn("py-terminal is read only on main thread"); - hooks.main.onReady.delete(main); - - // on main, it's easy to trash and clean the current terminal - globalThis.__py_terminal__ = init({ - disableStdin: true, - cursorBlink: false, - cursorStyle: "underline", - }); - run("from js import __py_terminal__ as __terminal__"); - delete globalThis.__py_terminal__; - - // This part is inevitably duplicated as external scope - // can't be reached by workers out of the box. - // The detail is that here we use readline here, not sync. - const decoder = new TextDecoder(); - let data = ""; - const generic = { - isatty: true, - write(buffer) { - data = decoder.decode(buffer); - readline.write(data); - return buffer.length; - }, - }; - interpreter.setStdout(generic); - interpreter.setStderr(generic); - interpreter.setStdin({ - isatty: true, - stdin: () => readline.read(data), - }); - - io.stderr = (error) => { - readline.write(`${error.message || error}\n`); + io.stderr = (error) => { + readline.write(`${error.message || error}\n`); + }; + + const isMicroPython = type === "mpy"; + + if (isMicroPython) { + interpreter.setStderr = Object; // as no-op + interpreter.setStdin = Object; // as no-op + interpreter.setStdout = ({ write }) => { + io.stdout = (str) => write(`${str}\n`); }; + } + + // This part is inevitably duplicated as external scope + // can't be reached by workers out of the box. + // The detail is that here we use readline here, not sync. + const decoder = new TextDecoder(); + let data = ""; + const generic = { + isatty: true, + write(buffer) { + data = isMicroPython ? buffer : decoder.decode(buffer); + readline.write(data); + return buffer.length; + }, + }; + interpreter.setStdout(generic); + interpreter.setStderr(generic); + interpreter.setStdin({ + isatty: true, + stdin: () => readline.read(data), }); - } + }); } }; -const mo = new MutationObserver(pyTerminal); -mo.observe(document, { childList: true, subtree: true }); +for (const key of TYPES.keys()) { + const selector = `script[type="${key}"][terminal],${key}-script[terminal]`; + SELECTORS.push(selector); + customObserver.set(selector, async (element) => { + // we currently support only one terminal on main as in "classic" + const terminals = document.querySelectorAll(SELECTORS.join(",")); + if ([].filter.call(terminals, onceOnMain).length > 1) + notifyAndThrow("You can use at most 1 main terminal"); + + // import styles lazily + if (addStyle) { + addStyle = false; + document.head.append( + Object.assign(document.createElement("link"), { + rel: "stylesheet", + href: new URL("./xterm.css", import.meta.url), + }), + ); + } -// try to check the current document ASAP -export default pyTerminal(); + await pyTerminal(element); + }); +} diff --git a/pyscript.core/test/py-terminal.html b/pyscript.core/test/py-terminal.html index ebf7f04de3a..d917be111e5 100644 --- a/pyscript.core/test/py-terminal.html +++ b/pyscript.core/test/py-terminal.html @@ -13,7 +13,7 @@ def greetings(event): print('hello world') - + diff --git a/pyscript.core/types/plugins/py-terminal.d.ts b/pyscript.core/types/plugins/py-terminal.d.ts index 35a35db464a..cb0ff5c3b54 100644 --- a/pyscript.core/types/plugins/py-terminal.d.ts +++ b/pyscript.core/types/plugins/py-terminal.d.ts @@ -1,2 +1 @@ -declare const _default: Promise; -export default _default; +export {}; From 239add4e20684201fa495ec2fce1cd62f0c10b6a Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Thu, 4 Apr 2024 15:33:41 +0200 Subject: [PATCH 027/179] Better MicroPython Terminal (#2014) * Better MicroPython Terminal + fixed Pyodide astty value --- pyscript.core/package-lock.json | 140 +++++++++++------------ pyscript.core/package.json | 6 +- pyscript.core/src/plugins/py-terminal.js | 122 ++++++++------------ pyscript.core/test/py-terminal.html | 19 --- 4 files changed, 123 insertions(+), 164 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 4533ba03f90..d727c25d03d 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.4.12", + "version": "0.4.13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.12", + "version": "0.4.13", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.1", + "polyscript": "^0.12.2", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -31,7 +31,7 @@ "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^8.57.0", - "rollup": "^4.13.2", + "rollup": "^4.14.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", @@ -472,9 +472,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.2.tgz", - "integrity": "sha512-3XFIDKWMFZrMnao1mJhnOT1h2g0169Os848NhhmGweEcfJ4rCi+3yMCOLG4zA61rbJdkcrM/DjVZm9Hg5p5w7g==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.0.tgz", + "integrity": "sha512-jwXtxYbRt1V+CdQSy6Z+uZti7JF5irRKF8hlKfEnF/xJpcNGuuiZMBvuoYM+x9sr9iWGnzrlM0+9hvQ1kgkf1w==", "cpu": [ "arm" ], @@ -485,9 +485,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.2.tgz", - "integrity": "sha512-GdxxXbAuM7Y/YQM9/TwwP+L0omeE/lJAR1J+olu36c3LqqZEBdsIWeQ91KBe6nxwOnb06Xh7JS2U5ooWU5/LgQ==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.0.tgz", + "integrity": "sha512-fI9nduZhCccjzlsA/OuAwtFGWocxA4gqXGTLvOyiF8d+8o0fZUeSztixkYjcGq1fGZY3Tkq4yRvHPFxU+jdZ9Q==", "cpu": [ "arm64" ], @@ -498,9 +498,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.2.tgz", - "integrity": "sha512-mCMlpzlBgOTdaFs83I4XRr8wNPveJiJX1RLfv4hggyIVhfB5mJfN4P8Z6yKh+oE4Luz+qq1P3kVdWrCKcMYrrA==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.0.tgz", + "integrity": "sha512-BcnSPRM76/cD2gQC+rQNGBN6GStBs2pl/FpweW8JYuz5J/IEa0Fr4AtrPv766DB/6b2MZ/AfSIOSGw3nEIP8SA==", "cpu": [ "arm64" ], @@ -511,9 +511,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.2.tgz", - "integrity": "sha512-yUoEvnH0FBef/NbB1u6d3HNGyruAKnN74LrPAfDQL3O32e3k3OSfLrPgSJmgb3PJrBZWfPyt6m4ZhAFa2nZp2A==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.0.tgz", + "integrity": "sha512-LDyFB9GRolGN7XI6955aFeI3wCdCUszFWumWU0deHA8VpR3nWRrjG6GtGjBrQxQKFevnUTHKCfPR4IvrW3kCgQ==", "cpu": [ "x64" ], @@ -524,9 +524,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.2.tgz", - "integrity": "sha512-GYbLs5ErswU/Xs7aGXqzc3RrdEjKdmoCrgzhJWyFL0r5fL3qd1NPcDKDowDnmcoSiGJeU68/Vy+OMUluRxPiLQ==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.0.tgz", + "integrity": "sha512-ygrGVhQP47mRh0AAD0zl6QqCbNsf0eTo+vgwkY6LunBcg0f2Jv365GXlDUECIyoXp1kKwL5WW6rsO429DBY/bA==", "cpu": [ "arm" ], @@ -537,9 +537,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.2.tgz", - "integrity": "sha512-L1+D8/wqGnKQIlh4Zre9i4R4b4noxzH5DDciyahX4oOz62CphY7WDWqJoQ66zNR4oScLNOqQJfNSIAe/6TPUmQ==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.0.tgz", + "integrity": "sha512-x+uJ6MAYRlHGe9wi4HQjxpaKHPM3d3JjqqCkeC5gpnnI6OWovLdXTpfa8trjxPLnWKyBsSi5kne+146GAxFt4A==", "cpu": [ "arm64" ], @@ -550,9 +550,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.2.tgz", - "integrity": "sha512-tK5eoKFkXdz6vjfkSTCupUzCo40xueTOiOO6PeEIadlNBkadH1wNOH8ILCPIl8by/Gmb5AGAeQOFeLev7iZDOA==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.0.tgz", + "integrity": "sha512-nrRw8ZTQKg6+Lttwqo6a2VxR9tOroa2m91XbdQ2sUUzHoedXlsyvY1fN4xWdqz8PKmf4orDwejxXHjh7YBGUCA==", "cpu": [ "arm64" ], @@ -563,9 +563,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.13.2.tgz", - "integrity": "sha512-zvXvAUGGEYi6tYhcDmb9wlOckVbuD+7z3mzInCSTACJ4DQrdSLPNUeDIcAQW39M3q6PDquqLWu7pnO39uSMRzQ==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.0.tgz", + "integrity": "sha512-xV0d5jDb4aFu84XKr+lcUJ9y3qpIWhttO3Qev97z8DKLXR62LC3cXT/bMZXrjLF9X+P5oSmJTzAhqwUbY96PnA==", "cpu": [ "ppc64le" ], @@ -576,9 +576,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.2.tgz", - "integrity": "sha512-C3GSKvMtdudHCN5HdmAMSRYR2kkhgdOfye4w0xzyii7lebVr4riCgmM6lRiSCnJn2w1Xz7ZZzHKuLrjx5620kw==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.0.tgz", + "integrity": "sha512-SDDhBQwZX6LPRoPYjAZWyL27LbcBo7WdBFWJi5PI9RPCzU8ijzkQn7tt8NXiXRiFMJCVpkuMkBf4OxSxVMizAw==", "cpu": [ "riscv64" ], @@ -589,9 +589,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.13.2.tgz", - "integrity": "sha512-l4U0KDFwzD36j7HdfJ5/TveEQ1fUTjFFQP5qIt9gBqBgu1G8/kCaq5Ok05kd5TG9F8Lltf3MoYsUMw3rNlJ0Yg==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.0.tgz", + "integrity": "sha512-RxB/qez8zIDshNJDufYlTT0ZTVut5eCpAZ3bdXDU9yTxBzui3KhbGjROK2OYTTor7alM7XBhssgoO3CZ0XD3qA==", "cpu": [ "s390x" ], @@ -602,9 +602,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.2.tgz", - "integrity": "sha512-xXMLUAMzrtsvh3cZ448vbXqlUa7ZL8z0MwHp63K2IIID2+DeP5iWIT6g1SN7hg1VxPzqx0xZdiDM9l4n9LRU1A==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.0.tgz", + "integrity": "sha512-C6y6z2eCNCfhZxT9u+jAM2Fup89ZjiG5pIzZIDycs1IwESviLxwkQcFRGLjnDrP+PT+v5i4YFvlcfAs+LnreXg==", "cpu": [ "x64" ], @@ -615,9 +615,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.2.tgz", - "integrity": "sha512-M/JYAWickafUijWPai4ehrjzVPKRCyDb1SLuO+ZyPfoXgeCEAlgPkNXewFZx0zcnoIe3ay4UjXIMdXQXOZXWqA==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.0.tgz", + "integrity": "sha512-i0QwbHYfnOMYsBEyjxcwGu5SMIi9sImDVjDg087hpzXqhBSosxkE7gyIYFHgfFl4mr7RrXksIBZ4DoLoP4FhJg==", "cpu": [ "x64" ], @@ -628,9 +628,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.2.tgz", - "integrity": "sha512-2YWwoVg9KRkIKaXSh0mz3NmfurpmYoBBTAXA9qt7VXk0Xy12PoOP40EFuau+ajgALbbhi4uTj3tSG3tVseCjuA==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.0.tgz", + "integrity": "sha512-Fq52EYb0riNHLBTAcL0cun+rRwyZ10S9vKzhGKKgeD+XbwunszSY0rVMco5KbOsTlwovP2rTOkiII/fQ4ih/zQ==", "cpu": [ "arm64" ], @@ -641,9 +641,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.2.tgz", - "integrity": "sha512-2FSsE9aQ6OWD20E498NYKEQLneShWes0NGMPQwxWOdws35qQXH+FplabOSP5zEe1pVjurSDOGEVCE2agFwSEsw==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.0.tgz", + "integrity": "sha512-e/PBHxPdJ00O9p5Ui43+vixSgVf4NlLsmV6QneGERJ3lnjIua/kim6PRFe3iDueT1rQcgSkYP8ZBBXa/h4iPvw==", "cpu": [ "ia32" ], @@ -654,9 +654,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.2.tgz", - "integrity": "sha512-7h7J2nokcdPePdKykd8wtc8QqqkqxIrUz7MHj6aNr8waBRU//NLDVnNjQnqQO6fqtjrtCdftpbTuOKAyrAQETQ==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.0.tgz", + "integrity": "sha512-aGg7iToJjdklmxlUlJh/PaPNa4PmqHfyRMLunbL3eaMO0gp656+q1zOKkpJ/CVe9CryJv6tAN1HDoR8cNGzkag==", "cpu": [ "x64" ], @@ -2440,9 +2440,9 @@ } }, "node_modules/polyscript": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.1.tgz", - "integrity": "sha512-fQtpelwephyl34UMHxPwKNpGkUDbAIEMa09EFLthBpvThRSmrNQrus/WuouGKjqedK5dv+qCwP5RU1Lbe1bQLA==", + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.2.tgz", + "integrity": "sha512-qHZbcSVhp4bDW9YjcPyYw2AWDRrBEDUVxKMuvjACjQK7O891H6x7dNKVYNjij75Ygn9akma+X1n6eTW4syBFmQ==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", @@ -3162,9 +3162,9 @@ } }, "node_modules/rollup": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.2.tgz", - "integrity": "sha512-MIlLgsdMprDBXC+4hsPgzWUasLO9CE4zOkj/u6j+Z6j5A4zRY+CtiXAdJyPtgCsc42g658Aeh1DlrdVEJhsL2g==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.0.tgz", + "integrity": "sha512-Qe7w62TyawbDzB4yt32R0+AbIo6m1/sqO7UPzFS8Z/ksL5mrfhA0v4CavfdmFav3D+ub4QeAgsGEe84DoWe/nQ==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -3177,21 +3177,21 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.13.2", - "@rollup/rollup-android-arm64": "4.13.2", - "@rollup/rollup-darwin-arm64": "4.13.2", - "@rollup/rollup-darwin-x64": "4.13.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.13.2", - "@rollup/rollup-linux-arm64-gnu": "4.13.2", - "@rollup/rollup-linux-arm64-musl": "4.13.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.13.2", - "@rollup/rollup-linux-riscv64-gnu": "4.13.2", - "@rollup/rollup-linux-s390x-gnu": "4.13.2", - "@rollup/rollup-linux-x64-gnu": "4.13.2", - "@rollup/rollup-linux-x64-musl": "4.13.2", - "@rollup/rollup-win32-arm64-msvc": "4.13.2", - "@rollup/rollup-win32-ia32-msvc": "4.13.2", - "@rollup/rollup-win32-x64-msvc": "4.13.2", + "@rollup/rollup-android-arm-eabi": "4.14.0", + "@rollup/rollup-android-arm64": "4.14.0", + "@rollup/rollup-darwin-arm64": "4.14.0", + "@rollup/rollup-darwin-x64": "4.14.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.14.0", + "@rollup/rollup-linux-arm64-gnu": "4.14.0", + "@rollup/rollup-linux-arm64-musl": "4.14.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.14.0", + "@rollup/rollup-linux-riscv64-gnu": "4.14.0", + "@rollup/rollup-linux-s390x-gnu": "4.14.0", + "@rollup/rollup-linux-x64-gnu": "4.14.0", + "@rollup/rollup-linux-x64-musl": "4.14.0", + "@rollup/rollup-win32-arm64-msvc": "4.14.0", + "@rollup/rollup-win32-ia32-msvc": "4.14.0", + "@rollup/rollup-win32-x64-msvc": "4.14.0", "fsevents": "~2.3.2" } }, diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 0b1e7fc860f..70b4174f8f7 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.12", + "version": "0.4.13", "type": "module", "description": "PyScript", "module": "./index.js", @@ -42,7 +42,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.1", + "polyscript": "^0.12.2", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -62,7 +62,7 @@ "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^8.57.0", - "rollup": "^4.13.2", + "rollup": "^4.14.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", diff --git a/pyscript.core/src/plugins/py-terminal.js b/pyscript.core/src/plugins/py-terminal.js index 83301d0d92b..10d17c9b7bb 100644 --- a/pyscript.core/src/plugins/py-terminal.js +++ b/pyscript.core/src/plugins/py-terminal.js @@ -32,78 +32,61 @@ const workerReady = ({ interpreter, io, run, type }, { sync }) => { "from polyscript import currentScript as _; __terminal__ = _.terminal; del _", ); - // This part is shared among both Pyodide and MicroPython - io.stderr = (error) => { - sync.pyterminal_write(`${error.message || error}\n`); + let data = ""; + const { pyterminal_read, pyterminal_write } = sync; + const decoder = new TextDecoder(); + const generic = { + isatty: false, + write(buffer) { + data = decoder.decode(buffer); + pyterminal_write(data); + return buffer.length; + }, }; - const isMicroPython = type === "mpy"; + // This part works already in both Pyodide and MicroPython + io.stderr = (error) => { + pyterminal_write(String(error.message || error)); + }; // MicroPython has no code or code.interact() - // This part patches it in a way that simulate + // This part patches it in a way that simulates // the code.interact() module in Pyodide. - if (isMicroPython) { - const encoder = new TextEncoder(); - const processData = () => { - if (data.length) { - for ( - let i = 0, b = encoder.encode(`${data}\r`); - i < b.length; - i++ - ) { - const code = interpreter.replProcessChar(b[i]); - if (code) { - throw new Error( - `replProcessChar failed with code ${code}`, - ); - } - } - } - data = ">>> "; - data = io.stdin(); - processData(); - }; - interpreter.setStderr = Object; // as no-op - interpreter.setStdout = ({ write }) => { - io.stdout = (str) => { - // avoid duplicated outcome due i/o + readline - const ignore = str.startsWith(`>>> ${data}`); - return ignore ? 0 : write(`${str}\n`); - }; - }; - interpreter.setStdin = ({ stdin }) => { - io.stdin = stdin; - }; + if (type === "mpy") { + io.stdout = generic.write; // tiny shim of the code module with only interact // to bootstrap a REPL like environment interpreter.registerJsModule("code", { interact() { + const encoder = new TextEncoder(); + const acc = []; + let input = ""; + let length = 1; + io.stdout = ([c]) => { + // avoid duplicating the output produced by the input + if (length++ > input.length) acc.push(c); + }; interpreter.replInit(); - data = ""; - processData(); + (function repl() { + const out = decoder.decode(new Uint8Array(acc.splice(0))); + pyterminal_write(out); + // print in current line only the last line produced by the REPL + data = out.split("\n").at(-1); + input = encoder.encode(`${pyterminal_read(data)}\r`); + length = 0; + for (const c of input) interpreter.replProcessChar(c); + repl(); + })(); }, }); + } else { + interpreter.setStdout(generic); + interpreter.setStderr(generic); + interpreter.setStdin({ + isatty: false, + stdin: () => pyterminal_read(data), + }); } - - // This part is inevitably duplicated as external scope - // can't be reached by workers out of the box. - // The detail is that here we use sync though, not readline. - const decoder = new TextDecoder(); - let data = ""; - const generic = { - isatty: true, - write(buffer) { - data = isMicroPython ? buffer : decoder.decode(buffer); - sync.pyterminal_write(data); - return buffer.length; - }, - }; - interpreter.setStdout(generic); - interpreter.setStderr(generic); - interpreter.setStdin({ - isatty: true, - stdin: () => sync.pyterminal_read(data), - }); }; const pyTerminal = async (element) => { @@ -192,28 +175,23 @@ const pyTerminal = async (element) => { delete globalThis.__py_terminal__; io.stderr = (error) => { - readline.write(`${error.message || error}\n`); + readline.write(String(error.message || error)); }; - const isMicroPython = type === "mpy"; - - if (isMicroPython) { - interpreter.setStderr = Object; // as no-op + if (type === "mpy") { interpreter.setStdin = Object; // as no-op + interpreter.setStderr = Object; // as no-op interpreter.setStdout = ({ write }) => { - io.stdout = (str) => write(`${str}\n`); + io.stdout = write; }; } - // This part is inevitably duplicated as external scope - // can't be reached by workers out of the box. - // The detail is that here we use readline here, not sync. - const decoder = new TextDecoder(); let data = ""; + const decoder = new TextDecoder(); const generic = { - isatty: true, + isatty: false, write(buffer) { - data = isMicroPython ? buffer : decoder.decode(buffer); + data = decoder.decode(buffer); readline.write(data); return buffer.length; }, @@ -221,7 +199,7 @@ const pyTerminal = async (element) => { interpreter.setStdout(generic); interpreter.setStderr(generic); interpreter.setStdin({ - isatty: true, + isatty: false, stdin: () => readline.read(data), }); }); diff --git a/pyscript.core/test/py-terminal.html b/pyscript.core/test/py-terminal.html index d917be111e5..1ce3192855c 100644 --- a/pyscript.core/test/py-terminal.html +++ b/pyscript.core/test/py-terminal.html @@ -9,28 +9,9 @@ - - From 1fb6cddd70a20088acfaf85831e7dbfec477c000 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Thu, 4 Apr 2024 15:53:52 +0200 Subject: [PATCH 028/179] Forgot to update current npm version (#2015) --- pyscript.core/package-lock.json | 4 ++-- pyscript.core/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index d727c25d03d..dae15627491 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.13", + "version": "0.4.14", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.13", + "version": "0.4.14", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 70b4174f8f7..f7e05f71166 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.13", + "version": "0.4.14", "type": "module", "description": "PyScript", "module": "./index.js", From 2f1b7642516b154b991619011dd6d7f25d30d017 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Thu, 4 Apr 2024 17:34:12 +0200 Subject: [PATCH 029/179] Provide input("") and sync output to MicroPython (#2016) Provide input("") and sync output to MicroPython --- pyscript.core/package-lock.json | 4 ++-- pyscript.core/package.json | 2 +- pyscript.core/src/plugins/py-terminal.js | 27 ++++++++++++++++++------ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index dae15627491..0b08af121df 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.14", + "version": "0.4.15", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.14", + "version": "0.4.15", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index f7e05f71166..e30ecec099b 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.14", + "version": "0.4.15", "type": "module", "description": "PyScript", "module": "./index.js", diff --git a/pyscript.core/src/plugins/py-terminal.js b/pyscript.core/src/plugins/py-terminal.js index 10d17c9b7bb..0a9a4725cdf 100644 --- a/pyscript.core/src/plugins/py-terminal.js +++ b/pyscript.core/src/plugins/py-terminal.js @@ -58,22 +58,35 @@ const workerReady = ({ interpreter, io, run, type }, { sync }) => { // to bootstrap a REPL like environment interpreter.registerJsModule("code", { interact() { - const encoder = new TextEncoder(); - const acc = []; let input = ""; let length = 1; - io.stdout = ([c]) => { + + const encoder = new TextEncoder(); + const acc = []; + + io.stdout = (buffer) => { // avoid duplicating the output produced by the input - if (length++ > input.length) acc.push(c); + if (length++ > input.length) { + acc.push(...buffer); + pyterminal_write(decoder.decode(buffer)); + } }; + interpreter.replInit(); + + // monkey patch global input otherwise broken in MicroPython + interpreter.registerJsModule("_pyscript_input", { + input: pyterminal_read, + }); + run("from _pyscript_input import input"); + + // loop forever waiting for user inputs (function repl() { const out = decoder.decode(new Uint8Array(acc.splice(0))); - pyterminal_write(out); // print in current line only the last line produced by the REPL - data = out.split("\n").at(-1); - input = encoder.encode(`${pyterminal_read(data)}\r`); + const data = `${pyterminal_read(out.split("\n").at(-1))}\r`; length = 0; + input = encoder.encode(data); for (const c of input) interpreter.replProcessChar(c); repl(); })(); From 65954a627e8c070ed6c82cd33232b99795b80993 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Thu, 4 Apr 2024 18:13:00 +0200 Subject: [PATCH 030/179] Allow MicroPython input("...") to work beside the code.interact() (#2017) --- pyscript.core/package-lock.json | 4 ++-- pyscript.core/package.json | 2 +- pyscript.core/src/plugins/py-terminal.js | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 0b08af121df..20cb8ba7f5b 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.15", + "version": "0.4.16", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.15", + "version": "0.4.16", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index e30ecec099b..5b7fa33388d 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.15", + "version": "0.4.16", "type": "module", "description": "PyScript", "module": "./index.js", diff --git a/pyscript.core/src/plugins/py-terminal.js b/pyscript.core/src/plugins/py-terminal.js index 0a9a4725cdf..925fc1f9957 100644 --- a/pyscript.core/src/plugins/py-terminal.js +++ b/pyscript.core/src/plugins/py-terminal.js @@ -53,6 +53,12 @@ const workerReady = ({ interpreter, io, run, type }, { sync }) => { // This part patches it in a way that simulates // the code.interact() module in Pyodide. if (type === "mpy") { + // monkey patch global input otherwise broken in MicroPython + interpreter.registerJsModule("_pyscript_input", { + input: pyterminal_read, + }); + run("from _pyscript_input import input"); + io.stdout = generic.write; // tiny shim of the code module with only interact // to bootstrap a REPL like environment @@ -74,12 +80,6 @@ const workerReady = ({ interpreter, io, run, type }, { sync }) => { interpreter.replInit(); - // monkey patch global input otherwise broken in MicroPython - interpreter.registerJsModule("_pyscript_input", { - input: pyterminal_read, - }); - run("from _pyscript_input import input"); - // loop forever waiting for user inputs (function repl() { const out = decoder.decode(new Uint8Array(acc.splice(0))); From 6d4572878768aacb703cc0b35b05e3e2d73bc165 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 10:40:53 +0200 Subject: [PATCH 031/179] Bump dorny/test-reporter from 1.8.0 to 1.9.0 in the github-actions group (#2019) Bumps the github-actions group with 1 update: [dorny/test-reporter](https://github.com/dorny/test-reporter). Updates `dorny/test-reporter` from 1.8.0 to 1.9.0 - [Release notes](https://github.com/dorny/test-reporter/releases) - [Changelog](https://github.com/dorny/test-reporter/blob/main/CHANGELOG.md) - [Commits](https://github.com/dorny/test-reporter/compare/v1.8.0...v1.9.0) --- updated-dependencies: - dependency-name: dorny/test-reporter dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test_report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_report.yml b/.github/workflows/test_report.yml index dde23ce4e1a..dbe61e9b80e 100644 --- a/.github/workflows/test_report.yml +++ b/.github/workflows/test_report.yml @@ -8,7 +8,7 @@ jobs: report: runs-on: ubuntu-latest-8core steps: - - uses: dorny/test-reporter@v1.8.0 + - uses: dorny/test-reporter@v1.9.0 with: artifact: test_results name: Test reports From 6ee82175937d31faa98a35e238d2ecb10200c394 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Tue, 9 Apr 2024 14:27:06 +0200 Subject: [PATCH 032/179] Updated dev-dependencies w/ ESLint 9 (#2021) --- pyscript.core/package-lock.json | 389 ++++++++++++++------------------ pyscript.core/package.json | 14 +- pyscript.core/types/core.d.ts | 1 - 3 files changed, 176 insertions(+), 228 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 20cb8ba7f5b..fdb4ebff955 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -21,21 +21,21 @@ "@codemirror/lang-python": "^6.1.5", "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.26.1", - "@playwright/test": "^1.42.1", + "@codemirror/view": "^6.26.2", + "@playwright/test": "^1.43.0", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", "@webreflection/toml-j0.4": "^1.1.3", - "@xterm/addon-fit": "^0.9.0", + "@xterm/addon-fit": "^0.10.0", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^8.57.0", - "rollup": "^4.14.0", + "eslint": "^9.0.0", + "rollup": "^4.14.1", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", - "typescript": "^5.4.3", + "typescript": "^5.4.4", "xterm": "^5.3.0", "xterm-readline": "^1.1.1" } @@ -135,9 +135,9 @@ "dev": true }, "node_modules/@codemirror/view": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.1.tgz", - "integrity": "sha512-wLw0t3R9AwOSQThdZ5Onw8QQtem5asE7+bPlnzc57eubPqiuJKIzwjMZ+C42vQett+iva+J8VgFV4RYWDBh5FA==", + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.2.tgz", + "integrity": "sha512-j6V48PlFC/O7ERAR5vRW5QKDdchzmyyfojDdt+zPsB0YXoWgcjlC1IWjmlYfx08aQZ3HN5BtALcgGgtSKGMe7A==", "dev": true, "dependencies": { "@codemirror/state": "^6.4.0", @@ -170,15 +170,15 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.0.2.tgz", + "integrity": "sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -186,28 +186,28 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.0.0.tgz", + "integrity": "sha512-RThY/MnKrhubF6+s1JflwUjPEsnCEmYCWwqa/aRISKWNXGZ9epUwft4bUMM35SdKF9xvBrLydAM1RDHd1Z//ZQ==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.12.3.tgz", + "integrity": "sha512-jsNnTBlMWuTpDkeE3on7+dWJi0D6fdDfeANj/w7MpS8ztROCoLvIO2nG0CcFj+E4k8j4QrSTh4Oryi3i2G669g==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", + "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" }, @@ -229,9 +229,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, "node_modules/@jridgewell/gen-mapping": { @@ -363,12 +363,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.42.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.1.tgz", - "integrity": "sha512-Gq9rmS54mjBL/7/MvBaNOBwbfnh7beHvS6oS4srqXFcQHpQCV1+c8JXWE8VLPyRDhgS3H8x8A7hztqI9VnwrAQ==", + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.43.0.tgz", + "integrity": "sha512-Ebw0+MCqoYflop7wVKj711ccbNlrwTBCtjY5rlbiY9kHL2bCYxq+qltK6uPsVBGGAOb033H2VO0YobcQVxoW7Q==", "dev": true, "dependencies": { - "playwright": "1.42.1" + "playwright": "1.43.0" }, "bin": { "playwright": "cli.js" @@ -472,9 +472,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.0.tgz", - "integrity": "sha512-jwXtxYbRt1V+CdQSy6Z+uZti7JF5irRKF8hlKfEnF/xJpcNGuuiZMBvuoYM+x9sr9iWGnzrlM0+9hvQ1kgkf1w==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.1.tgz", + "integrity": "sha512-fH8/o8nSUek8ceQnT7K4EQbSiV7jgkHq81m9lWZFIXjJ7lJzpWXbQFpT/Zh6OZYnpFykvzC3fbEvEAFZu03dPA==", "cpu": [ "arm" ], @@ -485,9 +485,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.0.tgz", - "integrity": "sha512-fI9nduZhCccjzlsA/OuAwtFGWocxA4gqXGTLvOyiF8d+8o0fZUeSztixkYjcGq1fGZY3Tkq4yRvHPFxU+jdZ9Q==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.1.tgz", + "integrity": "sha512-Y/9OHLjzkunF+KGEoJr3heiD5X9OLa8sbT1lm0NYeKyaM3oMhhQFvPB0bNZYJwlq93j8Z6wSxh9+cyKQaxS7PQ==", "cpu": [ "arm64" ], @@ -498,9 +498,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.0.tgz", - "integrity": "sha512-BcnSPRM76/cD2gQC+rQNGBN6GStBs2pl/FpweW8JYuz5J/IEa0Fr4AtrPv766DB/6b2MZ/AfSIOSGw3nEIP8SA==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.1.tgz", + "integrity": "sha512-+kecg3FY84WadgcuSVm6llrABOdQAEbNdnpi5X3UwWiFVhZIZvKgGrF7kmLguvxHNQy+UuRV66cLVl3S+Rkt+Q==", "cpu": [ "arm64" ], @@ -511,9 +511,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.0.tgz", - "integrity": "sha512-LDyFB9GRolGN7XI6955aFeI3wCdCUszFWumWU0deHA8VpR3nWRrjG6GtGjBrQxQKFevnUTHKCfPR4IvrW3kCgQ==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.1.tgz", + "integrity": "sha512-2pYRzEjVqq2TB/UNv47BV/8vQiXkFGVmPFwJb+1E0IFFZbIX8/jo1olxqqMbo6xCXf8kabANhp5bzCij2tFLUA==", "cpu": [ "x64" ], @@ -524,9 +524,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.0.tgz", - "integrity": "sha512-ygrGVhQP47mRh0AAD0zl6QqCbNsf0eTo+vgwkY6LunBcg0f2Jv365GXlDUECIyoXp1kKwL5WW6rsO429DBY/bA==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.1.tgz", + "integrity": "sha512-mS6wQ6Do6/wmrF9aTFVpIJ3/IDXhg1EZcQFYHZLHqw6AzMBjTHWnCG35HxSqUNphh0EHqSM6wRTT8HsL1C0x5g==", "cpu": [ "arm" ], @@ -537,9 +537,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.0.tgz", - "integrity": "sha512-x+uJ6MAYRlHGe9wi4HQjxpaKHPM3d3JjqqCkeC5gpnnI6OWovLdXTpfa8trjxPLnWKyBsSi5kne+146GAxFt4A==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.1.tgz", + "integrity": "sha512-p9rGKYkHdFMzhckOTFubfxgyIO1vw//7IIjBBRVzyZebWlzRLeNhqxuSaZ7kCEKVkm/kuC9fVRW9HkC/zNRG2w==", "cpu": [ "arm64" ], @@ -550,9 +550,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.0.tgz", - "integrity": "sha512-nrRw8ZTQKg6+Lttwqo6a2VxR9tOroa2m91XbdQ2sUUzHoedXlsyvY1fN4xWdqz8PKmf4orDwejxXHjh7YBGUCA==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.1.tgz", + "integrity": "sha512-nDY6Yz5xS/Y4M2i9JLQd3Rofh5OR8Bn8qe3Mv/qCVpHFlwtZSBYSPaU4mrGazWkXrdQ98GB//H0BirGR/SKFSw==", "cpu": [ "arm64" ], @@ -563,9 +563,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.0.tgz", - "integrity": "sha512-xV0d5jDb4aFu84XKr+lcUJ9y3qpIWhttO3Qev97z8DKLXR62LC3cXT/bMZXrjLF9X+P5oSmJTzAhqwUbY96PnA==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.1.tgz", + "integrity": "sha512-im7HE4VBL+aDswvcmfx88Mp1soqL9OBsdDBU8NqDEYtkri0qV0THhQsvZtZeNNlLeCUQ16PZyv7cqutjDF35qw==", "cpu": [ "ppc64le" ], @@ -576,9 +576,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.0.tgz", - "integrity": "sha512-SDDhBQwZX6LPRoPYjAZWyL27LbcBo7WdBFWJi5PI9RPCzU8ijzkQn7tt8NXiXRiFMJCVpkuMkBf4OxSxVMizAw==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.1.tgz", + "integrity": "sha512-RWdiHuAxWmzPJgaHJdpvUUlDz8sdQz4P2uv367T2JocdDa98iRw2UjIJ4QxSyt077mXZT2X6pKfT2iYtVEvOFw==", "cpu": [ "riscv64" ], @@ -589,9 +589,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.0.tgz", - "integrity": "sha512-RxB/qez8zIDshNJDufYlTT0ZTVut5eCpAZ3bdXDU9yTxBzui3KhbGjROK2OYTTor7alM7XBhssgoO3CZ0XD3qA==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.1.tgz", + "integrity": "sha512-VMgaGQ5zRX6ZqV/fas65/sUGc9cPmsntq2FiGmayW9KMNfWVG/j0BAqImvU4KTeOOgYSf1F+k6at1UfNONuNjA==", "cpu": [ "s390x" ], @@ -602,9 +602,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.0.tgz", - "integrity": "sha512-C6y6z2eCNCfhZxT9u+jAM2Fup89ZjiG5pIzZIDycs1IwESviLxwkQcFRGLjnDrP+PT+v5i4YFvlcfAs+LnreXg==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.1.tgz", + "integrity": "sha512-9Q7DGjZN+hTdJomaQ3Iub4m6VPu1r94bmK2z3UeWP3dGUecRC54tmVu9vKHTm1bOt3ASoYtEz6JSRLFzrysKlA==", "cpu": [ "x64" ], @@ -615,9 +615,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.0.tgz", - "integrity": "sha512-i0QwbHYfnOMYsBEyjxcwGu5SMIi9sImDVjDg087hpzXqhBSosxkE7gyIYFHgfFl4mr7RrXksIBZ4DoLoP4FhJg==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.1.tgz", + "integrity": "sha512-JNEG/Ti55413SsreTguSx0LOVKX902OfXIKVg+TCXO6Gjans/k9O6ww9q3oLGjNDaTLxM+IHFMeXy/0RXL5R/g==", "cpu": [ "x64" ], @@ -628,9 +628,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.0.tgz", - "integrity": "sha512-Fq52EYb0riNHLBTAcL0cun+rRwyZ10S9vKzhGKKgeD+XbwunszSY0rVMco5KbOsTlwovP2rTOkiII/fQ4ih/zQ==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.1.tgz", + "integrity": "sha512-ryS22I9y0mumlLNwDFYZRDFLwWh3aKaC72CWjFcFvxK0U6v/mOkM5Up1bTbCRAhv3kEIwW2ajROegCIQViUCeA==", "cpu": [ "arm64" ], @@ -641,9 +641,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.0.tgz", - "integrity": "sha512-e/PBHxPdJ00O9p5Ui43+vixSgVf4NlLsmV6QneGERJ3lnjIua/kim6PRFe3iDueT1rQcgSkYP8ZBBXa/h4iPvw==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.1.tgz", + "integrity": "sha512-TdloItiGk+T0mTxKx7Hp279xy30LspMso+GzQvV2maYePMAWdmrzqSNZhUpPj3CGw12aGj57I026PgLCTu8CGg==", "cpu": [ "ia32" ], @@ -654,9 +654,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.0.tgz", - "integrity": "sha512-aGg7iToJjdklmxlUlJh/PaPNa4PmqHfyRMLunbL3eaMO0gp656+q1zOKkpJ/CVe9CryJv6tAN1HDoR8cNGzkag==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.1.tgz", + "integrity": "sha512-wQGI+LY/Py20zdUPq+XCem7JcPOyzIJBm3dli+56DJsQOHbnXZFEwgmnC6el1TPAfC8lBT3m+z69RmLykNUbew==", "cpu": [ "x64" ], @@ -709,9 +709,9 @@ "dev": true }, "node_modules/@xterm/addon-fit": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.9.0.tgz", - "integrity": "sha512-hDlPPbTVPYyvwXu/asW8HbJkI/2RMi0cMaJnBZYVeJB0SWP2NeESMCNr+I7CvBlyI0sAxpxOg8Wk4OMkxBz9WA==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.10.0.tgz", + "integrity": "sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==", "dev": true, "peerDependencies": { "@xterm/xterm": "^5.0.0" @@ -1279,18 +1279,6 @@ "node": ">=0.10.0" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -1389,41 +1377,37 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.0.0.tgz", + "integrity": "sha512-IMryZ5SudxzQvuod6rUdIUz29qFItWx281VhtFVc2Psy/ZhlCeD/5DT6lBIJ4H3G+iamGJoTln1v+QSuPw0p7Q==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint/eslintrc": "^3.0.2", + "@eslint/js": "9.0.0", + "@humanwhocodes/config-array": "^0.12.3", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", + "eslint-scope": "^8.0.1", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.0.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -1437,23 +1421,23 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", + "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -1471,6 +1455,18 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -1484,17 +1480,29 @@ } }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", + "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", "dev": true, "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.11.3", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -1582,15 +1590,15 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/fill-range": { @@ -1622,23 +1630,22 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/fs.realpath": { @@ -1737,15 +1744,12 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2336,15 +2340,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -2396,12 +2391,12 @@ "integrity": "sha512-yyVAOFKTAElc7KdLt2+UKGExNYwYb/Y/WE9i+1ezCQsJE8gbKSjewfpRqK2nQgZ4d4hhAAGgDCOcIZVilqE5UA==" }, "node_modules/playwright": { - "version": "1.42.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.1.tgz", - "integrity": "sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg==", + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.0.tgz", + "integrity": "sha512-SiOKHbVjTSf6wHuGCbqrEyzlm6qvXcv7mENP+OZon1I07brfZLGdfWV0l/efAzVx7TF3Z45ov1gPEkku9q25YQ==", "dev": true, "dependencies": { - "playwright-core": "1.42.1" + "playwright-core": "1.43.0" }, "bin": { "playwright": "cli.js" @@ -2414,9 +2409,9 @@ } }, "node_modules/playwright-core": { - "version": "1.42.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.1.tgz", - "integrity": "sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA==", + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.0.tgz", + "integrity": "sha512-iWFjyBUH97+pUFiyTqSLd8cDMMOS0r2ZYz2qEsPjH8/bX++sbIJT35MSwKnp1r/OQBAqC5XO99xFbJ9XClhf4w==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -3126,45 +3121,10 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/rollup": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.0.tgz", - "integrity": "sha512-Qe7w62TyawbDzB4yt32R0+AbIo6m1/sqO7UPzFS8Z/ksL5mrfhA0v4CavfdmFav3D+ub4QeAgsGEe84DoWe/nQ==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.1.tgz", + "integrity": "sha512-4LnHSdd3QK2pa1J6dFbfm1HN0D7vSK/ZuZTsdyUAlA6Rr1yTouUTL13HaDOGJVgby461AhrNGBS7sCGXXtT+SA==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -3177,21 +3137,21 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.14.0", - "@rollup/rollup-android-arm64": "4.14.0", - "@rollup/rollup-darwin-arm64": "4.14.0", - "@rollup/rollup-darwin-x64": "4.14.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.14.0", - "@rollup/rollup-linux-arm64-gnu": "4.14.0", - "@rollup/rollup-linux-arm64-musl": "4.14.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.14.0", - "@rollup/rollup-linux-riscv64-gnu": "4.14.0", - "@rollup/rollup-linux-s390x-gnu": "4.14.0", - "@rollup/rollup-linux-x64-gnu": "4.14.0", - "@rollup/rollup-linux-x64-musl": "4.14.0", - "@rollup/rollup-win32-arm64-msvc": "4.14.0", - "@rollup/rollup-win32-ia32-msvc": "4.14.0", - "@rollup/rollup-win32-x64-msvc": "4.14.0", + "@rollup/rollup-android-arm-eabi": "4.14.1", + "@rollup/rollup-android-arm64": "4.14.1", + "@rollup/rollup-darwin-arm64": "4.14.1", + "@rollup/rollup-darwin-x64": "4.14.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.14.1", + "@rollup/rollup-linux-arm64-gnu": "4.14.1", + "@rollup/rollup-linux-arm64-musl": "4.14.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.14.1", + "@rollup/rollup-linux-riscv64-gnu": "4.14.1", + "@rollup/rollup-linux-s390x-gnu": "4.14.1", + "@rollup/rollup-linux-x64-gnu": "4.14.1", + "@rollup/rollup-linux-x64-musl": "4.14.1", + "@rollup/rollup-win32-arm64-msvc": "4.14.1", + "@rollup/rollup-win32-ia32-msvc": "4.14.1", + "@rollup/rollup-win32-x64-msvc": "4.14.1", "fsevents": "~2.3.2" } }, @@ -3568,22 +3528,10 @@ "resolved": "https://registry.npmjs.org/type-checked-collections/-/type-checked-collections-0.1.7.tgz", "integrity": "sha512-fLIydlJy7IG9XL4wjRwEcKhxx/ekLXiWiMvcGo01cOMF+TN+5ZqajM1mRNRz2bNNi1bzou2yofhjZEQi7kgl9A==" }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typescript": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", - "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", + "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -3690,6 +3638,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/xterm/-/xterm-5.3.0.tgz", "integrity": "sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==", + "deprecated": "This package is now deprecated. Move to @xterm/xterm instead.", "dev": true }, "node_modules/xterm-readline": { diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 5b7fa33388d..cd431f2358a 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -20,7 +20,7 @@ }, "scripts": { "server": "npx static-handler --coi .", - "build": "npm run build:3rd-party && npm run build:stdlib && npm run build:plugins && npm run build:core && eslint src/ && npm run ts && npm run test:mpy", + "build": "export ESLINT_USE_FLAT_CONFIG=false; npm run build:3rd-party && npm run build:stdlib && npm run build:plugins && npm run build:core && eslint src/ && npm run ts && npm run test:mpy", "build:core": "rm -rf dist && rollup --config rollup/core.config.js && cp src/3rd-party/*.css dist/", "build:plugins": "node rollup/plugins.cjs", "build:stdlib": "node rollup/stdlib.cjs", @@ -52,21 +52,21 @@ "@codemirror/lang-python": "^6.1.5", "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.26.1", - "@playwright/test": "^1.42.1", + "@codemirror/view": "^6.26.2", + "@playwright/test": "^1.43.0", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", "@webreflection/toml-j0.4": "^1.1.3", - "@xterm/addon-fit": "^0.9.0", + "@xterm/addon-fit": "^0.10.0", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^8.57.0", - "rollup": "^4.14.0", + "eslint": "^9.0.0", + "rollup": "^4.14.1", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", - "typescript": "^5.4.3", + "typescript": "^5.4.4", "xterm": "^5.3.0", "xterm-readline": "^1.1.1" }, diff --git a/pyscript.core/types/core.d.ts b/pyscript.core/types/core.d.ts index 4bddbbc75f1..a56801538f4 100644 --- a/pyscript.core/types/core.d.ts +++ b/pyscript.core/types/core.d.ts @@ -51,5 +51,4 @@ declare const exportedHooks: { }; declare const exportedConfig: {}; declare const exportedWhenDefined: (type: string) => Promise; -import sync from "./sync.js"; export { stdlib, TYPES, exportedPyWorker as PyWorker, exportedMPWorker as MPWorker, exportedHooks as hooks, exportedConfig as config, exportedWhenDefined as whenDefined }; From 2d5cf096e06433f89f4c5247cb03789e1601de7e Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Tue, 9 Apr 2024 14:51:10 +0200 Subject: [PATCH 033/179] Fix MicroPython badly handling unicode chars (#2018) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Changes * fixed an issue with the **py-editor** related to the new `linebuffer` directive * provide in worker hook scope a simple callback that pre-buffers unicode sequences [accordingly to the standard](https://encoding.spec.whatwg.org/#utf-8-bytes-needed) so that the buffer is sent to the terminal only once those sequences are fulfilled * test with both `µ` and way more convoluted sequences such as 👩‍❤️‍👨 that the output, if either requested as input or already evaluated from the page works ... in latter case `test = "👩‍❤️‍👨"` completely messes up the program and the resulting string is empty --- pyscript.core/package-lock.json | 12 +++---- pyscript.core/package.json | 4 +-- pyscript.core/src/plugins/py-editor.js | 4 +-- pyscript.core/src/plugins/py-terminal.js | 46 +++++++++++++++++++----- pyscript.core/test/py-terminal.html | 1 + 5 files changed, 49 insertions(+), 18 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index fdb4ebff955..b18c5741076 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.4.16", + "version": "0.4.18", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.16", + "version": "0.4.18", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.2", + "polyscript": "^0.12.3", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -2435,9 +2435,9 @@ } }, "node_modules/polyscript": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.2.tgz", - "integrity": "sha512-qHZbcSVhp4bDW9YjcPyYw2AWDRrBEDUVxKMuvjACjQK7O891H6x7dNKVYNjij75Ygn9akma+X1n6eTW4syBFmQ==", + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.3.tgz", + "integrity": "sha512-aekNrFZzdLe0KQuSMWKFsUwkv414hIIjDgqzCbEXl4l5xZA8vgiv+jFFOZnkJk9/HeybLRPJBRdlhBxfdKVV0Q==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index cd431f2358a..548d2dc42af 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.16", + "version": "0.4.18", "type": "module", "description": "PyScript", "module": "./index.js", @@ -42,7 +42,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.2", + "polyscript": "^0.12.3", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" diff --git a/pyscript.core/src/plugins/py-editor.js b/pyscript.core/src/plugins/py-editor.js index 8b1bb8d5e3d..9a8284565c1 100644 --- a/pyscript.core/src/plugins/py-editor.js +++ b/pyscript.core/src/plugins/py-editor.js @@ -15,8 +15,8 @@ const hooks = { codeBeforeRun: () => stdlib, // works on both Pyodide and MicroPython onReady: ({ runAsync, io }, { sync }) => { - io.stdout = (line) => sync.write(line); - io.stderr = (line) => sync.writeErr(line); + io.stdout = io.buffered(sync.write); + io.stderr = io.buffered(sync.writeErr); sync.revoke(); sync.runAsync = runAsync; }, diff --git a/pyscript.core/src/plugins/py-terminal.js b/pyscript.core/src/plugins/py-terminal.js index 925fc1f9957..721fef77725 100644 --- a/pyscript.core/src/plugins/py-terminal.js +++ b/pyscript.core/src/plugins/py-terminal.js @@ -59,7 +59,37 @@ const workerReady = ({ interpreter, io, run, type }, { sync }) => { }); run("from _pyscript_input import input"); - io.stdout = generic.write; + // this is needed to avoid truncated unicode in MicroPython + // the reason is that `linebuffer` false just send one byte + // per time and readline here doesn't like it much. + // MicroPython also has issues with code-points and + // replProcessChar(byte) but that function accepts only + // one byte per time so ... we have an issue! + // @see https://github.com/pyscript/pyscript/pull/2018 + // @see https://github.com/WebReflection/buffer-points + const bufferPoints = (stdio) => { + const bytes = []; + let needed = 0; + return (buffer) => { + let written = 0; + for (const byte of buffer) { + bytes.push(byte); + // @see https://encoding.spec.whatwg.org/#utf-8-bytes-needed + if (needed) needed--; + else if (0xc2 <= byte && byte <= 0xdf) needed = 1; + else if (0xe0 <= byte && byte <= 0xef) needed = 2; + else if (0xf0 <= byte && byte <= 0xf4) needed = 3; + if (!needed) { + written += bytes.length; + stdio(new Uint8Array(bytes.splice(0))); + } + } + return written; + }; + }; + + io.stdout = bufferPoints(generic.write); + // tiny shim of the code module with only interact // to bootstrap a REPL like environment interpreter.registerJsModule("code", { @@ -69,14 +99,14 @@ const workerReady = ({ interpreter, io, run, type }, { sync }) => { const encoder = new TextEncoder(); const acc = []; + const handlePoints = bufferPoints((buffer) => { + acc.push(...buffer); + pyterminal_write(decoder.decode(buffer)); + }); - io.stdout = (buffer) => { - // avoid duplicating the output produced by the input - if (length++ > input.length) { - acc.push(...buffer); - pyterminal_write(decoder.decode(buffer)); - } - }; + // avoid duplicating the output produced by the input + io.stdout = (buffer) => + length++ > input.length ? handlePoints(buffer) : 0; interpreter.replInit(); diff --git a/pyscript.core/test/py-terminal.html b/pyscript.core/test/py-terminal.html index 1ce3192855c..d4ab3537f8b 100644 --- a/pyscript.core/test/py-terminal.html +++ b/pyscript.core/test/py-terminal.html @@ -10,6 +10,7 @@ From d7d2dfb38308bfc65a873d824f53d169cc9ec2c4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 10 Apr 2024 16:22:15 +0200 Subject: [PATCH 034/179] [pre-commit.ci] pre-commit autoupdate (#2012) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 24.1.1 → 24.3.0](https://github.com/psf/black/compare/24.1.1...24.3.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Andrea Giammarchi --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7abd4181f7e..7434b43bff3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/psf/black - rev: 24.1.1 + rev: 24.3.0 hooks: - id: black exclude: pyscript\.core/src/stdlib/pyscript/__init__\.py From 44cd6273bad5d8cc1242c1f609648f24eb4966f9 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Fri, 12 Apr 2024 15:44:20 +0200 Subject: [PATCH 035/179] PyTerminal .process(code) utility (#2026) * PyTerminal .process(code) utility * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/package-lock.json | 4 ++-- pyscript.core/package.json | 2 +- pyscript.core/src/plugins/py-terminal.js | 22 ++++++++++++++++++++-- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index b18c5741076..1e8c9fd3209 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.18", + "version": "0.4.20", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.18", + "version": "0.4.20", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 548d2dc42af..17d6ab8aefe 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.18", + "version": "0.4.20", "type": "module", "description": "PyScript", "module": "./index.js", diff --git a/pyscript.core/src/plugins/py-terminal.js b/pyscript.core/src/plugins/py-terminal.js index 721fef77725..6bc26a4830b 100644 --- a/pyscript.core/src/plugins/py-terminal.js +++ b/pyscript.core/src/plugins/py-terminal.js @@ -1,7 +1,7 @@ // PyScript py-terminal plugin import { TYPES, hooks } from "../core.js"; import { notify } from "./error.js"; -import { customObserver, defineProperty } from "polyscript/exports"; +import { customObserver, defineProperties } from "polyscript/exports"; // will contain all valid selectors const SELECTORS = []; @@ -170,7 +170,25 @@ const pyTerminal = async (element) => { terminal.open(target); fitAddon.fit(); terminal.focus(); - defineProperty(element, "terminal", { value: terminal }); + defineProperties(element, { + terminal: { value: terminal }, + process: { + value: async (code) => { + // this loop is the only way I could find to actually simulate + // the user input char after char in a way that works in both + // MicroPython and Pyodide + for (const line of code.split(/(?:\r|\n|\r\n)/)) { + terminal.paste(`${line}\n`); + do { + await new Promise((resolve) => + setTimeout(resolve, 0), + ); + } while (!readline.activeRead?.resolve); + readline.activeRead.resolve(line); + } + }, + }, + }); return terminal; }; From c6532968219417baaa6a59ea7299179332894e79 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Fri, 12 Apr 2024 16:25:12 +0200 Subject: [PATCH 036/179] Added @xterm/addon-web-links to the terminal (#2027) * Added @xterm/addon-web-links to the terminal * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/package-lock.json | 14 ++++++++++++-- pyscript.core/package.json | 3 ++- pyscript.core/rollup/3rd-party.cjs | 3 +++ pyscript.core/src/plugins/py-terminal.js | 15 ++++++++++----- .../types/3rd-party/xterm_addon-web-links.d.ts | 4 ++++ 5 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 pyscript.core/types/3rd-party/xterm_addon-web-links.d.ts diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 1e8c9fd3209..2e4b208c4f6 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.20", + "version": "0.4.21", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.20", + "version": "0.4.21", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", @@ -28,6 +28,7 @@ "@rollup/plugin-terser": "^0.4.4", "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", + "@xterm/addon-web-links": "^0.11.0", "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^9.0.0", @@ -717,6 +718,15 @@ "@xterm/xterm": "^5.0.0" } }, + "node_modules/@xterm/addon-web-links": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@xterm/addon-web-links/-/addon-web-links-0.11.0.tgz", + "integrity": "sha512-nIHQ38pQI+a5kXnRaTgwqSHnX7KE6+4SVoceompgHL26unAxdfP6IPqUTSYPQgSwM56hsElfoNrrW5V7BUED/Q==", + "dev": true, + "peerDependencies": { + "@xterm/xterm": "^5.0.0" + } + }, "node_modules/@xterm/xterm": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.4.0.tgz", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 17d6ab8aefe..b9c229f054a 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.20", + "version": "0.4.21", "type": "module", "description": "PyScript", "module": "./index.js", @@ -59,6 +59,7 @@ "@rollup/plugin-terser": "^0.4.4", "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", + "@xterm/addon-web-links": "^0.11.0", "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^9.0.0", diff --git a/pyscript.core/rollup/3rd-party.cjs b/pyscript.core/rollup/3rd-party.cjs index 28c34beb9c1..44ffd16b1ea 100644 --- a/pyscript.core/rollup/3rd-party.cjs +++ b/pyscript.core/rollup/3rd-party.cjs @@ -51,6 +51,9 @@ const modules = { "xterm_addon-fit.js": fetch(`${CDN}/@xterm/addon-fit/+esm`).then((b) => b.text(), ), + "xterm_addon-web-links.js": fetch( + `${CDN}/@xterm/addon-web-links/+esm`, + ).then((b) => b.text()), "xterm.css": fetch(`${CDN}/xterm@${v("xterm")}/css/xterm.min.css`).then( (b) => b.text(), ), diff --git a/pyscript.core/src/plugins/py-terminal.js b/pyscript.core/src/plugins/py-terminal.js index 6bc26a4830b..54f1cdad382 100644 --- a/pyscript.core/src/plugins/py-terminal.js +++ b/pyscript.core/src/plugins/py-terminal.js @@ -134,11 +134,15 @@ const workerReady = ({ interpreter, io, run, type }, { sync }) => { const pyTerminal = async (element) => { // lazy load these only when a valid terminal is found - const [{ Terminal }, { Readline }, { FitAddon }] = await Promise.all([ - import(/* webpackIgnore: true */ "../3rd-party/xterm.js"), - import(/* webpackIgnore: true */ "../3rd-party/xterm-readline.js"), - import(/* webpackIgnore: true */ "../3rd-party/xterm_addon-fit.js"), - ]); + const [{ Terminal }, { Readline }, { FitAddon }, { WebLinksAddon }] = + await Promise.all([ + import(/* webpackIgnore: true */ "../3rd-party/xterm.js"), + import(/* webpackIgnore: true */ "../3rd-party/xterm-readline.js"), + import(/* webpackIgnore: true */ "../3rd-party/xterm_addon-fit.js"), + import( + /* webpackIgnore: true */ "../3rd-party/xterm_addon-web-links.js" + ), + ]); const readline = new Readline(); @@ -167,6 +171,7 @@ const pyTerminal = async (element) => { const fitAddon = new FitAddon(); terminal.loadAddon(fitAddon); terminal.loadAddon(readline); + terminal.loadAddon(new WebLinksAddon()); terminal.open(target); fitAddon.fit(); terminal.focus(); diff --git a/pyscript.core/types/3rd-party/xterm_addon-web-links.d.ts b/pyscript.core/types/3rd-party/xterm_addon-web-links.d.ts new file mode 100644 index 00000000000..5d1e051502b --- /dev/null +++ b/pyscript.core/types/3rd-party/xterm_addon-web-links.d.ts @@ -0,0 +1,4 @@ +declare var r: any; +declare var n: any; +declare var t: {}; +export { r as WebLinksAddon, n as __esModule, t as default }; From cf929960711387159286fd246f8ff47d7898b334 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Wed, 17 Apr 2024 17:10:23 +0200 Subject: [PATCH 037/179] Avoid PyWeb as part of stdlib on MicroPython (#2030) * Avoid PyWeb as part of stdlib on MicroPython * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/src/core.js | 8 ++++---- pyscript.core/src/hooks.js | 9 +++++---- pyscript.core/src/stdlib.js | 35 ++++++++++++++++++++++++++++----- pyscript.core/types/core.d.ts | 5 +++-- pyscript.core/types/hooks.d.ts | 2 +- pyscript.core/types/stdlib.d.ts | 4 ++-- 6 files changed, 45 insertions(+), 18 deletions(-) diff --git a/pyscript.core/src/core.js b/pyscript.core/src/core.js index d3955557918..fb7092ab6b9 100644 --- a/pyscript.core/src/core.js +++ b/pyscript.core/src/core.js @@ -26,8 +26,8 @@ import { ErrorCode } from "./exceptions.js"; import { robustFetch as fetch, getText } from "./fetch.js"; import { hooks, main, worker, codeFor, createFunction } from "./hooks.js"; -import stdlib from "./stdlib.js"; -export { stdlib }; +import { stdlib, optional } from "./stdlib.js"; +export { stdlib, optional }; // generic helper to disambiguate between custom element and script const isScript = ({ tagName }) => tagName === "SCRIPT"; @@ -168,7 +168,7 @@ for (const [TYPE, interpreter] of TYPES) { // specific main and worker hooks const hooks = { main: { - ...codeFor(main), + ...codeFor(main, TYPE), async onReady(wrap, element) { registerModule(wrap); @@ -265,7 +265,7 @@ for (const [TYPE, interpreter] of TYPES) { }, }, worker: { - ...codeFor(worker), + ...codeFor(worker, TYPE), // these are lazy getters that returns a composition // of the current hooks or undefined, if no hook is present get onReady() { diff --git a/pyscript.core/src/hooks.js b/pyscript.core/src/hooks.js index 921ae6a9338..03950bf4da2 100644 --- a/pyscript.core/src/hooks.js +++ b/pyscript.core/src/hooks.js @@ -2,7 +2,7 @@ import { typedSet } from "type-checked-collections"; import { dedent } from "polyscript/exports"; import toJSONCallback from "to-json-callback"; -import stdlib from "./stdlib.js"; +import { stdlib, optional } from "./stdlib.js"; export const main = (name) => hooks.main[name]; export const worker = (name) => hooks.worker[name]; @@ -15,10 +15,11 @@ const code = (hooks, branch, key, lib) => { }; }; -export const codeFor = (branch) => { +export const codeFor = (branch, type) => { + const pylib = type === "mpy" ? stdlib.replace(optional, "") : stdlib; const hooks = {}; - code(hooks, branch, `codeBeforeRun`, stdlib); - code(hooks, branch, `codeBeforeRunAsync`, stdlib); + code(hooks, branch, `codeBeforeRun`, pylib); + code(hooks, branch, `codeBeforeRunAsync`, pylib); code(hooks, branch, `codeAfterRun`); code(hooks, branch, `codeAfterRunAsync`); return hooks; diff --git a/pyscript.core/src/stdlib.js b/pyscript.core/src/stdlib.js index ddc4efc2474..45f2e162a9d 100644 --- a/pyscript.core/src/stdlib.js +++ b/pyscript.core/src/stdlib.js @@ -8,6 +8,27 @@ import pyscript from "./stdlib/pyscript.js"; +class Ignore extends Array { + #add = false; + #paths; + #array; + constructor(array, ...paths) { + super(); + this.#array = array; + this.#paths = paths; + } + push(...values) { + if (this.#add) super.push(...values); + return this.#array.push(...values); + } + path(path) { + for (const _path of this.#paths) { + // bails out at the first `true` value + if ((this.#add = path.startsWith(_path))) break; + } + } +} + const { entries } = Object; const python = [ @@ -16,16 +37,19 @@ const python = [ "_path = None", ]; +const ignore = new Ignore(python, "./pyweb"); + const write = (base, literal) => { for (const [key, value] of entries(literal)) { - python.push(`_path = _Path("${base}/${key}")`); + ignore.path(`${base}/${key}`); + ignore.push(`_path = _Path("${base}/${key}")`); if (typeof value === "string") { const code = JSON.stringify(value); - python.push(`_path.write_text(${code},encoding="utf-8")`); + ignore.push(`_path.write_text(${code},encoding="utf-8")`); } else { // @see https://github.com/pyscript/pyscript/pull/1813#issuecomment-1781502909 - python.push(`if not _os.path.exists("${base}/${key}"):`); - python.push(" _path.mkdir(parents=True, exist_ok=True)"); + ignore.push(`if not _os.path.exists("${base}/${key}"):`); + ignore.push(" _path.mkdir(parents=True, exist_ok=True)"); write(`${base}/${key}`, value); } } @@ -42,4 +66,5 @@ python.push( ); python.push("\n"); -export default python.join("\n"); +export const stdlib = python.join("\n"); +export const optional = ignore.join("\n"); diff --git a/pyscript.core/types/core.d.ts b/pyscript.core/types/core.d.ts index a56801538f4..629011e3274 100644 --- a/pyscript.core/types/core.d.ts +++ b/pyscript.core/types/core.d.ts @@ -1,4 +1,5 @@ -import stdlib from "./stdlib.js"; +import { stdlib } from "./stdlib.js"; +import { optional } from "./stdlib.js"; import TYPES from "./types.js"; /** * A `Worker` facade able to bootstrap on the worker thread only a PyScript module. @@ -51,4 +52,4 @@ declare const exportedHooks: { }; declare const exportedConfig: {}; declare const exportedWhenDefined: (type: string) => Promise; -export { stdlib, TYPES, exportedPyWorker as PyWorker, exportedMPWorker as MPWorker, exportedHooks as hooks, exportedConfig as config, exportedWhenDefined as whenDefined }; +export { stdlib, optional, TYPES, exportedPyWorker as PyWorker, exportedMPWorker as MPWorker, exportedHooks as hooks, exportedConfig as config, exportedWhenDefined as whenDefined }; diff --git a/pyscript.core/types/hooks.d.ts b/pyscript.core/types/hooks.d.ts index e79ff791852..6e676d42e8b 100644 --- a/pyscript.core/types/hooks.d.ts +++ b/pyscript.core/types/hooks.d.ts @@ -1,6 +1,6 @@ export function main(name: any): any; export function worker(name: any): any; -export function codeFor(branch: any): {}; +export function codeFor(branch: any, type: any): {}; export function createFunction(self: any, name: any): any; export namespace hooks { namespace main { diff --git a/pyscript.core/types/stdlib.d.ts b/pyscript.core/types/stdlib.d.ts index ae80ecad1b2..c42c11acfd6 100644 --- a/pyscript.core/types/stdlib.d.ts +++ b/pyscript.core/types/stdlib.d.ts @@ -1,2 +1,2 @@ -declare const _default: string; -export default _default; +export const stdlib: string; +export const optional: string; From 643b76479f2b45ed2ea8667356a43b6ece7bb6c6 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Mon, 22 Apr 2024 12:43:17 +0200 Subject: [PATCH 038/179] HTML class in MicroPython (#2033) --- pyscript.core/src/stdlib/pyscript/display.py | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/pyscript.core/src/stdlib/pyscript/display.py b/pyscript.core/src/stdlib/pyscript/display.py index f6bff53ed02..1d1bdb0378f 100644 --- a/pyscript.core/src/stdlib/pyscript/display.py +++ b/pyscript.core/src/stdlib/pyscript/display.py @@ -6,17 +6,17 @@ from pyscript.magic_js import current_target, document, window _MIME_METHODS = { - "__repr__": "text/plain", - "_repr_html_": "text/html", - "_repr_markdown_": "text/markdown", - "_repr_svg_": "image/svg+xml", - "_repr_pdf_": "application/pdf", - "_repr_jpeg_": "image/jpeg", - "_repr_png_": "image/png", - "_repr_latex": "text/latex", - "_repr_json_": "application/json", - "_repr_javascript_": "application/javascript", "savefig": "image/png", + "_repr_javascript_": "application/javascript", + "_repr_json_": "application/json", + "_repr_latex": "text/latex", + "_repr_png_": "image/png", + "_repr_jpeg_": "image/jpeg", + "_repr_pdf_": "application/pdf", + "_repr_svg_": "image/svg+xml", + "_repr_markdown_": "text/markdown", + "_repr_html_": "text/html", + "__repr__": "text/plain", } @@ -99,7 +99,7 @@ def _format_mime(obj): format_dict = mimebundle output, not_available = None, [] - for method, mime_type in reversed(_MIME_METHODS.items()): + for method, mime_type in _MIME_METHODS.items(): if mime_type in format_dict: output = format_dict[mime_type] else: From 83c2afeaf1f9dacf0efde853f985c12b3f843fb0 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Wed, 24 Apr 2024 16:56:47 +0200 Subject: [PATCH 039/179] Updated Polyscript to its latest (#2036) --- pyscript.core/package-lock.json | 249 +++++++++++++++++--------------- pyscript.core/package.json | 16 +- 2 files changed, 143 insertions(+), 122 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 2e4b208c4f6..278a4757a69 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,28 +1,28 @@ { "name": "@pyscript/core", - "version": "0.4.21", + "version": "0.4.22", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.21", + "version": "0.4.22", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.3", + "polyscript": "^0.12.6", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" }, "devDependencies": { - "@codemirror/commands": "^6.3.3", + "@codemirror/commands": "^6.5.0", "@codemirror/lang-python": "^6.1.5", "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.26.2", - "@playwright/test": "^1.43.0", + "@codemirror/view": "^6.26.3", + "@playwright/test": "^1.43.1", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", @@ -31,12 +31,12 @@ "@xterm/addon-web-links": "^0.11.0", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^9.0.0", - "rollup": "^4.14.1", + "eslint": "^9.1.1", + "rollup": "^4.16.4", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", - "typescript": "^5.4.4", + "typescript": "^5.4.5", "xterm": "^5.3.0", "xterm-readline": "^1.1.1" } @@ -69,9 +69,9 @@ } }, "node_modules/@codemirror/commands": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.3.3.tgz", - "integrity": "sha512-dO4hcF0fGT9tu1Pj1D2PvGvxjeGkbC6RGcZw6Qs74TH+Ed1gw98jmUgd2axWvIZEqTeTuFrg1lEB1KV6cK9h1A==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.5.0.tgz", + "integrity": "sha512-rK+sj4fCAN/QfcY9BEzYMgp4wwL/q5aj/VfNSoH1RWPF9XS/dUwBkvlL3hpWgEjOqlpdN1uLC9UkjJ4tmyjJYg==", "dev": true, "dependencies": { "@codemirror/language": "^6.0.0", @@ -136,9 +136,9 @@ "dev": true }, "node_modules/@codemirror/view": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.2.tgz", - "integrity": "sha512-j6V48PlFC/O7ERAR5vRW5QKDdchzmyyfojDdt+zPsB0YXoWgcjlC1IWjmlYfx08aQZ3HN5BtALcgGgtSKGMe7A==", + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.3.tgz", + "integrity": "sha512-gmqxkPALZjkgSxIeeweY/wGQXBfwTUaLs8h7OKtSwfbj9Ct3L11lD+u1sS7XHppxFQoMDiMDp07P9f3I2jWOHw==", "dev": true, "dependencies": { "@codemirror/state": "^6.4.0", @@ -194,18 +194,18 @@ } }, "node_modules/@eslint/js": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.0.0.tgz", - "integrity": "sha512-RThY/MnKrhubF6+s1JflwUjPEsnCEmYCWwqa/aRISKWNXGZ9epUwft4bUMM35SdKF9xvBrLydAM1RDHd1Z//ZQ==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.1.1.tgz", + "integrity": "sha512-5WoDz3Y19Bg2BnErkZTp0en+c/i9PvgFS7MBe1+m60HjFr0hrphlAGp4yzI7pxpt4xShln4ZyYp4neJm8hmOkQ==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.12.3.tgz", - "integrity": "sha512-jsNnTBlMWuTpDkeE3on7+dWJi0D6fdDfeANj/w7MpS8ztROCoLvIO2nG0CcFj+E4k8j4QrSTh4Oryi3i2G669g==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^2.0.3", @@ -235,6 +235,19 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, + "node_modules/@humanwhocodes/retry": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.2.3.tgz", + "integrity": "sha512-X38nUbachlb01YMlvPFojKoiXq+LzZvuSce70KPMPdeM1Rj03k4dR7lDslhbqXn3Ang4EU3+EAmwEAsbrjHW3g==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -364,12 +377,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.43.0.tgz", - "integrity": "sha512-Ebw0+MCqoYflop7wVKj711ccbNlrwTBCtjY5rlbiY9kHL2bCYxq+qltK6uPsVBGGAOb033H2VO0YobcQVxoW7Q==", + "version": "1.43.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.43.1.tgz", + "integrity": "sha512-HgtQzFgNEEo4TE22K/X7sYTYNqEMMTZmFS8kTq6m8hXj+m1D8TgwgIbumHddJa9h4yl4GkKb8/bgAl2+g7eDgA==", "dev": true, "dependencies": { - "playwright": "1.43.0" + "playwright": "1.43.1" }, "bin": { "playwright": "cli.js" @@ -473,9 +486,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.1.tgz", - "integrity": "sha512-fH8/o8nSUek8ceQnT7K4EQbSiV7jgkHq81m9lWZFIXjJ7lJzpWXbQFpT/Zh6OZYnpFykvzC3fbEvEAFZu03dPA==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.16.4.tgz", + "integrity": "sha512-GkhjAaQ8oUTOKE4g4gsZ0u8K/IHU1+2WQSgS1TwTcYvL+sjbaQjNHFXbOJ6kgqGHIO1DfUhI/Sphi9GkRT9K+Q==", "cpu": [ "arm" ], @@ -486,9 +499,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.1.tgz", - "integrity": "sha512-Y/9OHLjzkunF+KGEoJr3heiD5X9OLa8sbT1lm0NYeKyaM3oMhhQFvPB0bNZYJwlq93j8Z6wSxh9+cyKQaxS7PQ==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.16.4.tgz", + "integrity": "sha512-Bvm6D+NPbGMQOcxvS1zUl8H7DWlywSXsphAeOnVeiZLQ+0J6Is8T7SrjGTH29KtYkiY9vld8ZnpV3G2EPbom+w==", "cpu": [ "arm64" ], @@ -499,9 +512,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.1.tgz", - "integrity": "sha512-+kecg3FY84WadgcuSVm6llrABOdQAEbNdnpi5X3UwWiFVhZIZvKgGrF7kmLguvxHNQy+UuRV66cLVl3S+Rkt+Q==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.16.4.tgz", + "integrity": "sha512-i5d64MlnYBO9EkCOGe5vPR/EeDwjnKOGGdd7zKFhU5y8haKhQZTN2DgVtpODDMxUr4t2K90wTUJg7ilgND6bXw==", "cpu": [ "arm64" ], @@ -512,9 +525,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.1.tgz", - "integrity": "sha512-2pYRzEjVqq2TB/UNv47BV/8vQiXkFGVmPFwJb+1E0IFFZbIX8/jo1olxqqMbo6xCXf8kabANhp5bzCij2tFLUA==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.16.4.tgz", + "integrity": "sha512-WZupV1+CdUYehaZqjaFTClJI72fjJEgTXdf4NbW69I9XyvdmztUExBtcI2yIIU6hJtYvtwS6pkTkHJz+k08mAQ==", "cpu": [ "x64" ], @@ -525,9 +538,22 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.1.tgz", - "integrity": "sha512-mS6wQ6Do6/wmrF9aTFVpIJ3/IDXhg1EZcQFYHZLHqw6AzMBjTHWnCG35HxSqUNphh0EHqSM6wRTT8HsL1C0x5g==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.16.4.tgz", + "integrity": "sha512-ADm/xt86JUnmAfA9mBqFcRp//RVRt1ohGOYF6yL+IFCYqOBNwy5lbEK05xTsEoJq+/tJzg8ICUtS82WinJRuIw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.16.4.tgz", + "integrity": "sha512-tJfJaXPiFAG+Jn3cutp7mCs1ePltuAgRqdDZrzb1aeE3TktWWJ+g7xK9SNlaSUFw6IU4QgOxAY4rA+wZUT5Wfg==", "cpu": [ "arm" ], @@ -538,9 +564,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.1.tgz", - "integrity": "sha512-p9rGKYkHdFMzhckOTFubfxgyIO1vw//7IIjBBRVzyZebWlzRLeNhqxuSaZ7kCEKVkm/kuC9fVRW9HkC/zNRG2w==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.16.4.tgz", + "integrity": "sha512-7dy1BzQkgYlUTapDTvK997cgi0Orh5Iu7JlZVBy1MBURk7/HSbHkzRnXZa19ozy+wwD8/SlpJnOOckuNZtJR9w==", "cpu": [ "arm64" ], @@ -551,9 +577,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.1.tgz", - "integrity": "sha512-nDY6Yz5xS/Y4M2i9JLQd3Rofh5OR8Bn8qe3Mv/qCVpHFlwtZSBYSPaU4mrGazWkXrdQ98GB//H0BirGR/SKFSw==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.16.4.tgz", + "integrity": "sha512-zsFwdUw5XLD1gQe0aoU2HVceI6NEW7q7m05wA46eUAyrkeNYExObfRFQcvA6zw8lfRc5BHtan3tBpo+kqEOxmg==", "cpu": [ "arm64" ], @@ -564,11 +590,11 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.1.tgz", - "integrity": "sha512-im7HE4VBL+aDswvcmfx88Mp1soqL9OBsdDBU8NqDEYtkri0qV0THhQsvZtZeNNlLeCUQ16PZyv7cqutjDF35qw==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.16.4.tgz", + "integrity": "sha512-p8C3NnxXooRdNrdv6dBmRTddEapfESEUflpICDNKXpHvTjRRq1J82CbU5G3XfebIZyI3B0s074JHMWD36qOW6w==", "cpu": [ - "ppc64le" + "ppc64" ], "dev": true, "optional": true, @@ -577,9 +603,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.1.tgz", - "integrity": "sha512-RWdiHuAxWmzPJgaHJdpvUUlDz8sdQz4P2uv367T2JocdDa98iRw2UjIJ4QxSyt077mXZT2X6pKfT2iYtVEvOFw==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.16.4.tgz", + "integrity": "sha512-Lh/8ckoar4s4Id2foY7jNgitTOUQczwMWNYi+Mjt0eQ9LKhr6sK477REqQkmy8YHY3Ca3A2JJVdXnfb3Rrwkng==", "cpu": [ "riscv64" ], @@ -590,9 +616,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.1.tgz", - "integrity": "sha512-VMgaGQ5zRX6ZqV/fas65/sUGc9cPmsntq2FiGmayW9KMNfWVG/j0BAqImvU4KTeOOgYSf1F+k6at1UfNONuNjA==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.16.4.tgz", + "integrity": "sha512-1xwwn9ZCQYuqGmulGsTZoKrrn0z2fAur2ujE60QgyDpHmBbXbxLaQiEvzJWDrscRq43c8DnuHx3QorhMTZgisQ==", "cpu": [ "s390x" ], @@ -603,9 +629,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.1.tgz", - "integrity": "sha512-9Q7DGjZN+hTdJomaQ3Iub4m6VPu1r94bmK2z3UeWP3dGUecRC54tmVu9vKHTm1bOt3ASoYtEz6JSRLFzrysKlA==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.16.4.tgz", + "integrity": "sha512-LuOGGKAJ7dfRtxVnO1i3qWc6N9sh0Em/8aZ3CezixSTM+E9Oq3OvTsvC4sm6wWjzpsIlOCnZjdluINKESflJLA==", "cpu": [ "x64" ], @@ -616,9 +642,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.1.tgz", - "integrity": "sha512-JNEG/Ti55413SsreTguSx0LOVKX902OfXIKVg+TCXO6Gjans/k9O6ww9q3oLGjNDaTLxM+IHFMeXy/0RXL5R/g==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.16.4.tgz", + "integrity": "sha512-ch86i7KkJKkLybDP2AtySFTRi5fM3KXp0PnHocHuJMdZwu7BuyIKi35BE9guMlmTpwwBTB3ljHj9IQXnTCD0vA==", "cpu": [ "x64" ], @@ -629,9 +655,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.1.tgz", - "integrity": "sha512-ryS22I9y0mumlLNwDFYZRDFLwWh3aKaC72CWjFcFvxK0U6v/mOkM5Up1bTbCRAhv3kEIwW2ajROegCIQViUCeA==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.16.4.tgz", + "integrity": "sha512-Ma4PwyLfOWZWayfEsNQzTDBVW8PZ6TUUN1uFTBQbF2Chv/+sjenE86lpiEwj2FiviSmSZ4Ap4MaAfl1ciF4aSA==", "cpu": [ "arm64" ], @@ -642,9 +668,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.1.tgz", - "integrity": "sha512-TdloItiGk+T0mTxKx7Hp279xy30LspMso+GzQvV2maYePMAWdmrzqSNZhUpPj3CGw12aGj57I026PgLCTu8CGg==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.16.4.tgz", + "integrity": "sha512-9m/ZDrQsdo/c06uOlP3W9G2ENRVzgzbSXmXHT4hwVaDQhYcRpi9bgBT0FTG9OhESxwK0WjQxYOSfv40cU+T69w==", "cpu": [ "ia32" ], @@ -655,9 +681,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.1.tgz", - "integrity": "sha512-wQGI+LY/Py20zdUPq+XCem7JcPOyzIJBm3dli+56DJsQOHbnXZFEwgmnC6el1TPAfC8lBT3m+z69RmLykNUbew==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.16.4.tgz", + "integrity": "sha512-YunpoOAyGLDseanENHmbFvQSfVL5BxW3k7hhy0eN4rb3gS/ct75dVD0EXOWIqFT/nE8XYW6LP6vz6ctKRi0k9A==", "cpu": [ "x64" ], @@ -1387,17 +1413,18 @@ } }, "node_modules/eslint": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.0.0.tgz", - "integrity": "sha512-IMryZ5SudxzQvuod6rUdIUz29qFItWx281VhtFVc2Psy/ZhlCeD/5DT6lBIJ4H3G+iamGJoTln1v+QSuPw0p7Q==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.1.1.tgz", + "integrity": "sha512-b4cRQ0BeZcSEzPpY2PjFY70VbO32K7BStTGtBsnIGdTSEEQzBi8hPBcGQmTG2zUvFr9uLe0TK42bw8YszuHEqg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^3.0.2", - "@eslint/js": "9.0.0", - "@humanwhocodes/config-array": "^0.12.3", + "@eslint/js": "9.1.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.2.3", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.12.4", "chalk": "^4.0.0", @@ -1413,7 +1440,6 @@ "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", @@ -1765,12 +1791,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2401,12 +2421,12 @@ "integrity": "sha512-yyVAOFKTAElc7KdLt2+UKGExNYwYb/Y/WE9i+1ezCQsJE8gbKSjewfpRqK2nQgZ4d4hhAAGgDCOcIZVilqE5UA==" }, "node_modules/playwright": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.0.tgz", - "integrity": "sha512-SiOKHbVjTSf6wHuGCbqrEyzlm6qvXcv7mENP+OZon1I07brfZLGdfWV0l/efAzVx7TF3Z45ov1gPEkku9q25YQ==", + "version": "1.43.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.1.tgz", + "integrity": "sha512-V7SoH0ai2kNt1Md9E3Gwas5B9m8KR2GVvwZnAI6Pg0m3sh7UvgiYhRrhsziCmqMJNouPckiOhk8T+9bSAK0VIA==", "dev": true, "dependencies": { - "playwright-core": "1.43.0" + "playwright-core": "1.43.1" }, "bin": { "playwright": "cli.js" @@ -2419,9 +2439,9 @@ } }, "node_modules/playwright-core": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.0.tgz", - "integrity": "sha512-iWFjyBUH97+pUFiyTqSLd8cDMMOS0r2ZYz2qEsPjH8/bX++sbIJT35MSwKnp1r/OQBAqC5XO99xFbJ9XClhf4w==", + "version": "1.43.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.1.tgz", + "integrity": "sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -2445,9 +2465,9 @@ } }, "node_modules/polyscript": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.3.tgz", - "integrity": "sha512-aekNrFZzdLe0KQuSMWKFsUwkv414hIIjDgqzCbEXl4l5xZA8vgiv+jFFOZnkJk9/HeybLRPJBRdlhBxfdKVV0Q==", + "version": "0.12.6", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.6.tgz", + "integrity": "sha512-tvVuPp+ygyDSqtLiNbbGZRUHvBz594xAao0bq0fg6JYcnidmuhZhgFiwwMC3tw/eJKKlBPKKc60UnYr6lvNH4A==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", @@ -3132,9 +3152,9 @@ } }, "node_modules/rollup": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.1.tgz", - "integrity": "sha512-4LnHSdd3QK2pa1J6dFbfm1HN0D7vSK/ZuZTsdyUAlA6Rr1yTouUTL13HaDOGJVgby461AhrNGBS7sCGXXtT+SA==", + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.16.4.tgz", + "integrity": "sha512-kuaTJSUbz+Wsb2ATGvEknkI12XV40vIiHmLuFlejoo7HtDok/O5eDDD0UpCVY5bBX5U5RYo8wWP83H7ZsqVEnA==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -3147,21 +3167,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.14.1", - "@rollup/rollup-android-arm64": "4.14.1", - "@rollup/rollup-darwin-arm64": "4.14.1", - "@rollup/rollup-darwin-x64": "4.14.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.14.1", - "@rollup/rollup-linux-arm64-gnu": "4.14.1", - "@rollup/rollup-linux-arm64-musl": "4.14.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.14.1", - "@rollup/rollup-linux-riscv64-gnu": "4.14.1", - "@rollup/rollup-linux-s390x-gnu": "4.14.1", - "@rollup/rollup-linux-x64-gnu": "4.14.1", - "@rollup/rollup-linux-x64-musl": "4.14.1", - "@rollup/rollup-win32-arm64-msvc": "4.14.1", - "@rollup/rollup-win32-ia32-msvc": "4.14.1", - "@rollup/rollup-win32-x64-msvc": "4.14.1", + "@rollup/rollup-android-arm-eabi": "4.16.4", + "@rollup/rollup-android-arm64": "4.16.4", + "@rollup/rollup-darwin-arm64": "4.16.4", + "@rollup/rollup-darwin-x64": "4.16.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.16.4", + "@rollup/rollup-linux-arm-musleabihf": "4.16.4", + "@rollup/rollup-linux-arm64-gnu": "4.16.4", + "@rollup/rollup-linux-arm64-musl": "4.16.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.16.4", + "@rollup/rollup-linux-riscv64-gnu": "4.16.4", + "@rollup/rollup-linux-s390x-gnu": "4.16.4", + "@rollup/rollup-linux-x64-gnu": "4.16.4", + "@rollup/rollup-linux-x64-musl": "4.16.4", + "@rollup/rollup-win32-arm64-msvc": "4.16.4", + "@rollup/rollup-win32-ia32-msvc": "4.16.4", + "@rollup/rollup-win32-x64-msvc": "4.16.4", "fsevents": "~2.3.2" } }, @@ -3539,9 +3560,9 @@ "integrity": "sha512-fLIydlJy7IG9XL4wjRwEcKhxx/ekLXiWiMvcGo01cOMF+TN+5ZqajM1mRNRz2bNNi1bzou2yofhjZEQi7kgl9A==" }, "node_modules/typescript": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", - "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index b9c229f054a..ddcad7cf4c7 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.21", + "version": "0.4.22", "type": "module", "description": "PyScript", "module": "./index.js", @@ -42,18 +42,18 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.3", + "polyscript": "^0.12.6", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" }, "devDependencies": { - "@codemirror/commands": "^6.3.3", + "@codemirror/commands": "^6.5.0", "@codemirror/lang-python": "^6.1.5", "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.26.2", - "@playwright/test": "^1.43.0", + "@codemirror/view": "^6.26.3", + "@playwright/test": "^1.43.1", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", @@ -62,12 +62,12 @@ "@xterm/addon-web-links": "^0.11.0", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^9.0.0", - "rollup": "^4.14.1", + "eslint": "^9.1.1", + "rollup": "^4.16.4", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", - "typescript": "^5.4.4", + "typescript": "^5.4.5", "xterm": "^5.3.0", "xterm-readline": "^1.1.1" }, From 5b4e8527da3ea87052d1fea36e352971d31f2176 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Thu, 2 May 2024 11:47:52 +0200 Subject: [PATCH 040/179] Fix #2040 - Polyscript update to provide config dictionary (#2041) * Fix #2040 - Polyscript update to provide config dictionary * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/package-lock.json | 156 +++++++++--------- pyscript.core/package.json | 8 +- pyscript.core/src/stdlib/pyscript/__init__.py | 1 + pyscript.core/src/stdlib/pyscript/magic_js.py | 4 + pyscript.core/test/config-url.html | 8 + 5 files changed, 95 insertions(+), 82 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 278a4757a69..95e9ca6b267 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,24 +1,24 @@ { "name": "@pyscript/core", - "version": "0.4.22", + "version": "0.4.24", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.22", + "version": "0.4.24", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.6", + "polyscript": "^0.12.7", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" }, "devDependencies": { "@codemirror/commands": "^6.5.0", - "@codemirror/lang-python": "^6.1.5", + "@codemirror/lang-python": "^6.1.6", "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.1", "@codemirror/view": "^6.26.3", @@ -32,7 +32,7 @@ "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^9.1.1", - "rollup": "^4.16.4", + "rollup": "^4.17.2", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", @@ -81,9 +81,9 @@ } }, "node_modules/@codemirror/lang-python": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.5.tgz", - "integrity": "sha512-hCm+8X6wrnXJCGf+QhmFu1AXkdTVG7dHy0Ly6SI1N3SRPptaMvwX6oNQonOXOMPvmcjiB0xq342KAxX3BYpijw==", + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.6.tgz", + "integrity": "sha512-ai+01WfZhWqM92UqjnvorkxosZ2aq2u28kHvr+N3gu012XqY2CThD67JPMHnGceRfXPDBmn1HnyqowdpF57bNg==", "dev": true, "dependencies": { "@codemirror/autocomplete": "^6.3.2", @@ -486,9 +486,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.16.4.tgz", - "integrity": "sha512-GkhjAaQ8oUTOKE4g4gsZ0u8K/IHU1+2WQSgS1TwTcYvL+sjbaQjNHFXbOJ6kgqGHIO1DfUhI/Sphi9GkRT9K+Q==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz", + "integrity": "sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==", "cpu": [ "arm" ], @@ -499,9 +499,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.16.4.tgz", - "integrity": "sha512-Bvm6D+NPbGMQOcxvS1zUl8H7DWlywSXsphAeOnVeiZLQ+0J6Is8T7SrjGTH29KtYkiY9vld8ZnpV3G2EPbom+w==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz", + "integrity": "sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==", "cpu": [ "arm64" ], @@ -512,9 +512,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.16.4.tgz", - "integrity": "sha512-i5d64MlnYBO9EkCOGe5vPR/EeDwjnKOGGdd7zKFhU5y8haKhQZTN2DgVtpODDMxUr4t2K90wTUJg7ilgND6bXw==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz", + "integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==", "cpu": [ "arm64" ], @@ -525,9 +525,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.16.4.tgz", - "integrity": "sha512-WZupV1+CdUYehaZqjaFTClJI72fjJEgTXdf4NbW69I9XyvdmztUExBtcI2yIIU6hJtYvtwS6pkTkHJz+k08mAQ==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz", + "integrity": "sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==", "cpu": [ "x64" ], @@ -538,9 +538,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.16.4.tgz", - "integrity": "sha512-ADm/xt86JUnmAfA9mBqFcRp//RVRt1ohGOYF6yL+IFCYqOBNwy5lbEK05xTsEoJq+/tJzg8ICUtS82WinJRuIw==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz", + "integrity": "sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==", "cpu": [ "arm" ], @@ -551,9 +551,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.16.4.tgz", - "integrity": "sha512-tJfJaXPiFAG+Jn3cutp7mCs1ePltuAgRqdDZrzb1aeE3TktWWJ+g7xK9SNlaSUFw6IU4QgOxAY4rA+wZUT5Wfg==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz", + "integrity": "sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==", "cpu": [ "arm" ], @@ -564,9 +564,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.16.4.tgz", - "integrity": "sha512-7dy1BzQkgYlUTapDTvK997cgi0Orh5Iu7JlZVBy1MBURk7/HSbHkzRnXZa19ozy+wwD8/SlpJnOOckuNZtJR9w==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz", + "integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==", "cpu": [ "arm64" ], @@ -577,9 +577,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.16.4.tgz", - "integrity": "sha512-zsFwdUw5XLD1gQe0aoU2HVceI6NEW7q7m05wA46eUAyrkeNYExObfRFQcvA6zw8lfRc5BHtan3tBpo+kqEOxmg==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz", + "integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==", "cpu": [ "arm64" ], @@ -590,9 +590,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.16.4.tgz", - "integrity": "sha512-p8C3NnxXooRdNrdv6dBmRTddEapfESEUflpICDNKXpHvTjRRq1J82CbU5G3XfebIZyI3B0s074JHMWD36qOW6w==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz", + "integrity": "sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==", "cpu": [ "ppc64" ], @@ -603,9 +603,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.16.4.tgz", - "integrity": "sha512-Lh/8ckoar4s4Id2foY7jNgitTOUQczwMWNYi+Mjt0eQ9LKhr6sK477REqQkmy8YHY3Ca3A2JJVdXnfb3Rrwkng==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz", + "integrity": "sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==", "cpu": [ "riscv64" ], @@ -616,9 +616,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.16.4.tgz", - "integrity": "sha512-1xwwn9ZCQYuqGmulGsTZoKrrn0z2fAur2ujE60QgyDpHmBbXbxLaQiEvzJWDrscRq43c8DnuHx3QorhMTZgisQ==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz", + "integrity": "sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==", "cpu": [ "s390x" ], @@ -629,9 +629,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.16.4.tgz", - "integrity": "sha512-LuOGGKAJ7dfRtxVnO1i3qWc6N9sh0Em/8aZ3CezixSTM+E9Oq3OvTsvC4sm6wWjzpsIlOCnZjdluINKESflJLA==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz", + "integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==", "cpu": [ "x64" ], @@ -642,9 +642,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.16.4.tgz", - "integrity": "sha512-ch86i7KkJKkLybDP2AtySFTRi5fM3KXp0PnHocHuJMdZwu7BuyIKi35BE9guMlmTpwwBTB3ljHj9IQXnTCD0vA==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz", + "integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==", "cpu": [ "x64" ], @@ -655,9 +655,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.16.4.tgz", - "integrity": "sha512-Ma4PwyLfOWZWayfEsNQzTDBVW8PZ6TUUN1uFTBQbF2Chv/+sjenE86lpiEwj2FiviSmSZ4Ap4MaAfl1ciF4aSA==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz", + "integrity": "sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==", "cpu": [ "arm64" ], @@ -668,9 +668,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.16.4.tgz", - "integrity": "sha512-9m/ZDrQsdo/c06uOlP3W9G2ENRVzgzbSXmXHT4hwVaDQhYcRpi9bgBT0FTG9OhESxwK0WjQxYOSfv40cU+T69w==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz", + "integrity": "sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==", "cpu": [ "ia32" ], @@ -681,9 +681,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.16.4.tgz", - "integrity": "sha512-YunpoOAyGLDseanENHmbFvQSfVL5BxW3k7hhy0eN4rb3gS/ct75dVD0EXOWIqFT/nE8XYW6LP6vz6ctKRi0k9A==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz", + "integrity": "sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==", "cpu": [ "x64" ], @@ -2465,9 +2465,9 @@ } }, "node_modules/polyscript": { - "version": "0.12.6", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.6.tgz", - "integrity": "sha512-tvVuPp+ygyDSqtLiNbbGZRUHvBz594xAao0bq0fg6JYcnidmuhZhgFiwwMC3tw/eJKKlBPKKc60UnYr6lvNH4A==", + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.7.tgz", + "integrity": "sha512-Aaw/UCFNEuBkEcT00wok8ks+llVINunx98x4FdXZueUlFsr5+B41OVV3DptsJ3+7tzjqmJwhxe7cBTpMolLG/Q==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", @@ -3152,9 +3152,9 @@ } }, "node_modules/rollup": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.16.4.tgz", - "integrity": "sha512-kuaTJSUbz+Wsb2ATGvEknkI12XV40vIiHmLuFlejoo7HtDok/O5eDDD0UpCVY5bBX5U5RYo8wWP83H7ZsqVEnA==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz", + "integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -3167,22 +3167,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.16.4", - "@rollup/rollup-android-arm64": "4.16.4", - "@rollup/rollup-darwin-arm64": "4.16.4", - "@rollup/rollup-darwin-x64": "4.16.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.16.4", - "@rollup/rollup-linux-arm-musleabihf": "4.16.4", - "@rollup/rollup-linux-arm64-gnu": "4.16.4", - "@rollup/rollup-linux-arm64-musl": "4.16.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.16.4", - "@rollup/rollup-linux-riscv64-gnu": "4.16.4", - "@rollup/rollup-linux-s390x-gnu": "4.16.4", - "@rollup/rollup-linux-x64-gnu": "4.16.4", - "@rollup/rollup-linux-x64-musl": "4.16.4", - "@rollup/rollup-win32-arm64-msvc": "4.16.4", - "@rollup/rollup-win32-ia32-msvc": "4.16.4", - "@rollup/rollup-win32-x64-msvc": "4.16.4", + "@rollup/rollup-android-arm-eabi": "4.17.2", + "@rollup/rollup-android-arm64": "4.17.2", + "@rollup/rollup-darwin-arm64": "4.17.2", + "@rollup/rollup-darwin-x64": "4.17.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.17.2", + "@rollup/rollup-linux-arm-musleabihf": "4.17.2", + "@rollup/rollup-linux-arm64-gnu": "4.17.2", + "@rollup/rollup-linux-arm64-musl": "4.17.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.17.2", + "@rollup/rollup-linux-riscv64-gnu": "4.17.2", + "@rollup/rollup-linux-s390x-gnu": "4.17.2", + "@rollup/rollup-linux-x64-gnu": "4.17.2", + "@rollup/rollup-linux-x64-musl": "4.17.2", + "@rollup/rollup-win32-arm64-msvc": "4.17.2", + "@rollup/rollup-win32-ia32-msvc": "4.17.2", + "@rollup/rollup-win32-x64-msvc": "4.17.2", "fsevents": "~2.3.2" } }, diff --git a/pyscript.core/package.json b/pyscript.core/package.json index ddcad7cf4c7..887cb02965e 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.22", + "version": "0.4.24", "type": "module", "description": "PyScript", "module": "./index.js", @@ -42,14 +42,14 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.6", + "polyscript": "^0.12.7", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" }, "devDependencies": { "@codemirror/commands": "^6.5.0", - "@codemirror/lang-python": "^6.1.5", + "@codemirror/lang-python": "^6.1.6", "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.1", "@codemirror/view": "^6.26.3", @@ -63,7 +63,7 @@ "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^9.1.1", - "rollup": "^4.16.4", + "rollup": "^4.17.2", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", diff --git a/pyscript.core/src/stdlib/pyscript/__init__.py b/pyscript.core/src/stdlib/pyscript/__init__.py index 8e3c53ee22b..dc0d83040ea 100644 --- a/pyscript.core/src/stdlib/pyscript/__init__.py +++ b/pyscript.core/src/stdlib/pyscript/__init__.py @@ -34,6 +34,7 @@ from pyscript.magic_js import ( RUNNING_IN_WORKER, PyWorker, + config, current_target, document, js_modules, diff --git a/pyscript.core/src/stdlib/pyscript/magic_js.py b/pyscript.core/src/stdlib/pyscript/magic_js.py index 49fd9c96080..845799134a9 100644 --- a/pyscript.core/src/stdlib/pyscript/magic_js.py +++ b/pyscript.core/src/stdlib/pyscript/magic_js.py @@ -1,11 +1,15 @@ +import json import sys import js as globalThis +from polyscript import config as _config from polyscript import js_modules from pyscript.util import NotSupported RUNNING_IN_WORKER = not hasattr(globalThis, "document") +config = json.loads(globalThis.JSON.stringify(_config)) + # allow `from pyscript.js_modules.xxx import yyy` class JSModule: diff --git a/pyscript.core/test/config-url.html b/pyscript.core/test/config-url.html index eb0ad1ff31c..566de6145da 100644 --- a/pyscript.core/test/config-url.html +++ b/pyscript.core/test/config-url.html @@ -8,9 +8,17 @@ From 1a05ea5fd20c93997e16dc1bdea0ca0d5407b439 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Fri, 3 May 2024 11:35:05 +0200 Subject: [PATCH 041/179] Fix #2031 - Add pyscript.WebSocket to the mix (#2042) * Fix #2031 - Add pyscript.WebSocket to the mix * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Working on a test case anyone can run * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/package-lock.json | 139 +++++++++++++++++- pyscript.core/package.json | 6 +- pyscript.core/src/stdlib/pyscript/__init__.py | 1 + pyscript.core/src/stdlib/pyscript/fetch.py | 13 +- pyscript.core/src/stdlib/pyscript/util.py | 12 ++ .../src/stdlib/pyscript/websocket.py | 64 ++++++++ pyscript.core/test/ws.spec.js | 6 + pyscript.core/test/ws/index.html | 31 ++++ pyscript.core/test/ws/index.js | 33 +++++ pyscript.core/types/stdlib/pyscript.d.ts | 1 + 10 files changed, 292 insertions(+), 14 deletions(-) create mode 100644 pyscript.core/src/stdlib/pyscript/websocket.py create mode 100644 pyscript.core/test/ws.spec.js create mode 100644 pyscript.core/test/ws/index.html create mode 100644 pyscript.core/test/ws/index.js diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 95e9ca6b267..09ec3dec822 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.24", + "version": "0.4.25", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.24", + "version": "0.4.25", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", @@ -29,6 +29,7 @@ "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", + "bun": "^1.1.6", "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^9.1.1", @@ -376,6 +377,110 @@ "node": ">= 8" } }, + "node_modules/@oven/bun-darwin-aarch64": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.6.tgz", + "integrity": "sha512-1GQb0gugo/qndj5ehktgHRAoyCM5fWisbLEBLq6YorHTc71T5cqFWCQ6uPcfy3k9cxEDd8tUpejekyi8EsCxgw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oven/bun-darwin-x64": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.6.tgz", + "integrity": "sha512-NK8py4eJNkN6iNfvaM8pzmmNNNkbyzRvnc/pmrDLFPPfgJklJ2esm8OBCALDe9RvP1USDo8H1I4IXCtQQIu3SQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oven/bun-darwin-x64-baseline": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.6.tgz", + "integrity": "sha512-amG6o1y1ksjwOUKS97IW5VQE/UPfEa4Edket1+VUa0UGvo/0z3+2gVYF3Bt+pZA45glJKXM3nI9wYlmVeE/AcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oven/bun-linux-aarch64": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.6.tgz", + "integrity": "sha512-FOlZBeIrk7DlOsktWwahmxJwaKxCG9C+pKPMj8s+u08WhAKtfMBpgHvHsilBKE9W1twta+jB+geW4kU1KZSNZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oven/bun-linux-x64": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.6.tgz", + "integrity": "sha512-PN/5XSPCWCuIgOEhxWfx5ViVEY9ZfpEpJkadDiZi9IY17mb/aZVvt0Lll4doe6B7hjbglb1nI++GXcpqU/fonw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oven/bun-linux-x64-baseline": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.6.tgz", + "integrity": "sha512-a/Wx5ZTl0BDq9WH5nJfl8rw0YX5/dWmxmy3pYki6EBbwjcsA8iMzjkRpp5k8NEV2SpyaDMdS+xCb/HiaO4RWoQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oven/bun-windows-x64": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.6.tgz", + "integrity": "sha512-knJePhYbqtYv5RNUrnkMFrK4z3dDIPzom402yjSLkESZhsnO16xtLkULocV2yk0KDXKo2C3BqoZKHATCK6LxqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@oven/bun-windows-x64-baseline": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.6.tgz", + "integrity": "sha512-8VVPdKTYEsQPwlCasLWmTsHPcC9om9FaZlH9j7Gs9jBYje3FDXMyLI3DalVQ/VBY+uwQ8qoXhtDrh83nLuawhA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@playwright/test": { "version": "1.43.1", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.43.1.tgz", @@ -938,6 +1043,36 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bun": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.6.tgz", + "integrity": "sha512-0oKx5dVZ8LpsAvXdW2DTR5Zt3KS81Ifjx9T2ma7RjDPKbvGIlDXOPt++tr1SndxhFNFsMFeE4i6VKvlL7IR0Zw==", + "cpu": [ + "arm64", + "x64" + ], + "dev": true, + "hasInstallScript": true, + "os": [ + "darwin", + "linux", + "win32" + ], + "bin": { + "bun": "bin/bun.exe", + "bunx": "bin/bun.exe" + }, + "optionalDependencies": { + "@oven/bun-darwin-aarch64": "1.1.6", + "@oven/bun-darwin-x64": "1.1.6", + "@oven/bun-darwin-x64-baseline": "1.1.6", + "@oven/bun-linux-aarch64": "1.1.6", + "@oven/bun-linux-x64": "1.1.6", + "@oven/bun-linux-x64-baseline": "1.1.6", + "@oven/bun-windows-x64": "1.1.6", + "@oven/bun-windows-x64-baseline": "1.1.6" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 887cb02965e..7d8ff38983d 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.24", + "version": "0.4.25", "type": "module", "description": "PyScript", "module": "./index.js", @@ -26,7 +26,8 @@ "build:stdlib": "node rollup/stdlib.cjs", "build:3rd-party": "node rollup/3rd-party.cjs", "clean:3rd-party": "rm src/3rd-party/*.js && rm src/3rd-party/*.css", - "test:mpy": "static-handler --coi . 2>/dev/null & SH_PID=$!; EXIT_CODE=0; playwright test --fully-parallel test/ || EXIT_CODE=$?; kill $SH_PID 2>/dev/null; exit $EXIT_CODE", + "test:mpy": "static-handler --coi . 2>/dev/null & SH_PID=$!; EXIT_CODE=0; playwright test --fully-parallel test/mpy.spec.js || EXIT_CODE=$?; kill $SH_PID 2>/dev/null; exit $EXIT_CODE", + "test:ws": "bun test/ws/index.js & playwright test test/ws.spec.js", "dev": "node dev.cjs", "release": "npm run build && npm run zip", "size": "echo -e \"\\033[1mdist/*.js file size\\033[0m\"; for js in $(ls dist/*.js); do cat $js | brotli > ._; echo -e \"\\033[2m$js:\\033[0m $(du -h --apparent-size ._ | sed -e 's/[[:space:]]*._//')\"; rm ._; done", @@ -60,6 +61,7 @@ "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", + "bun": "^1.1.6", "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^9.1.1", diff --git a/pyscript.core/src/stdlib/pyscript/__init__.py b/pyscript.core/src/stdlib/pyscript/__init__.py index dc0d83040ea..594e528b83f 100644 --- a/pyscript.core/src/stdlib/pyscript/__init__.py +++ b/pyscript.core/src/stdlib/pyscript/__init__.py @@ -41,6 +41,7 @@ sync, window, ) +from pyscript.websocket import WebSocket try: from pyscript.event_handling import when diff --git a/pyscript.core/src/stdlib/pyscript/fetch.py b/pyscript.core/src/stdlib/pyscript/fetch.py index 28764f551c9..cdcc81c6041 100644 --- a/pyscript.core/src/stdlib/pyscript/fetch.py +++ b/pyscript.core/src/stdlib/pyscript/fetch.py @@ -1,6 +1,7 @@ import json import js +from pyscript.util import as_bytearray ### wrap the response to grant Pythonic results @@ -12,14 +13,6 @@ def __init__(self, response): def __getattr__(self, attr): return getattr(self._response, attr) - def _as_bytearray(self, buffer): - ui8a = js.Uint8Array.new(buffer) - size = ui8a.length - ba = bytearray(size) - for i in range(0, size): - ba[i] = ui8a[i] - return ba - # exposed methods with Pythonic results async def arrayBuffer(self): buffer = await self._response.arrayBuffer() @@ -27,14 +20,14 @@ async def arrayBuffer(self): if hasattr(buffer, "to_py"): return buffer.to_py() # shims in MicroPython - return memoryview(self._as_bytearray(buffer)) + return memoryview(as_bytearray(buffer)) async def blob(self): return await self._response.blob() async def bytearray(self): buffer = await self._response.arrayBuffer() - return self._as_bytearray(buffer) + return as_bytearray(buffer) async def json(self): return json.loads(await self.text()) diff --git a/pyscript.core/src/stdlib/pyscript/util.py b/pyscript.core/src/stdlib/pyscript/util.py index 8676f052fb6..ca96ea57c21 100644 --- a/pyscript.core/src/stdlib/pyscript/util.py +++ b/pyscript.core/src/stdlib/pyscript/util.py @@ -1,3 +1,15 @@ +import js + + +def as_bytearray(buffer): + ui8a = js.Uint8Array.new(buffer) + size = ui8a.length + ba = bytearray(size) + for i in range(0, size): + ba[i] = ui8a[i] + return ba + + class NotSupported: """ Small helper that raises exceptions if you try to get/set any attribute on diff --git a/pyscript.core/src/stdlib/pyscript/websocket.py b/pyscript.core/src/stdlib/pyscript/websocket.py new file mode 100644 index 00000000000..2e351bcde98 --- /dev/null +++ b/pyscript.core/src/stdlib/pyscript/websocket.py @@ -0,0 +1,64 @@ +import js +from pyscript.util import as_bytearray + +code = "code" +protocols = "protocols" +reason = "reason" + + +class EventMessage: + def __init__(self, event): + self._event = event + + def __getattr__(self, attr): + value = getattr(self._event, attr) + + if attr == "data" and not isinstance(value, str): + if hasattr(value, "to_py"): + return value.to_py() + # shims in MicroPython + return memoryview(as_bytearray(value)) + + return value + + +class WebSocket(object): + CONNECTING = 0 + OPEN = 1 + CLOSING = 2 + CLOSED = 3 + + def __init__(self, **kw): + url = kw["url"] + socket = None + if protocols in kw: + socket = js.WebSocket.new(url, kw[protocols]) + else: + socket = js.WebSocket.new(url) + object.__setattr__(self, "_ws", socket) + + def __getattr__(self, attr): + return getattr(self._ws, attr) + + def __setattr__(self, attr, value): + if attr == "onmessage": + setattr(self._ws, attr, lambda e: value(EventMessage(e))) + else: + setattr(self._ws, attr, value) + + def close(self, **kw): + if code in kw and reason in kw: + self._ws.close(kw[code], kw[reason]) + elif code in kw: + self._ws.close(kw[code]) + else: + self._ws.close() + + def send(self, data): + if isinstance(data, str): + self._ws.send(data) + else: + buffer = js.Uint8Array.new(len(data)) + for pos, b in enumerate(data): + buffer[pos] = b + self._ws.send(buffer) diff --git a/pyscript.core/test/ws.spec.js b/pyscript.core/test/ws.spec.js new file mode 100644 index 00000000000..669be352f8a --- /dev/null +++ b/pyscript.core/test/ws.spec.js @@ -0,0 +1,6 @@ +import { test, expect } from '@playwright/test'; + +test('MicroPython WebSocket', async ({ page }) => { + await page.goto('http://localhost:5037/'); + await page.waitForSelector('html.ok'); +}); diff --git a/pyscript.core/test/ws/index.html b/pyscript.core/test/ws/index.html new file mode 100644 index 00000000000..fe8ad7291e6 --- /dev/null +++ b/pyscript.core/test/ws/index.html @@ -0,0 +1,31 @@ + + + + + + + + + + + + diff --git a/pyscript.core/test/ws/index.js b/pyscript.core/test/ws/index.js new file mode 100644 index 00000000000..7db7f7c528a --- /dev/null +++ b/pyscript.core/test/ws/index.js @@ -0,0 +1,33 @@ +import { serve, file } from 'bun'; + +import path, { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; + +const dir = dirname(fileURLToPath(import.meta.url)); + +serve({ + port: 5037, + fetch(req, server) { + if (server.upgrade(req)) return; + const url = new URL(req.url); + let { pathname } = url; + if (pathname === '/') pathname = '/index.html'; + else if (/^\/dist\//.test(pathname)) pathname = `/../..${pathname}`; + else if (pathname === '/favicon.ico') + return new Response('Not Found', { status: 404 }); + const response = new Response(file(`${dir}${pathname}`)); + const { headers } = response; + headers.set('Cross-Origin-Opener-Policy', 'same-origin'); + headers.set('Cross-Origin-Embedder-Policy', 'require-corp'); + headers.set('Cross-Origin-Resource-Policy', 'cross-origin'); + return response; + }, + websocket: { + message(ws, message) { + ws.send(message); + }, + close() { + process.exit(0); + } + }, +}); diff --git a/pyscript.core/types/stdlib/pyscript.d.ts b/pyscript.core/types/stdlib/pyscript.d.ts index 648b493ef12..0a9893a6f13 100644 --- a/pyscript.core/types/stdlib/pyscript.d.ts +++ b/pyscript.core/types/stdlib/pyscript.d.ts @@ -7,6 +7,7 @@ declare namespace _default { "ffi.py": string; "magic_js.py": string; "util.py": string; + "websocket.py": string; }; let pyweb: { "__init__.py": string; From d1d1c5740fb3dcdf90339038cdd65717028b003d Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Fri, 3 May 2024 12:23:57 +0200 Subject: [PATCH 042/179] Fixed py-editor offline use case (#2043) --- pyscript.core/package-lock.json | 4 ++-- pyscript.core/package.json | 2 +- pyscript.core/src/plugins/py-editor.js | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 09ec3dec822..50a1e31cd15 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.25", + "version": "0.4.26", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.25", + "version": "0.4.26", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 7d8ff38983d..73bde472c79 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.25", + "version": "0.4.26", "type": "module", "description": "PyScript", "module": "./index.js", diff --git a/pyscript.core/src/plugins/py-editor.js b/pyscript.core/src/plugins/py-editor.js index 9a8284565c1..ee5ed5c3d6c 100644 --- a/pyscript.core/src/plugins/py-editor.js +++ b/pyscript.core/src/plugins/py-editor.js @@ -42,6 +42,8 @@ async function execute({ currentTarget }) { ? await import(/* webpackIgnore: true */ "../3rd-party/toml.js") : JSON; details.config = parse(await fetch(config).then((r) => r.text())); + const { interpreter } = details.config; + if (interpreter) details.version = interpreter; } const xworker = XWorker.call(new Hook(null, hooks), srcLink, details); From c49cb9231b1cb859f76d95eb3fbecc1bc2488295 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Fri, 3 May 2024 16:34:21 +0200 Subject: [PATCH 043/179] Added listeners to the constructing kw options (#2044) --- pyscript.core/package-lock.json | 4 ++-- pyscript.core/package.json | 2 +- pyscript.core/src/stdlib/pyscript/websocket.py | 9 ++++++--- pyscript.core/test/ws/index.html | 10 ++++++---- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 50a1e31cd15..eecbd82a015 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.26", + "version": "0.4.27", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.26", + "version": "0.4.27", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 73bde472c79..95d5cd74814 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.26", + "version": "0.4.27", "type": "module", "description": "PyScript", "module": "./index.js", diff --git a/pyscript.core/src/stdlib/pyscript/websocket.py b/pyscript.core/src/stdlib/pyscript/websocket.py index 2e351bcde98..7ce46ddd049 100644 --- a/pyscript.core/src/stdlib/pyscript/websocket.py +++ b/pyscript.core/src/stdlib/pyscript/websocket.py @@ -30,21 +30,24 @@ class WebSocket(object): def __init__(self, **kw): url = kw["url"] - socket = None if protocols in kw: socket = js.WebSocket.new(url, kw[protocols]) else: socket = js.WebSocket.new(url) object.__setattr__(self, "_ws", socket) + for t in ["onclose", "onerror", "onmessage", "onopen"]: + if t in kw: + socket[t] = kw[t] + def __getattr__(self, attr): return getattr(self._ws, attr) def __setattr__(self, attr, value): if attr == "onmessage": - setattr(self._ws, attr, lambda e: value(EventMessage(e))) + self._ws[attr] = lambda e: value(EventMessage(e)) else: - setattr(self._ws, attr, value) + self._ws[attr] = value def close(self, **kw): if code in kw and reason in kw: diff --git a/pyscript.core/test/ws/index.html b/pyscript.core/test/ws/index.html index fe8ad7291e6..a850f0eaa60 100644 --- a/pyscript.core/test/ws/index.html +++ b/pyscript.core/test/ws/index.html @@ -22,10 +22,12 @@ print(event.type) document.documentElement.classList.add("ok") - ws = WebSocket(url="ws://localhost:5037/") - ws.onopen = onopen - ws.onmessage = onmessage - ws.onclose = onclose + ws = WebSocket( + url="ws://localhost:5037/", + onopen=onopen, + onmessage=onmessage, + onclose=onclose + ) From 9bd473770893df6202c6b182f558c1cbf82c3799 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 09:42:28 +0200 Subject: [PATCH 044/179] [pre-commit.ci] pre-commit autoupdate (#2051) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v4.5.0 → v4.6.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.5.0...v4.6.0) - [github.com/psf/black: 24.3.0 → 24.4.2](https://github.com/psf/black/compare/24.3.0...24.4.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7434b43bff3..6240966201a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ ci: default_stages: [commit] repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: check-builtin-literals - id: check-case-conflict @@ -25,7 +25,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/psf/black - rev: 24.3.0 + rev: 24.4.2 hooks: - id: black exclude: pyscript\.core/src/stdlib/pyscript/__init__\.py From 8ec33817896290ea505f40d128bfb36927d49a58 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Tue, 7 May 2024 10:02:55 +0200 Subject: [PATCH 045/179] Even better PyEditor offline use case (#2050) * Even better PyEditor offline use case * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/package-lock.json | 124 ++++++++++++------------- pyscript.core/package.json | 10 +- pyscript.core/src/core.js | 5 +- pyscript.core/src/plugins/py-editor.js | 5 +- pyscript.core/types/core.d.ts | 1 + 5 files changed, 74 insertions(+), 71 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index eecbd82a015..eb9b483d0b9 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.4.27", + "version": "0.4.31", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.27", + "version": "0.4.31", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.7", + "polyscript": "^0.12.8", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -22,17 +22,17 @@ "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.1", "@codemirror/view": "^6.26.3", - "@playwright/test": "^1.43.1", + "@playwright/test": "^1.44.0", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", - "bun": "^1.1.6", + "bun": "^1.1.7", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^9.1.1", + "eslint": "^9.2.0", "rollup": "^4.17.2", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", @@ -195,9 +195,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.1.1.tgz", - "integrity": "sha512-5WoDz3Y19Bg2BnErkZTp0en+c/i9PvgFS7MBe1+m60HjFr0hrphlAGp4yzI7pxpt4xShln4ZyYp4neJm8hmOkQ==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.2.0.tgz", + "integrity": "sha512-ESiIudvhoYni+MdsI8oD7skpprZ89qKocwRM2KEvhhBJ9nl5MRh7BXU5GTod7Mdygq+AUl+QzId6iWJKR/wABA==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -378,9 +378,9 @@ } }, "node_modules/@oven/bun-darwin-aarch64": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.6.tgz", - "integrity": "sha512-1GQb0gugo/qndj5ehktgHRAoyCM5fWisbLEBLq6YorHTc71T5cqFWCQ6uPcfy3k9cxEDd8tUpejekyi8EsCxgw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.7.tgz", + "integrity": "sha512-6xH96IjcQlnbsGziUELOhewuobKyzcc+/mV1fSQkY8+c5crgca1nnArS8ja7GaduDWCGuSvMiURFUtf/EAZYtg==", "cpu": [ "arm64" ], @@ -391,9 +391,9 @@ ] }, "node_modules/@oven/bun-darwin-x64": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.6.tgz", - "integrity": "sha512-NK8py4eJNkN6iNfvaM8pzmmNNNkbyzRvnc/pmrDLFPPfgJklJ2esm8OBCALDe9RvP1USDo8H1I4IXCtQQIu3SQ==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.7.tgz", + "integrity": "sha512-VL0yT0rfdxU3NHts5aGjve1ui977BDJ9xb1Obw0LALWL4EzgQbiF8q8nUE6B25LwrQLzydUNTgMY0YYVLR2UkA==", "cpu": [ "x64" ], @@ -404,9 +404,9 @@ ] }, "node_modules/@oven/bun-darwin-x64-baseline": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.6.tgz", - "integrity": "sha512-amG6o1y1ksjwOUKS97IW5VQE/UPfEa4Edket1+VUa0UGvo/0z3+2gVYF3Bt+pZA45glJKXM3nI9wYlmVeE/AcQ==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.7.tgz", + "integrity": "sha512-oMKWmT5lqrnew/cmB+Mmuy/X7X0dBXnyJgsPp1RmV665u7UlNgRGncXhaW/EXlPJk4vaXh6UQQ8bLlg6mnQNgg==", "cpu": [ "x64" ], @@ -417,9 +417,9 @@ ] }, "node_modules/@oven/bun-linux-aarch64": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.6.tgz", - "integrity": "sha512-FOlZBeIrk7DlOsktWwahmxJwaKxCG9C+pKPMj8s+u08WhAKtfMBpgHvHsilBKE9W1twta+jB+geW4kU1KZSNZg==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.7.tgz", + "integrity": "sha512-/oVeD+f4S2tfIoKXVALuQv68k9O/91aMRCJ8+TlnVvZgZEpE6xdtbrSa+iP1wbAvBUy9ags0AgQOJg1QJzK/ow==", "cpu": [ "arm64" ], @@ -430,9 +430,9 @@ ] }, "node_modules/@oven/bun-linux-x64": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.6.tgz", - "integrity": "sha512-PN/5XSPCWCuIgOEhxWfx5ViVEY9ZfpEpJkadDiZi9IY17mb/aZVvt0Lll4doe6B7hjbglb1nI++GXcpqU/fonw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.7.tgz", + "integrity": "sha512-b+yTqZREacwPXcsg6/ps+qAZ/rlyuRztzptX6oNnc42+xd7BpdvKpdu2p8hbN0IoKBMqlAqFedffxFimIOMWFA==", "cpu": [ "x64" ], @@ -443,9 +443,9 @@ ] }, "node_modules/@oven/bun-linux-x64-baseline": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.6.tgz", - "integrity": "sha512-a/Wx5ZTl0BDq9WH5nJfl8rw0YX5/dWmxmy3pYki6EBbwjcsA8iMzjkRpp5k8NEV2SpyaDMdS+xCb/HiaO4RWoQ==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.7.tgz", + "integrity": "sha512-JklT4tgXi83nDyPLcWEfHxLKQnJdtpHG9sSOxpke6TlBwnj84lXbZ+CWhQL/aL9ye1lCTUjEIEbbZph8IhWlWg==", "cpu": [ "x64" ], @@ -456,9 +456,9 @@ ] }, "node_modules/@oven/bun-windows-x64": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.6.tgz", - "integrity": "sha512-knJePhYbqtYv5RNUrnkMFrK4z3dDIPzom402yjSLkESZhsnO16xtLkULocV2yk0KDXKo2C3BqoZKHATCK6LxqQ==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.7.tgz", + "integrity": "sha512-y8qrlwv09UIYKEm9+X1KzHHtaudWWWn7GGwSqCT6c7XYfR70fbnriyCm2i0qUAUTmgtuhY7dwFtAKf1UkQJ2SQ==", "cpu": [ "x64" ], @@ -469,9 +469,9 @@ ] }, "node_modules/@oven/bun-windows-x64-baseline": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.6.tgz", - "integrity": "sha512-8VVPdKTYEsQPwlCasLWmTsHPcC9om9FaZlH9j7Gs9jBYje3FDXMyLI3DalVQ/VBY+uwQ8qoXhtDrh83nLuawhA==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.7.tgz", + "integrity": "sha512-DkclScCfTR8YsNMATn2WVqbIf8cyD/UhIdFa4/R0Qsf+C1BB9jPquXoogSrAUJJyPMSbkBf2KshlROiFjYrjkw==", "cpu": [ "x64" ], @@ -482,12 +482,12 @@ ] }, "node_modules/@playwright/test": { - "version": "1.43.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.43.1.tgz", - "integrity": "sha512-HgtQzFgNEEo4TE22K/X7sYTYNqEMMTZmFS8kTq6m8hXj+m1D8TgwgIbumHddJa9h4yl4GkKb8/bgAl2+g7eDgA==", + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.44.0.tgz", + "integrity": "sha512-rNX5lbNidamSUorBhB4XZ9SQTjAqfe5M+p37Z8ic0jPFBMo5iCtQz1kRWkEMg+rYOKSlVycpQmpqjSFq7LXOfg==", "dev": true, "dependencies": { - "playwright": "1.43.1" + "playwright": "1.44.0" }, "bin": { "playwright": "cli.js" @@ -1044,9 +1044,9 @@ } }, "node_modules/bun": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.6.tgz", - "integrity": "sha512-0oKx5dVZ8LpsAvXdW2DTR5Zt3KS81Ifjx9T2ma7RjDPKbvGIlDXOPt++tr1SndxhFNFsMFeE4i6VKvlL7IR0Zw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.7.tgz", + "integrity": "sha512-4Q/ySjXfSTOsehxektQuo376FfI/QMPSjnsBAwQAZsRFW37Hb8IdctOABDEBQcrYmiwgDGKlgdWTQ8/5H0N2ww==", "cpu": [ "arm64", "x64" @@ -1063,14 +1063,14 @@ "bunx": "bin/bun.exe" }, "optionalDependencies": { - "@oven/bun-darwin-aarch64": "1.1.6", - "@oven/bun-darwin-x64": "1.1.6", - "@oven/bun-darwin-x64-baseline": "1.1.6", - "@oven/bun-linux-aarch64": "1.1.6", - "@oven/bun-linux-x64": "1.1.6", - "@oven/bun-linux-x64-baseline": "1.1.6", - "@oven/bun-windows-x64": "1.1.6", - "@oven/bun-windows-x64-baseline": "1.1.6" + "@oven/bun-darwin-aarch64": "1.1.7", + "@oven/bun-darwin-x64": "1.1.7", + "@oven/bun-darwin-x64-baseline": "1.1.7", + "@oven/bun-linux-aarch64": "1.1.7", + "@oven/bun-linux-x64": "1.1.7", + "@oven/bun-linux-x64-baseline": "1.1.7", + "@oven/bun-windows-x64": "1.1.7", + "@oven/bun-windows-x64-baseline": "1.1.7" } }, "node_modules/callsites": { @@ -1548,15 +1548,15 @@ } }, "node_modules/eslint": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.1.1.tgz", - "integrity": "sha512-b4cRQ0BeZcSEzPpY2PjFY70VbO32K7BStTGtBsnIGdTSEEQzBi8hPBcGQmTG2zUvFr9uLe0TK42bw8YszuHEqg==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.2.0.tgz", + "integrity": "sha512-0n/I88vZpCOzO+PQpt0lbsqmn9AsnsJAQseIqhZFI8ibQT0U1AkEKRxA3EVMos0BoHSXDQvCXY25TUjB5tr8Og==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^3.0.2", - "@eslint/js": "9.1.1", + "@eslint/js": "9.2.0", "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.2.3", @@ -2556,12 +2556,12 @@ "integrity": "sha512-yyVAOFKTAElc7KdLt2+UKGExNYwYb/Y/WE9i+1ezCQsJE8gbKSjewfpRqK2nQgZ4d4hhAAGgDCOcIZVilqE5UA==" }, "node_modules/playwright": { - "version": "1.43.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.1.tgz", - "integrity": "sha512-V7SoH0ai2kNt1Md9E3Gwas5B9m8KR2GVvwZnAI6Pg0m3sh7UvgiYhRrhsziCmqMJNouPckiOhk8T+9bSAK0VIA==", + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.0.tgz", + "integrity": "sha512-F9b3GUCLQ3Nffrfb6dunPOkE5Mh68tR7zN32L4jCk4FjQamgesGay7/dAAe1WaMEGV04DkdJfcJzjoCKygUaRQ==", "dev": true, "dependencies": { - "playwright-core": "1.43.1" + "playwright-core": "1.44.0" }, "bin": { "playwright": "cli.js" @@ -2574,9 +2574,9 @@ } }, "node_modules/playwright-core": { - "version": "1.43.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.1.tgz", - "integrity": "sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg==", + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.0.tgz", + "integrity": "sha512-ZTbkNpFfYcGWohvTTl+xewITm7EOuqIqex0c7dNZ+aXsbrLj0qI8XlGKfPpipjm0Wny/4Lt4CJsWJk1stVS5qQ==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -2600,9 +2600,9 @@ } }, "node_modules/polyscript": { - "version": "0.12.7", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.7.tgz", - "integrity": "sha512-Aaw/UCFNEuBkEcT00wok8ks+llVINunx98x4FdXZueUlFsr5+B41OVV3DptsJ3+7tzjqmJwhxe7cBTpMolLG/Q==", + "version": "0.12.8", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.8.tgz", + "integrity": "sha512-kcG3W9jU/s1sYjWOTAa2jAh5D2jm3zJRi+glSTsC+lA3D1b/Sd67pEIGpyL9bWNKYSimqAx4se6jAhQjJZ7+jQ==", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 95d5cd74814..aa27e4afd89 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.27", + "version": "0.4.31", "type": "module", "description": "PyScript", "module": "./index.js", @@ -43,7 +43,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.7", + "polyscript": "^0.12.8", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -54,17 +54,17 @@ "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.1", "@codemirror/view": "^6.26.3", - "@playwright/test": "^1.43.1", + "@playwright/test": "^1.44.0", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", - "bun": "^1.1.6", + "bun": "^1.1.7", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^9.1.1", + "eslint": "^9.2.0", "rollup": "^4.17.2", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", diff --git a/pyscript.core/src/core.js b/pyscript.core/src/core.js index fb7092ab6b9..735d9c56f96 100644 --- a/pyscript.core/src/core.js +++ b/pyscript.core/src/core.js @@ -84,6 +84,9 @@ export { exportedWhenDefined as whenDefined, }; +export const offline_interpreter = (config) => + config?.interpreter && new URL(config.interpreter, location.href).href; + const hooked = new Map(); for (const [TYPE, interpreter] of TYPES) { @@ -294,7 +297,7 @@ for (const [TYPE, interpreter] of TYPES) { interpreter, hooks, env: `${TYPE}-script`, - version: config?.interpreter, + version: offline_interpreter(config), onerror(error, element) { errors.set(element, error); }, diff --git a/pyscript.core/src/plugins/py-editor.js b/pyscript.core/src/plugins/py-editor.js index ee5ed5c3d6c..47be2b084e0 100644 --- a/pyscript.core/src/plugins/py-editor.js +++ b/pyscript.core/src/plugins/py-editor.js @@ -1,6 +1,6 @@ // PyScript py-editor plugin import { Hook, XWorker, dedent } from "polyscript/exports"; -import { TYPES, stdlib } from "../core.js"; +import { TYPES, offline_interpreter, stdlib } from "../core.js"; const RUN_BUTTON = ``; @@ -42,8 +42,7 @@ async function execute({ currentTarget }) { ? await import(/* webpackIgnore: true */ "../3rd-party/toml.js") : JSON; details.config = parse(await fetch(config).then((r) => r.text())); - const { interpreter } = details.config; - if (interpreter) details.version = interpreter; + details.version = offline_interpreter(details.config); } const xworker = XWorker.call(new Hook(null, hooks), srcLink, details); diff --git a/pyscript.core/types/core.d.ts b/pyscript.core/types/core.d.ts index 629011e3274..0b3f20b6943 100644 --- a/pyscript.core/types/core.d.ts +++ b/pyscript.core/types/core.d.ts @@ -1,3 +1,4 @@ +export function offline_interpreter(config: any): string; import { stdlib } from "./stdlib.js"; import { optional } from "./stdlib.js"; import TYPES from "./types.js"; From 04222b0d03760e2a8da2af420194715d33a09193 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Wed, 8 May 2024 21:33:07 +0200 Subject: [PATCH 046/179] PyEditor - process(code) ability (#2053) * Even better PyEditor offline use case (#2050) * Even better PyEditor offline use case * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * PyEditor - process(code) ability * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/src/plugins/py-editor.js | 43 +++++++++++++++++++++---- pyscript.core/test/py-editor/index.html | 16 ++++++++- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/pyscript.core/src/plugins/py-editor.js b/pyscript.core/src/plugins/py-editor.js index 47be2b084e0..2a45aa27db4 100644 --- a/pyscript.core/src/plugins/py-editor.js +++ b/pyscript.core/src/plugins/py-editor.js @@ -1,5 +1,5 @@ // PyScript py-editor plugin -import { Hook, XWorker, dedent } from "polyscript/exports"; +import { Hook, XWorker, dedent, defineProperties } from "polyscript/exports"; import { TYPES, offline_interpreter, stdlib } from "../core.js"; const RUN_BUTTON = ``; @@ -58,7 +58,7 @@ async function execute({ currentTarget }) { // wait for the env then set the target div // before executing the current code - envs.get(env).then((xworker) => { + return envs.get(env).then((xworker) => { xworker.onerror = ({ error }) => { if (hasRunButton) { outDiv.innerHTML += `${ @@ -148,7 +148,7 @@ const init = async (script, type, interpreter) => { import(/* webpackIgnore: true */ "../3rd-party/codemirror_commands.js"), ]); - const isSetup = script.hasAttribute("setup"); + let isSetup = script.hasAttribute("setup"); const hasConfig = script.hasAttribute("config"); const env = `${interpreter}-${script.getAttribute("env") || getID(type)}`; @@ -162,7 +162,7 @@ const init = async (script, type, interpreter) => { configs.set(env, hasConfig); - const source = script.src + let source = script.src ? await fetch(script.src).then((b) => b.text()) : script.textContent; const context = { @@ -179,14 +179,44 @@ const init = async (script, type, interpreter) => { }, }; + let target; + defineProperties(script, { + target: { get: () => target }, + process: { + /** + * Simulate a setup node overriding the source to evaluate. + * @param {string} code the Python code to evaluate. + * @returns {Promise<...>} fulfill once code has been evaluated. + */ + value(code) { + const wasSetup = isSetup; + const wasSource = source; + isSetup = true; + source = code; + const restore = () => { + isSetup = wasSetup; + source = wasSource; + }; + return execute + .call(context, { currentTarget: null }) + .then(restore, restore); + }, + }, + }); + + const notify = () => { + const event = new Event(`${type}-editor`, { bubbles: true }); + script.dispatchEvent(event); + }; + if (isSetup) { - execute.call(context, { currentTarget: null }); + await execute.call(context, { currentTarget: null }); + notify(); return; } const selector = script.getAttribute("target"); - let target; if (selector) { target = document.getElementById(selector) || @@ -236,6 +266,7 @@ const init = async (script, type, interpreter) => { }); editor.focus(); + notify(); }; // avoid too greedy MutationObserver operations at distance diff --git a/pyscript.core/test/py-editor/index.html b/pyscript.core/test/py-editor/index.html index ec46bc61192..c1b4f57adb4 100644 --- a/pyscript.core/test/py-editor/index.html +++ b/pyscript.core/test/py-editor/index.html @@ -4,7 +4,21 @@ - + From d1a0d8ea987956658a2767fb5c42a97b1e8a0a0a Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Mon, 13 May 2024 10:36:00 +0200 Subject: [PATCH 047/179] Fix #2056 - Provide a default empty config per editor env (#2058) * Fix #2056 - Provide a default empty config per editor env * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/.npmignore | 1 + pyscript.core/package-lock.json | 4 ++-- pyscript.core/package.json | 2 +- pyscript.core/src/plugins/py-editor.js | 2 ++ pyscript.core/test-results/.last-run.json | 4 ++++ pyscript.core/test/py-editor/issue-2056.html | 17 +++++++++++++++++ 6 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 pyscript.core/test-results/.last-run.json create mode 100644 pyscript.core/test/py-editor/issue-2056.html diff --git a/pyscript.core/.npmignore b/pyscript.core/.npmignore index cd1f68af59c..6a6507d08c4 100644 --- a/pyscript.core/.npmignore +++ b/pyscript.core/.npmignore @@ -4,6 +4,7 @@ node_modules/ rollup/ test/ tests/ +test-results/ src/stdlib/_pyscript src/stdlib/pyscript.py package-lock.json diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index eb9b483d0b9..9468e90627e 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.31", + "version": "0.4.32", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.31", + "version": "0.4.32", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index aa27e4afd89..0adc3eb5640 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.31", + "version": "0.4.32", "type": "module", "description": "PyScript", "module": "./index.js", diff --git a/pyscript.core/src/plugins/py-editor.js b/pyscript.core/src/plugins/py-editor.js index 2a45aa27db4..73494b95c6e 100644 --- a/pyscript.core/src/plugins/py-editor.js +++ b/pyscript.core/src/plugins/py-editor.js @@ -43,6 +43,8 @@ async function execute({ currentTarget }) { : JSON; details.config = parse(await fetch(config).then((r) => r.text())); details.version = offline_interpreter(details.config); + } else { + details.config = {}; } const xworker = XWorker.call(new Hook(null, hooks), srcLink, details); diff --git a/pyscript.core/test-results/.last-run.json b/pyscript.core/test-results/.last-run.json new file mode 100644 index 00000000000..f740f7c7003 --- /dev/null +++ b/pyscript.core/test-results/.last-run.json @@ -0,0 +1,4 @@ +{ + "status": "passed", + "failedTests": [] +} diff --git a/pyscript.core/test/py-editor/issue-2056.html b/pyscript.core/test/py-editor/issue-2056.html new file mode 100644 index 00000000000..3106c4fcda3 --- /dev/null +++ b/pyscript.core/test/py-editor/issue-2056.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + + From e7216d26e755fe85f29ceccad29e2da63a11ac1c Mon Sep 17 00:00:00 2001 From: Nicholas Tollervey Date: Mon, 13 May 2024 12:27:24 +0100 Subject: [PATCH 048/179] Add release information to README. (#2059) * Add release information to README. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index d0af51fc22d..7ede8dbd4fc 100644 --- a/README.md +++ b/README.md @@ -74,3 +74,22 @@ Check out the [developing process](https://pyscript.github.io/docs/latest/contri ## Governance The [PyScript organization governance](https://github.com/pyscript/governance) is documented in a separate repository. + +## Release + +To cut a new release of PyScript simply +[add a new release](https://github.com/pyscript/pyscript/releases) while +remembering to write a comprehensive changelog. A [GitHub action](https://github.com/pyscript/pyscript/blob/main/.github/workflows/publish-release.yml) +will kick in and ensure the release is described and deployed to a URL with the +pattern: https://pyscript.net/releases/YYYY.M.v/ (year/month/version - as per +our [CalVer](https://calver.org/) versioning scheme). + +Then, the following three separate repositories need updating: + +- [Documentation](https://github.com/pyscript/docs) - Change the `version.json` + file in the root of the directory and then `node version-update.js`. +- [Homepage](https://github.com/pyscript/pyscript.net) - Ensure the version + referenced in `index.html` is the latest version. +- [PSDC](https://pyscript.com) - Use discord or Anaconda Slack (if you work at + Anaconda) to let the PSDC team know there's a new version, so they can update + their project templates. From ed6d0136b8bcf03f3d3a4ea6f0951e83d60ffc0e Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Sun, 19 May 2024 12:10:15 +0200 Subject: [PATCH 049/179] Updated MicroPython to its latest (#2063) * Updated MicroPython to its latest * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/package-lock.json | 134 ++++++++++++++++++++------------ pyscript.core/package.json | 6 +- 2 files changed, 88 insertions(+), 52 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 9468e90627e..e1b4bb8e924 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.4.32", + "version": "0.4.34", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.32", + "version": "0.4.34", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.8", + "polyscript": "^0.12.10", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -29,7 +29,7 @@ "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", - "bun": "^1.1.7", + "bun": "^1.1.8", "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^9.2.0", @@ -74,6 +74,7 @@ "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.5.0.tgz", "integrity": "sha512-rK+sj4fCAN/QfcY9BEzYMgp4wwL/q5aj/VfNSoH1RWPF9XS/dUwBkvlL3hpWgEjOqlpdN1uLC9UkjJ4tmyjJYg==", "dev": true, + "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.4.0", @@ -86,6 +87,7 @@ "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.6.tgz", "integrity": "sha512-ai+01WfZhWqM92UqjnvorkxosZ2aq2u28kHvr+N3gu012XqY2CThD67JPMHnGceRfXPDBmn1HnyqowdpF57bNg==", "dev": true, + "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.3.2", "@codemirror/language": "^6.8.0", @@ -99,6 +101,7 @@ "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.1.tgz", "integrity": "sha512-5GrXzrhq6k+gL5fjkAwt90nYDmjlzTIJV8THnxNFtNKWotMIlzzN+CpqxqwXOECnUdOndmSeWntVrVcv5axWRQ==", "dev": true, + "license": "MIT", "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.23.0", @@ -134,13 +137,15 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz", "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@codemirror/view": { "version": "6.26.3", "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.3.tgz", "integrity": "sha512-gmqxkPALZjkgSxIeeweY/wGQXBfwTUaLs8h7OKtSwfbj9Ct3L11lD+u1sS7XHppxFQoMDiMDp07P9f3I2jWOHw==", "dev": true, + "license": "MIT", "dependencies": { "@codemirror/state": "^6.4.0", "style-mod": "^4.1.0", @@ -378,104 +383,112 @@ } }, "node_modules/@oven/bun-darwin-aarch64": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.7.tgz", - "integrity": "sha512-6xH96IjcQlnbsGziUELOhewuobKyzcc+/mV1fSQkY8+c5crgca1nnArS8ja7GaduDWCGuSvMiURFUtf/EAZYtg==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.8.tgz", + "integrity": "sha512-M9qPzCYbSsQOsPNhyr8h8hIyZ1T7fgeg8QJPIIXppWHzL6nqqOn+12ombFuDy0EdetVjrUSDmSPO8cR8j3Kv0Q==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@oven/bun-darwin-x64": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.7.tgz", - "integrity": "sha512-VL0yT0rfdxU3NHts5aGjve1ui977BDJ9xb1Obw0LALWL4EzgQbiF8q8nUE6B25LwrQLzydUNTgMY0YYVLR2UkA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.8.tgz", + "integrity": "sha512-al0V8PlWWFRprptwAQTdhMYacc0K1RyaoW+FvLtwZis1Lzl8o+NDHnxOhRzfzafttYIjssPOEz9zGTYuACBn8w==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@oven/bun-darwin-x64-baseline": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.7.tgz", - "integrity": "sha512-oMKWmT5lqrnew/cmB+Mmuy/X7X0dBXnyJgsPp1RmV665u7UlNgRGncXhaW/EXlPJk4vaXh6UQQ8bLlg6mnQNgg==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.8.tgz", + "integrity": "sha512-YV7pETCt3k5Xc4soR3kFx3AxbPco3w/17JhDHTDajkw033aSqCMWLvd2fHLUA0xPn46ktOMhe/aESULymvvo5w==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@oven/bun-linux-aarch64": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.7.tgz", - "integrity": "sha512-/oVeD+f4S2tfIoKXVALuQv68k9O/91aMRCJ8+TlnVvZgZEpE6xdtbrSa+iP1wbAvBUy9ags0AgQOJg1QJzK/ow==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.8.tgz", + "integrity": "sha512-C/QL5vgmBXWm0JsHWEKXlwG/gSB+MiOdvgfbnADRDaGPgZMGRK7uXFj/TLtw9CBRXugfty/lLkzY+18fQ8LVfw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@oven/bun-linux-x64": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.7.tgz", - "integrity": "sha512-b+yTqZREacwPXcsg6/ps+qAZ/rlyuRztzptX6oNnc42+xd7BpdvKpdu2p8hbN0IoKBMqlAqFedffxFimIOMWFA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.8.tgz", + "integrity": "sha512-Z6Lyd8oH8EjER4rpC3L+B7G4ub7DW6IjPqmaov445jByOK/KZktzlNEJgdrcrPVocAA/xZ+eYtzeyQ/z4ITdhg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@oven/bun-linux-x64-baseline": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.7.tgz", - "integrity": "sha512-JklT4tgXi83nDyPLcWEfHxLKQnJdtpHG9sSOxpke6TlBwnj84lXbZ+CWhQL/aL9ye1lCTUjEIEbbZph8IhWlWg==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.8.tgz", + "integrity": "sha512-RlWLFVvSbHkpNyorzeapfYUKuZYfhBgQV5N7EwiG8Kul8BPiRKAW+uOK6BuwJyA0vduF7Z4/cBeIO4XygXb5QQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@oven/bun-windows-x64": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.7.tgz", - "integrity": "sha512-y8qrlwv09UIYKEm9+X1KzHHtaudWWWn7GGwSqCT6c7XYfR70fbnriyCm2i0qUAUTmgtuhY7dwFtAKf1UkQJ2SQ==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.8.tgz", + "integrity": "sha512-svZHc2sGLqJrzXiD/6XaJNvJ0PE+WpdZv/pRkn9tXgA2j0gOawN3oAiHXUOWoYS5kQQ7GiksEJlYVPA4JyJY0A==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@oven/bun-windows-x64-baseline": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.7.tgz", - "integrity": "sha512-DkclScCfTR8YsNMATn2WVqbIf8cyD/UhIdFa4/R0Qsf+C1BB9jPquXoogSrAUJJyPMSbkBf2KshlROiFjYrjkw==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.8.tgz", + "integrity": "sha512-RXoCcY5DnVaF5HAGZ8Hms8Izo6yTHgTZsy/rqmaZLjfntOf4Gn8vw3YVE4Pa0AqW6oQYTSmSlgxM47kVWOv3+w==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -486,6 +499,7 @@ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.44.0.tgz", "integrity": "sha512-rNX5lbNidamSUorBhB4XZ9SQTjAqfe5M+p37Z8ic0jPFBMo5iCtQz1kRWkEMg+rYOKSlVycpQmpqjSFq7LXOfg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "playwright": "1.44.0" }, @@ -501,6 +515,7 @@ "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.7.tgz", "integrity": "sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==", "dev": true, + "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", @@ -526,6 +541,7 @@ "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz", "integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==", "dev": true, + "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", @@ -551,6 +567,7 @@ "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", "dev": true, + "license": "MIT", "dependencies": { "serialize-javascript": "^6.0.1", "smob": "^1.0.0", @@ -827,7 +844,8 @@ "node_modules/@ungap/with-resolvers": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@ungap/with-resolvers/-/with-resolvers-0.1.0.tgz", - "integrity": "sha512-g7f0IkJdPW2xhY7H4iE72DAsIyfuwEFc6JWc2tYFwKDMWWAF699vGjrM348cwQuOXgHpe1gWFe+Eiyjx/ewvvw==" + "integrity": "sha512-g7f0IkJdPW2xhY7H4iE72DAsIyfuwEFc6JWc2tYFwKDMWWAF699vGjrM348cwQuOXgHpe1gWFe+Eiyjx/ewvvw==", + "license": "ISC" }, "node_modules/@webreflection/fetch": { "version": "0.1.5", @@ -845,6 +863,7 @@ "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.10.0.tgz", "integrity": "sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==", "dev": true, + "license": "MIT", "peerDependencies": { "@xterm/xterm": "^5.0.0" } @@ -854,6 +873,7 @@ "resolved": "https://registry.npmjs.org/@xterm/addon-web-links/-/addon-web-links-0.11.0.tgz", "integrity": "sha512-nIHQ38pQI+a5kXnRaTgwqSHnX7KE6+4SVoceompgHL26unAxdfP6IPqUTSYPQgSwM56hsElfoNrrW5V7BUED/Q==", "dev": true, + "license": "MIT", "peerDependencies": { "@xterm/xterm": "^5.0.0" } @@ -954,7 +974,8 @@ "node_modules/basic-devtools": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/basic-devtools/-/basic-devtools-0.1.6.tgz", - "integrity": "sha512-g9zJ63GmdUesS3/Fwv0B5SYX6nR56TQXmGr+wE5PRTNCnGQMYWhUx/nZB/mMWnQJVLPPAp89oxDNlasdtNkW5Q==" + "integrity": "sha512-g9zJ63GmdUesS3/Fwv0B5SYX6nR56TQXmGr+wE5PRTNCnGQMYWhUx/nZB/mMWnQJVLPPAp89oxDNlasdtNkW5Q==", + "license": "ISC" }, "node_modules/binary-extensions": { "version": "2.2.0", @@ -1044,15 +1065,16 @@ } }, "node_modules/bun": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.7.tgz", - "integrity": "sha512-4Q/ySjXfSTOsehxektQuo376FfI/QMPSjnsBAwQAZsRFW37Hb8IdctOABDEBQcrYmiwgDGKlgdWTQ8/5H0N2ww==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.8.tgz", + "integrity": "sha512-TSL3POeJspEvIsfVqQZ/Sbl81kkzuUYCdE5fPdaDw0V6uU1j9d6JzfjYwNyDRnaacAAPnz3ZJukwGz3d6qJNzw==", "cpu": [ "arm64", "x64" ], "dev": true, "hasInstallScript": true, + "license": "MIT", "os": [ "darwin", "linux", @@ -1063,14 +1085,14 @@ "bunx": "bin/bun.exe" }, "optionalDependencies": { - "@oven/bun-darwin-aarch64": "1.1.7", - "@oven/bun-darwin-x64": "1.1.7", - "@oven/bun-darwin-x64-baseline": "1.1.7", - "@oven/bun-linux-aarch64": "1.1.7", - "@oven/bun-linux-x64": "1.1.7", - "@oven/bun-linux-x64-baseline": "1.1.7", - "@oven/bun-windows-x64": "1.1.7", - "@oven/bun-windows-x64-baseline": "1.1.7" + "@oven/bun-darwin-aarch64": "1.1.8", + "@oven/bun-darwin-x64": "1.1.8", + "@oven/bun-darwin-x64-baseline": "1.1.8", + "@oven/bun-linux-aarch64": "1.1.8", + "@oven/bun-linux-x64": "1.1.8", + "@oven/bun-linux-x64-baseline": "1.1.8", + "@oven/bun-windows-x64": "1.1.8", + "@oven/bun-windows-x64-baseline": "1.1.8" } }, "node_modules/callsites": { @@ -1135,6 +1157,7 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -1167,6 +1190,7 @@ "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz", "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==", "dev": true, + "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/commands": "^6.0.0", @@ -1552,6 +1576,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.2.0.tgz", "integrity": "sha512-0n/I88vZpCOzO+PQpt0lbsqmn9AsnsJAQseIqhZFI8ibQT0U1AkEKRxA3EVMos0BoHSXDQvCXY25TUjB5tr8Og==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -2600,9 +2625,10 @@ } }, "node_modules/polyscript": { - "version": "0.12.8", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.8.tgz", - "integrity": "sha512-kcG3W9jU/s1sYjWOTAa2jAh5D2jm3zJRi+glSTsC+lA3D1b/Sd67pEIGpyL9bWNKYSimqAx4se6jAhQjJZ7+jQ==", + "version": "0.12.10", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.10.tgz", + "integrity": "sha512-aHVHm6cphwGIlz7tHv3dY8KleVVYJfoGOHjlYyw6w/9HBiX9DHqI0X0SDdS1frXphLEF8B6OtbzqRYtKmUBNeg==", + "license": "APACHE-2.0", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", @@ -3291,6 +3317,7 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz", "integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "1.0.5" }, @@ -3326,6 +3353,7 @@ "resolved": "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-4.0.2.tgz", "integrity": "sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "concat-with-sourcemaps": "^1.1.0", @@ -3353,6 +3381,7 @@ "resolved": "https://registry.npmjs.org/rollup-plugin-string/-/rollup-plugin-string-3.0.0.tgz", "integrity": "sha512-vqyzgn9QefAgeKi+Y4A7jETeIAU1zQmS6VotH6bzm/zmUQEnYkpIGRaOBPY41oiWYV4JyBoGAaBjYMYuv+6wVw==", "dev": true, + "license": "MIT", "dependencies": { "rollup-pluginutils": "^2.4.1" } @@ -3498,6 +3527,7 @@ "resolved": "https://registry.npmjs.org/static-handler/-/static-handler-0.4.3.tgz", "integrity": "sha512-rHi6vtxW/kjC+L18cRVAICAp/ymTjyvZHCPXIrejrlVrRrNxrVGk9FNCg+rC9wM7SpZ9euyjsr7tNVtqpA2iLA==", "dev": true, + "license": "ISC", "dependencies": { "mime-types": "^2.1.35" }, @@ -3511,7 +3541,8 @@ "node_modules/sticky-module": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/sticky-module/-/sticky-module-0.1.1.tgz", - "integrity": "sha512-IuYgnyIMUx/m6rtu14l/LR2MaqOLtpXcWkxPmtPsiScRHEo+S4Tojk+DWFHOncSdFX/OsoLOM4+T92yOmI1AMw==" + "integrity": "sha512-IuYgnyIMUx/m6rtu14l/LR2MaqOLtpXcWkxPmtPsiScRHEo+S4Tojk+DWFHOncSdFX/OsoLOM4+T92yOmI1AMw==", + "license": "ISC" }, "node_modules/string-hash": { "version": "1.1.3", @@ -3663,7 +3694,8 @@ "node_modules/to-json-callback": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/to-json-callback/-/to-json-callback-0.1.1.tgz", - "integrity": "sha512-BzOeinTT3NjE+FJ2iCvWB8HvyuyBzoH3WlSnJ+AYVC4tlePyZWSYdkQIFOARWiq0t35/XhmI0uQsFiUsRksRqg==" + "integrity": "sha512-BzOeinTT3NjE+FJ2iCvWB8HvyuyBzoH3WlSnJ+AYVC4tlePyZWSYdkQIFOARWiq0t35/XhmI0uQsFiUsRksRqg==", + "license": "ISC" }, "node_modules/to-regex-range": { "version": "5.0.1", @@ -3692,13 +3724,15 @@ "node_modules/type-checked-collections": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/type-checked-collections/-/type-checked-collections-0.1.7.tgz", - "integrity": "sha512-fLIydlJy7IG9XL4wjRwEcKhxx/ekLXiWiMvcGo01cOMF+TN+5ZqajM1mRNRz2bNNi1bzou2yofhjZEQi7kgl9A==" + "integrity": "sha512-fLIydlJy7IG9XL4wjRwEcKhxx/ekLXiWiMvcGo01cOMF+TN+5ZqajM1mRNRz2bNNi1bzou2yofhjZEQi7kgl9A==", + "license": "ISC" }, "node_modules/typescript": { "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3805,13 +3839,15 @@ "resolved": "https://registry.npmjs.org/xterm/-/xterm-5.3.0.tgz", "integrity": "sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==", "deprecated": "This package is now deprecated. Move to @xterm/xterm instead.", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/xterm-readline": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/xterm-readline/-/xterm-readline-1.1.1.tgz", "integrity": "sha512-f87S2/jKwRZoZTxE2vkPgBCipDl6k6tTkMTb9pmwC4R6XkfR491fWBuToZd/nZasp6seD2u0jdABinUDWsK6dw==", "dev": true, + "license": "MIT", "dependencies": { "string-width": "^4.0.0" }, diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 0adc3eb5640..ace38e267bd 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.32", + "version": "0.4.34", "type": "module", "description": "PyScript", "module": "./index.js", @@ -43,7 +43,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.8", + "polyscript": "^0.12.10", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -61,7 +61,7 @@ "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", - "bun": "^1.1.7", + "bun": "^1.1.8", "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^9.2.0", From 18ec6ce775356bf98a5af5910bbed3d0f01d960f Mon Sep 17 00:00:00 2001 From: Takanori Suzuki Date: Tue, 21 May 2024 18:36:41 +0900 Subject: [PATCH 050/179] refs #2068 fix links on CONTRIBUTING.md (#2072) --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d97fc485af0..b5e9682c458 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -59,9 +59,9 @@ If you would like to contribute to PyScript, but you aren't sure where to begin, ## Setting up your local environment and developing -If you would like to contribute to PyScript, you will need to set up a local development environment. The [following instructions](https://pyscript.github.io/docs/latest/development/setting-up-environment.html) will help you get started. +If you would like to contribute to PyScript, you will need to set up a local development environment. The [following instructions](https://docs.pyscript.net/latest/contributing/#set-up-your-development-environment) will help you get started. -You can also read about PyScript's [development process](https://pyscript.github.io/docs/latest/development/developing.html) to learn how to contribute code to PyScript, how to run tests and what's the PR etiquette of the community! +You can also read about PyScript's [development process](https://docs.pyscript.net/latest/developers/) to learn how to contribute code to PyScript, how to run tests and what's the PR etiquette of the community! ## License terms for contributions From 9985787e4bfe9afeb405ebc83fd48dc513b3cbb5 Mon Sep 17 00:00:00 2001 From: jdw170000 <50096766+jdw170000@users.noreply.github.com> Date: Mon, 27 May 2024 04:44:24 -0500 Subject: [PATCH 051/179] Update dependencies and deprecated linter configuration format (#2076) * update python dependencies to latest versions * isort automatic formatting nits * update eslint config to non-deprecated flat format * `npm update` to upgrade javascript dependencies * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/.eslintrc.cjs | 26 -- pyscript.core/.npmignore | 1 + pyscript.core/eslint.config.mjs | 22 ++ pyscript.core/package-lock.json | 671 ++++++++++++++++++++++---------- pyscript.core/package.json | 2 +- requirements.txt | 18 +- 6 files changed, 502 insertions(+), 238 deletions(-) delete mode 100644 pyscript.core/.eslintrc.cjs create mode 100644 pyscript.core/eslint.config.mjs diff --git a/pyscript.core/.eslintrc.cjs b/pyscript.core/.eslintrc.cjs deleted file mode 100644 index ecdde66299f..00000000000 --- a/pyscript.core/.eslintrc.cjs +++ /dev/null @@ -1,26 +0,0 @@ -module.exports = { - env: { - browser: true, - es2021: true, - }, - extends: "eslint:recommended", - overrides: [ - { - env: { - node: true, - }, - files: [".eslintrc.{js,cjs}"], - parserOptions: { - sourceType: "script", - }, - }, - ], - parserOptions: { - ecmaVersion: "latest", - sourceType: "module", - }, - ignorePatterns: ["3rd-party"], - rules: { - "no-implicit-globals": ["error"], - }, -}; diff --git a/pyscript.core/.npmignore b/pyscript.core/.npmignore index 6a6507d08c4..cc7f5fd0a23 100644 --- a/pyscript.core/.npmignore +++ b/pyscript.core/.npmignore @@ -1,4 +1,5 @@ .eslintrc.cjs +eslint.config.mjs .pytest_cache/ node_modules/ rollup/ diff --git a/pyscript.core/eslint.config.mjs b/pyscript.core/eslint.config.mjs new file mode 100644 index 00000000000..9b9cc86349b --- /dev/null +++ b/pyscript.core/eslint.config.mjs @@ -0,0 +1,22 @@ +import globals from "globals"; +import js from "@eslint/js"; + +export default [ + js.configs.recommended, + { + ignores: ["**/3rd-party/"], + }, + { + languageOptions: { + ecmaVersion: "latest", + sourceType: "module", + globals: { + ...globals.browser, + ...globals.es2021, + }, + }, + rules: { + "no-implicit-globals": ["error"], + }, + }, +]; diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index e1b4bb8e924..6b01848d7fe 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -42,20 +42,12 @@ "xterm-readline": "^1.1.1" } }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@codemirror/autocomplete": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.12.0.tgz", - "integrity": "sha512-r4IjdYFthwbCQyvqnSlx0WBHRHi8nBvU+WjJxFUij81qsBfhNudf/XKKmmC2j3m0LaOYUQTf3qiEK1J8lO1sdg==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.16.0.tgz", + "integrity": "sha512-P/LeCTtZHRTCU4xQsa89vSKWecYv1ZqwzOd5topheGRf+qtacFgBeIMQi3eL8Kt/BUNvxUWkx+5qP2jlGoARrg==", "dev": true, + "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", @@ -112,10 +104,11 @@ } }, "node_modules/@codemirror/lint": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.5.0.tgz", - "integrity": "sha512-+5YyicIaaAZKU8K43IQi8TBy6mF6giGeWAH7N96Z5LC30Wm5JMjqxOYIE9mxwMG1NbhT2mA3l9hA4uuKUM3E5g==", + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.7.1.tgz", + "integrity": "sha512-rELba6QJD20/bNXWP/cKTGLrwVEcpa2ViwULCV03ONcY1Je85++7sczVRUlnE4TJMjatx3IJTz6HX4NXi+moXw==", "dev": true, + "license": "MIT", "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", @@ -127,6 +120,7 @@ "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz", "integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==", "dev": true, + "license": "MIT", "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", @@ -157,6 +151,7 @@ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -167,20 +162,35 @@ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@eslint-community/regexpp": { "version": "4.10.0", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.0.2.tgz", - "integrity": "sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -200,10 +210,11 @@ } }, "node_modules/@eslint/js": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.2.0.tgz", - "integrity": "sha512-ESiIudvhoYni+MdsI8oD7skpprZ89qKocwRM2KEvhhBJ9nl5MRh7BXU5GTod7Mdygq+AUl+QzId6iWJKR/wABA==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.3.0.tgz", + "integrity": "sha512-niBqk8iwv96+yuTwjM6bWg8ovzAPF9qkICsGtcoa5/dmqcEMfdwNAX7+/OHcJHc7wj7XqPxH98oAHytFYlw6Sw==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -213,6 +224,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", @@ -227,6 +239,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -239,13 +252,15 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@humanwhocodes/retry": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.2.3.tgz", - "integrity": "sha512-X38nUbachlb01YMlvPFojKoiXq+LzZvuSce70KPMPdeM1Rj03k4dR7lDslhbqXn3Ang4EU3+EAmwEAsbrjHW3g==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18" }, @@ -255,14 +270,15 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -273,40 +289,45 @@ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -316,13 +337,15 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@lezer/highlight": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz", "integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==", "dev": true, + "license": "MIT", "dependencies": { "@lezer/common": "^1.0.0" } @@ -332,15 +355,17 @@ "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.0.tgz", "integrity": "sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==", "dev": true, + "license": "MIT", "dependencies": { "@lezer/common": "^1.0.0" } }, "node_modules/@lezer/python": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.11.tgz", - "integrity": "sha512-C3QeLCcdAKJDUOsYjfFP6a1wdn8jhUNX200bgFm8TpKH1eM2PlgYQS5ugw6E38qGeEx7CP21I1Q52SoybXt0OQ==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.13.tgz", + "integrity": "sha512-AdbRAtdQq94PfTNd4kqMEJhH2fqa2JdoyyqqVewY6w34w2Gi6dg2JuOtOgR21Bi0zP9r0KjSSHOUq/tP7FVT8A==", "dev": true, + "license": "MIT", "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", @@ -352,6 +377,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -365,6 +391,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -374,6 +401,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -590,6 +618,7 @@ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", @@ -615,6 +644,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -628,6 +658,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -641,6 +672,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -654,6 +686,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -667,6 +700,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -680,6 +714,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -693,6 +728,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -706,6 +742,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -719,6 +756,7 @@ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -732,6 +770,7 @@ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -745,6 +784,7 @@ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -758,6 +798,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -771,6 +812,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -784,6 +826,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -797,6 +840,7 @@ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -810,6 +854,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -820,6 +865,7 @@ "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10.13.0" } @@ -828,18 +874,21 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "license": "ISC" }, "node_modules/@ungap/with-resolvers": { "version": "0.1.0", @@ -850,7 +899,8 @@ "node_modules/@webreflection/fetch": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/@webreflection/fetch/-/fetch-0.1.5.tgz", - "integrity": "sha512-zCcqCJoNLvdeF41asAK71XPlwSPieeRDsE09albBunJEksuYPYNillKNQjf8p5BqSoTKTuKrW3lUm3MNodUC4g==" + "integrity": "sha512-zCcqCJoNLvdeF41asAK71XPlwSPieeRDsE09albBunJEksuYPYNillKNQjf8p5BqSoTKTuKrW3lUm3MNodUC4g==", + "license": "MIT" }, "node_modules/@webreflection/toml-j0.4": { "version": "1.1.3", @@ -879,10 +929,11 @@ } }, "node_modules/@xterm/xterm": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.4.0.tgz", - "integrity": "sha512-GlyzcZZ7LJjhFevthHtikhiDIl8lnTSgol6eTM4aoSNLcuXu3OEhnbqdCVIjtIil3jjabf3gDtb1S8FGahsuEw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz", + "integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/acorn": { @@ -890,6 +941,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -902,6 +954,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -911,6 +964,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -927,6 +981,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -936,6 +991,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -951,6 +1007,7 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -963,13 +1020,15 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/basic-devtools": { "version": "0.1.6", @@ -978,25 +1037,31 @@ "license": "ISC" }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1007,6 +1072,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.0.1" }, @@ -1033,6 +1099,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "caniuse-lite": "^1.0.30001587", "electron-to-chromium": "^1.4.668", @@ -1050,13 +1117,15 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/builtin-modules": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -1100,6 +1169,7 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1109,6 +1179,7 @@ "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", "dev": true, + "license": "MIT", "dependencies": { "browserslist": "^4.0.0", "caniuse-lite": "^1.0.0", @@ -1117,9 +1188,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001587", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz", - "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==", + "version": "1.0.30001620", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001620.tgz", + "integrity": "sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==", "dev": true, "funding": [ { @@ -1134,13 +1205,15 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1181,6 +1254,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/codedent/-/codedent-0.1.2.tgz", "integrity": "sha512-qEqzcy5viM3UoCN0jYHZeXZoyd4NZQzYFg0kOBj8O1CgoGG9WYYTF+VeQRsN0OSKFjF3G1u4WDUOtOsWEx6N2w==", + "license": "ISC", "dependencies": { "plain-tag": "^0.1.3" } @@ -1205,6 +1279,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/coincident/-/coincident-1.2.3.tgz", "integrity": "sha512-Uxz3BMTWIslzeWjuQnizGWVg0j6khbvHUQ8+5BdM7WuJEm4ALXwq3wluYoB+uF68uPBz/oUOeJnYURKyfjexlA==", + "license": "ISC", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", @@ -1220,6 +1295,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -1231,19 +1307,22 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/colord": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/commander": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10" } @@ -1252,19 +1331,22 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/concat-with-sourcemaps": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", "dev": true, + "license": "ISC", "dependencies": { "source-map": "^0.6.1" } @@ -1273,13 +1355,15 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1294,6 +1378,7 @@ "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", "dev": true, + "license": "ISC", "engines": { "node": "^10 || ^12 || >=14" }, @@ -1306,6 +1391,7 @@ "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.0.1", @@ -1322,6 +1408,7 @@ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", "dev": true, + "license": "MIT", "dependencies": { "mdn-data": "2.0.14", "source-map": "^0.6.1" @@ -1335,6 +1422,7 @@ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">= 6" }, @@ -1347,6 +1435,7 @@ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, + "license": "MIT", "bin": { "cssesc": "bin/cssesc" }, @@ -1359,6 +1448,7 @@ "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", "dev": true, + "license": "MIT", "dependencies": { "cssnano-preset-default": "^5.2.14", "lilconfig": "^2.0.3", @@ -1380,6 +1470,7 @@ "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", "dev": true, + "license": "MIT", "dependencies": { "css-declaration-sorter": "^6.3.1", "cssnano-utils": "^3.1.0", @@ -1423,6 +1514,7 @@ "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", "dev": true, + "license": "MIT", "engines": { "node": "^10 || ^12 || >=14.0" }, @@ -1435,6 +1527,7 @@ "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", "dev": true, + "license": "MIT", "dependencies": { "css-tree": "^1.1.2" }, @@ -1447,6 +1540,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -1463,13 +1557,15 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1479,6 +1575,7 @@ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "dev": true, + "license": "MIT", "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", @@ -1498,13 +1595,15 @@ "type": "github", "url": "https://github.com/sponsors/fb55" } - ] + ], + "license": "BSD-2-Clause" }, "node_modules/domhandler": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "domelementtype": "^2.2.0" }, @@ -1520,6 +1619,7 @@ "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", @@ -1530,22 +1630,25 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.670", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.670.tgz", - "integrity": "sha512-hcijYOWjOtjKrKPtNA6tuLlA/bTLO3heFG8pQA6mLpq7dRydSWicXova5lyxDzp1iVJaYhK7J2OQlGE52KYn7A==", - "dev": true + "version": "1.4.775", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.775.tgz", + "integrity": "sha512-JpOfl1aNAiZ88wFzjPczTLwYIoPIsij8S9/XQH9lqMpiJOf23kxea68B8wje4f68t4rOIq4Bh+vP4I65njiJBw==", + "dev": true, + "license": "ISC" }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", "dev": true, + "license": "BSD-2-Clause", "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -1555,6 +1658,7 @@ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1564,6 +1668,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -1572,19 +1677,19 @@ } }, "node_modules/eslint": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.2.0.tgz", - "integrity": "sha512-0n/I88vZpCOzO+PQpt0lbsqmn9AsnsJAQseIqhZFI8ibQT0U1AkEKRxA3EVMos0BoHSXDQvCXY25TUjB5tr8Og==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.3.0.tgz", + "integrity": "sha512-5Iv4CsZW030lpUqHBapdPo3MJetAPtejVW8B84GIcIIv8+ohFaddXsrn1Gn8uD9ijDb+kcYKFUVmC8qG8B2ORQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^3.0.2", - "@eslint/js": "9.2.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.3.0", "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.2.3", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.12.4", "chalk": "^4.0.0", @@ -1628,6 +1733,7 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -1640,22 +1746,11 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -1668,6 +1763,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -1680,6 +1776,7 @@ "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.11.3", "acorn-jsx": "^5.3.2", @@ -1692,23 +1789,12 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -1721,6 +1807,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -1733,6 +1820,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -1741,13 +1829,15 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -1756,31 +1846,36 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -1790,6 +1885,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" }, @@ -1802,6 +1898,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -1814,6 +1911,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -1830,6 +1928,7 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" @@ -1842,13 +1941,15 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", @@ -1856,6 +1957,7 @@ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -1869,6 +1971,7 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -1876,13 +1979,15 @@ "node_modules/gc-hook": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/gc-hook/-/gc-hook-0.3.1.tgz", - "integrity": "sha512-E5M+O/h2o7eZzGhzRZGex6hbB3k4NWqO0eA+OzLRLXxhdbYPajZnynPwAtphnh+cRHPwsj5Z80dqZlfI4eK55A==" + "integrity": "sha512-E5M+O/h2o7eZzGhzRZGex6hbB3k4NWqO0eA+OzLRLXxhdbYPajZnynPwAtphnh+cRHPwsj5Z80dqZlfI4eK55A==", + "license": "ISC" }, "node_modules/generic-names": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz", "integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==", "dev": true, + "license": "MIT", "dependencies": { "loader-utils": "^3.2.0" } @@ -1892,6 +1997,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1911,6 +2017,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -1923,6 +2030,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -1932,6 +2040,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -1944,6 +2053,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -1956,15 +2066,17 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -1975,19 +2087,22 @@ "node_modules/html-escaper": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", - "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==" + "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==", + "license": "MIT" }, "node_modules/icss-replace-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", "integrity": "sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/icss-utils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", "dev": true, + "license": "ISC", "engines": { "node": "^10 || ^12 || >= 14" }, @@ -2000,6 +2115,7 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -2009,6 +2125,7 @@ "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz", "integrity": "sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==", "dev": true, + "license": "MIT", "dependencies": { "import-from": "^3.0.0" }, @@ -2021,6 +2138,7 @@ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -2037,6 +2155,7 @@ "resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz", "integrity": "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==", "dev": true, + "license": "MIT", "dependencies": { "resolve-from": "^5.0.0" }, @@ -2049,6 +2168,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2058,6 +2178,7 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -2067,6 +2188,7 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2076,13 +2198,15 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -2095,6 +2219,7 @@ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", "dev": true, + "license": "MIT", "dependencies": { "builtin-modules": "^3.3.0" }, @@ -2110,6 +2235,7 @@ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, + "license": "MIT", "dependencies": { "hasown": "^2.0.0" }, @@ -2122,6 +2248,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2131,6 +2258,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2140,6 +2268,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -2151,13 +2280,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -2167,6 +2298,7 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2176,6 +2308,7 @@ "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "*" } @@ -2184,13 +2317,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -2202,25 +2337,29 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -2230,6 +2369,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -2243,6 +2383,7 @@ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } @@ -2252,6 +2393,7 @@ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 12.13.0" } @@ -2261,6 +2403,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -2275,49 +2418,53 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/magic-string": { - "version": "0.30.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.7.tgz", - "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==", + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", "dev": true, + "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" - }, - "engines": { - "node": ">=12" } }, "node_modules/mdn-data": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true + "dev": true, + "license": "CC0-1.0" }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -2327,6 +2474,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -2339,6 +2487,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2350,7 +2499,8 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.7", @@ -2363,6 +2513,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "peer": true, "bin": { "nanoid": "bin/nanoid.cjs" @@ -2375,19 +2526,22 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2397,6 +2551,7 @@ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2409,6 +2564,7 @@ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0" }, @@ -2421,22 +2577,24 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { "wrappy": "1" } }, "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -2447,6 +2605,7 @@ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -2456,6 +2615,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -2471,6 +2631,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -2486,6 +2647,7 @@ "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", "dev": true, + "license": "MIT", "dependencies": { "eventemitter3": "^4.0.4", "p-timeout": "^3.2.0" @@ -2502,6 +2664,7 @@ "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", "dev": true, + "license": "MIT", "dependencies": { "p-finally": "^1.0.0" }, @@ -2514,6 +2677,7 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -2526,6 +2690,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2535,6 +2700,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2543,19 +2709,22 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -2568,6 +2737,7 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -2578,13 +2748,15 @@ "node_modules/plain-tag": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/plain-tag/-/plain-tag-0.1.3.tgz", - "integrity": "sha512-yyVAOFKTAElc7KdLt2+UKGExNYwYb/Y/WE9i+1ezCQsJE8gbKSjewfpRqK2nQgZ4d4hhAAGgDCOcIZVilqE5UA==" + "integrity": "sha512-yyVAOFKTAElc7KdLt2+UKGExNYwYb/Y/WE9i+1ezCQsJE8gbKSjewfpRqK2nQgZ4d4hhAAGgDCOcIZVilqE5UA==", + "license": "ISC" }, "node_modules/playwright": { "version": "1.44.0", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.0.tgz", "integrity": "sha512-F9b3GUCLQ3Nffrfb6dunPOkE5Mh68tR7zN32L4jCk4FjQamgesGay7/dAAe1WaMEGV04DkdJfcJzjoCKygUaRQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "playwright-core": "1.44.0" }, @@ -2603,6 +2775,7 @@ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.0.tgz", "integrity": "sha512-ZTbkNpFfYcGWohvTTl+xewITm7EOuqIqex0c7dNZ+aXsbrLj0qI8XlGKfPpipjm0Wny/4Lt4CJsWJk1stVS5qQ==", "dev": true, + "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, @@ -2616,6 +2789,7 @@ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -2644,9 +2818,9 @@ } }, "node_modules/postcss": { - "version": "8.4.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", - "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", "dev": true, "funding": [ { @@ -2662,11 +2836,12 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "peer": true, "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" @@ -2677,6 +2852,7 @@ "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", "dev": true, + "license": "MIT", "dependencies": { "postcss-selector-parser": "^6.0.9", "postcss-value-parser": "^4.2.0" @@ -2690,6 +2866,7 @@ "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", "dev": true, + "license": "MIT", "dependencies": { "browserslist": "^4.21.4", "caniuse-api": "^3.0.0", @@ -2708,6 +2885,7 @@ "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", "dev": true, + "license": "MIT", "dependencies": { "browserslist": "^4.21.4", "postcss-value-parser": "^4.2.0" @@ -2724,6 +2902,7 @@ "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", "dev": true, + "license": "MIT", "engines": { "node": "^10 || ^12 || >=14.0" }, @@ -2736,6 +2915,7 @@ "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", "dev": true, + "license": "MIT", "engines": { "node": "^10 || ^12 || >=14.0" }, @@ -2748,6 +2928,7 @@ "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", "dev": true, + "license": "MIT", "engines": { "node": "^10 || ^12 || >=14.0" }, @@ -2760,6 +2941,7 @@ "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", "dev": true, + "license": "MIT", "engines": { "node": "^10 || ^12 || >=14.0" }, @@ -2772,6 +2954,7 @@ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", "dev": true, + "license": "MIT", "dependencies": { "lilconfig": "^2.0.5", "yaml": "^1.10.2" @@ -2801,6 +2984,7 @@ "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0", "stylehacks": "^5.1.1" @@ -2817,6 +3001,7 @@ "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", "dev": true, + "license": "MIT", "dependencies": { "browserslist": "^4.21.4", "caniuse-api": "^3.0.0", @@ -2835,6 +3020,7 @@ "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -2850,6 +3036,7 @@ "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", "dev": true, + "license": "MIT", "dependencies": { "colord": "^2.9.1", "cssnano-utils": "^3.1.0", @@ -2867,6 +3054,7 @@ "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", "dev": true, + "license": "MIT", "dependencies": { "browserslist": "^4.21.4", "cssnano-utils": "^3.1.0", @@ -2884,6 +3072,7 @@ "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", "dev": true, + "license": "MIT", "dependencies": { "postcss-selector-parser": "^6.0.5" }, @@ -2899,6 +3088,7 @@ "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-4.3.1.tgz", "integrity": "sha512-ItUhSUxBBdNamkT3KzIZwYNNRFKmkJrofvC2nWab3CPKhYBQ1f27XXh1PAPE27Psx58jeelPsxWB/+og+KEH0Q==", "dev": true, + "license": "MIT", "dependencies": { "generic-names": "^4.0.0", "icss-replace-symbols": "^1.1.0", @@ -2914,10 +3104,11 @@ } }, "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", "dev": true, + "license": "ISC", "engines": { "node": "^10 || ^12 || >= 14" }, @@ -2926,10 +3117,11 @@ } }, "node_modules/postcss-modules-local-by-default": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.4.tgz", - "integrity": "sha512-L4QzMnOdVwRm1Qb8m4x8jsZzKAaPAgrUF1r/hjDR2Xj7R+8Zsf97jAlSQzWtKx5YNiNGN8QxmPFIc/sh+RQl+Q==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", "dev": true, + "license": "MIT", "dependencies": { "icss-utils": "^5.0.0", "postcss-selector-parser": "^6.0.2", @@ -2943,10 +3135,11 @@ } }, "node_modules/postcss-modules-scope": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.1.1.tgz", - "integrity": "sha512-uZgqzdTleelWjzJY+Fhti6F3C9iF1JR/dODLs/JDefozYcKTBCdD8BIl6nNPbTbcLnGrk56hzwZC2DaGNvYjzA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", "dev": true, + "license": "ISC", "dependencies": { "postcss-selector-parser": "^6.0.4" }, @@ -2962,6 +3155,7 @@ "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", "dev": true, + "license": "ISC", "dependencies": { "icss-utils": "^5.0.0" }, @@ -2977,6 +3171,7 @@ "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", "dev": true, + "license": "MIT", "engines": { "node": "^10 || ^12 || >=14.0" }, @@ -2989,6 +3184,7 @@ "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -3004,6 +3200,7 @@ "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -3019,6 +3216,7 @@ "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -3034,6 +3232,7 @@ "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -3049,6 +3248,7 @@ "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -3064,6 +3264,7 @@ "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", "dev": true, + "license": "MIT", "dependencies": { "browserslist": "^4.21.4", "postcss-value-parser": "^4.2.0" @@ -3080,6 +3281,7 @@ "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", "dev": true, + "license": "MIT", "dependencies": { "normalize-url": "^6.0.1", "postcss-value-parser": "^4.2.0" @@ -3096,6 +3298,7 @@ "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -3111,6 +3314,7 @@ "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", "dev": true, + "license": "MIT", "dependencies": { "cssnano-utils": "^3.1.0", "postcss-value-parser": "^4.2.0" @@ -3127,6 +3331,7 @@ "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", "dev": true, + "license": "MIT", "dependencies": { "browserslist": "^4.21.4", "caniuse-api": "^3.0.0" @@ -3143,6 +3348,7 @@ "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, @@ -3154,10 +3360,11 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.15", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", - "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", + "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", "dev": true, + "license": "MIT", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3171,6 +3378,7 @@ "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0", "svgo": "^2.7.0" @@ -3187,6 +3395,7 @@ "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", "dev": true, + "license": "MIT", "dependencies": { "postcss-selector-parser": "^6.0.5" }, @@ -3201,13 +3410,15 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } @@ -3217,6 +3428,7 @@ "resolved": "https://registry.npmjs.org/promise.series/-/promise.series-0.2.0.tgz", "integrity": "sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12" } @@ -3224,13 +3436,15 @@ "node_modules/proxy-target": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/proxy-target/-/proxy-target-3.0.2.tgz", - "integrity": "sha512-FFE1XNwXX/FNC3/P8HiKaJSy/Qk68RitG/QEcLy/bVnTAPlgTAWPZKh0pARLAnpfXQPKyalBhk009NRTgsk8vQ==" + "integrity": "sha512-FFE1XNwXX/FNC3/P8HiKaJSy/Qk68RitG/QEcLy/bVnTAPlgTAWPZKh0pARLAnpfXQPKyalBhk009NRTgsk8vQ==", + "license": "MIT" }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3253,13 +3467,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } @@ -3269,6 +3485,7 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -3281,6 +3498,7 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -3298,6 +3516,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -3307,6 +3526,7 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -3391,6 +3611,7 @@ "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", "dev": true, + "license": "MIT", "dependencies": { "estree-walker": "^0.6.1" } @@ -3399,7 +3620,8 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/run-parallel": { "version": "1.2.0", @@ -3420,6 +3642,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -3442,19 +3665,22 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safe-identifier": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } @@ -3464,6 +3690,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -3476,30 +3703,34 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/smob": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/smob/-/smob-1.4.1.tgz", - "integrity": "sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==", - "dev": true + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", + "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", + "dev": true, + "license": "MIT" }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, + "license": "BSD-3-Clause", "peer": true, "engines": { "node": ">=0.10.0" @@ -3510,6 +3741,7 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -3520,7 +3752,8 @@ "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/static-handler": { "version": "0.4.3", @@ -3548,13 +3781,15 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==", - "dev": true + "dev": true, + "license": "CC0-1.0" }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3569,6 +3804,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3581,6 +3817,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -3592,19 +3829,22 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/style-inject/-/style-inject-0.3.0.tgz", "integrity": "sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/style-mod": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.0.tgz", - "integrity": "sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==", - "dev": true + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", + "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==", + "dev": true, + "license": "MIT" }, "node_modules/stylehacks": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", "dev": true, + "license": "MIT", "dependencies": { "browserslist": "^4.21.4", "postcss-selector-parser": "^6.0.4" @@ -3621,6 +3861,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -3633,6 +3874,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3645,6 +3887,7 @@ "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", "dev": true, + "license": "MIT", "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", @@ -3662,10 +3905,11 @@ } }, "node_modules/terser": { - "version": "5.27.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.1.tgz", - "integrity": "sha512-29wAr6UU/oQpnTw5HoadwjUZnFQXGdOfj0LjZ4sVxzqwHh/QVkvr7m8y9WoR4iN3FRitVduTc6KdjcW38Npsug==", + "version": "5.31.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz", + "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -3683,13 +3927,15 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/to-json-callback": { "version": "0.1.1", @@ -3702,6 +3948,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -3714,6 +3961,7 @@ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -3742,9 +3990,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", "dev": true, "funding": [ { @@ -3760,9 +4008,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -3776,6 +4025,7 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -3784,19 +4034,22 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/w3c-keyname": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -3807,16 +4060,28 @@ "node": ">= 8" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", + "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "license": "MIT", "optional": true, "engines": { "node": ">=10.0.0" @@ -3860,6 +4125,7 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true, + "license": "ISC", "engines": { "node": ">= 6" } @@ -3869,6 +4135,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, diff --git a/pyscript.core/package.json b/pyscript.core/package.json index ace38e267bd..2d3fdef75ad 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -20,7 +20,7 @@ }, "scripts": { "server": "npx static-handler --coi .", - "build": "export ESLINT_USE_FLAT_CONFIG=false; npm run build:3rd-party && npm run build:stdlib && npm run build:plugins && npm run build:core && eslint src/ && npm run ts && npm run test:mpy", + "build": "export ESLINT_USE_FLAT_CONFIG=true;npm run build:3rd-party && npm run build:stdlib && npm run build:plugins && npm run build:core && eslint src/ && npm run ts && npm run test:mpy", "build:core": "rm -rf dist && rollup --config rollup/core.config.js && cp src/3rd-party/*.css dist/", "build:plugins": "node rollup/plugins.cjs", "build:stdlib": "node rollup/stdlib.cjs", diff --git a/requirements.txt b/requirements.txt index 16c84899dcc..972a034ea63 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,13 +1,13 @@ -black==23.11.0 -isort==5.12.0 -pytest==7.1.2 -pre-commit==3.5.0 -playwright==1.33.0 -pytest-playwright==0.3.3 -pytest-xdist==3.3.0 +black==24.4.2 +isort==5.13.2 +pytest==8.2.1 +pre-commit==3.7.1 +playwright==1.44.0 +pytest-playwright==0.5.0 +pytest-xdist==3.6.1 pexpect==4.9.0 pyodide_py==0.24.1 micropip==0.5.0 toml==0.10.2 -numpy==1.26.2 -pillow==10.1.0 +numpy==1.26.4 +pillow==10.3.0 From 85da548447d2fff7d211831aa2a8d8841f2547ab Mon Sep 17 00:00:00 2001 From: Amjith Ramanujam Date: Mon, 27 May 2024 05:47:25 -0400 Subject: [PATCH 052/179] Fix the links to development process. (#2064) Co-authored-by: Andrea Giammarchi --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7ede8dbd4fc..cf3bdd5a326 100644 --- a/README.md +++ b/README.md @@ -67,9 +67,9 @@ Check out the [official docs](https://docs.pyscript.net/) for more detailed docu ## How to Contribute -Read the [contributing guide](CONTRIBUTING.md) to learn about our development process, reporting bugs and improvements, creating issues and asking questions. +Read the [contributing guide](https://docs.pyscript.net/latest/contributing/) to learn about our development process, reporting bugs and improvements, creating issues and asking questions. -Check out the [developing process](https://pyscript.github.io/docs/latest/contributing) documentation for more information on how to setup your development environment. +Check out the [developing process](https://docs.pyscript.net/latest/developers/) documentation for more information on how to setup your development environment. ## Governance From 39ca29749c19e2fe0f5cefce3e331e48e557b943 Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 27 May 2024 11:08:49 +0100 Subject: [PATCH 053/179] fix: typo in "isinstance" in Element.snap. (#2071) Co-authored-by: Fabio Pliger Co-authored-by: Andrea Giammarchi --- pyscript.core/src/stdlib/pyweb/pydom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyscript.core/src/stdlib/pyweb/pydom.py b/pyscript.core/src/stdlib/pyweb/pydom.py index 6a2a4289f44..0e7286743fd 100644 --- a/pyscript.core/src/stdlib/pyweb/pydom.py +++ b/pyscript.core/src/stdlib/pyweb/pydom.py @@ -267,7 +267,7 @@ def snap( canvas._js.width = width canvas._js.height = height - elif isistance(to, Element): + elif isinstance(to, Element): if to._js.tagName != "CANVAS": raise TypeError("Element to snap to must a canvas.") canvas = to From 66f72eda1e50ce7ac7cc595fa2b133d52f8c08ae Mon Sep 17 00:00:00 2001 From: jdw170000 <50096766+jdw170000@users.noreply.github.com> Date: Wed, 29 May 2024 10:36:06 -0500 Subject: [PATCH 054/179] Add spinner to py-editor run buttons (#2078) * Add spinner to disabled py-editor run buttons * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * css nit suggested by WebReflection --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- CHANGELOG.md | 10 ++++++++++ pyscript.core/src/core.css | 31 +++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c536d8c4907..0eec7b1e26b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Release Notes +## 2024.05.21 + +### Features + +### Bug fixes + +### Enhancements + +- `py-editor` run buttons now display a spinner when disabled, which occurs when the editor is running code. + ## 2023.05.01 ### Features diff --git a/pyscript.core/src/core.css b/pyscript.core/src/core.css index 84473940143..81b37e0c9c4 100644 --- a/pyscript.core/src/core.css +++ b/pyscript.core/src/core.css @@ -42,3 +42,34 @@ mpy-config { .mpy-editor-run-button:disabled { opacity: 1; } + +@keyframes spinner { + to { + transform: rotate(360deg); + } +} +.py-editor-run-button:disabled > *, +.mpy-editor-run-button:disabled > * { + display: none; /* hide all the child elements of the run button when it is disabled */ +} +.py-editor-run-button:disabled, +.mpy-editor-run-button:disabled { + border-width: 0; +} +.py-editor-run-button:disabled::before, +.mpy-editor-run-button:disabled::before { + content: ""; + box-sizing: border-box; + position: absolute; + top: 100%; + left: 100%; + width: 20px; + height: 20px; + margin-top: -23px; /* hardcoded value to center the spinner on the run button */ + margin-left: -26px; /* hardcoded value to center the spinner on the run button */ + border-radius: 50%; + border: 2px solid #aaa; + border-top-color: #000; + background-color: #fff; + animation: spinner 0.6s linear infinite; +} From 9b775ce015fa7cd3fc555e07cfb8bebb4d7b68d4 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Thu, 30 May 2024 13:36:42 +0200 Subject: [PATCH 055/179] Enhance MicroPython Terminal on both Main and Worker (#2083) * Allow MicroPython Terminal on Main * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .gitignore | 1 + pyscript.core/package-lock.json | 300 +++++++++--------- pyscript.core/package.json | 14 +- pyscript.core/src/core.js | 11 +- pyscript.core/src/hooks.js | 2 +- pyscript.core/src/plugins/py-terminal.js | 283 ++--------------- pyscript.core/src/plugins/py-terminal/mpy.js | 239 ++++++++++++++ pyscript.core/src/plugins/py-terminal/py.js | 179 +++++++++++ pyscript.core/test-results/.last-run.json | 4 - pyscript.core/test/py-terminal-worker.html | 2 +- pyscript.core/types/core.d.ts | 3 +- pyscript.core/types/hooks.d.ts | 1 + .../types/plugins/py-terminal/mpy.d.ts | 2 + .../types/plugins/py-terminal/py.d.ts | 2 + 14 files changed, 618 insertions(+), 425 deletions(-) create mode 100644 pyscript.core/src/plugins/py-terminal/mpy.js create mode 100644 pyscript.core/src/plugins/py-terminal/py.js delete mode 100644 pyscript.core/test-results/.last-run.json create mode 100644 pyscript.core/types/plugins/py-terminal/mpy.d.ts create mode 100644 pyscript.core/types/plugins/py-terminal/py.d.ts diff --git a/.gitignore b/.gitignore index d19ac9a9b6d..0b22174ef34 100644 --- a/.gitignore +++ b/.gitignore @@ -142,6 +142,7 @@ coverage/ test_results # @pyscript/core npm artifacts +pyscript.core/test-results/* pyscript.core/core.* pyscript.core/dist pyscript.core/dist.zip diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 6b01848d7fe..102864a4301 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.4.34", + "version": "0.4.38", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.34", + "version": "0.4.38", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.10", + "polyscript": "^0.12.12", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -22,18 +22,18 @@ "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.1", "@codemirror/view": "^6.26.3", - "@playwright/test": "^1.44.0", - "@rollup/plugin-commonjs": "^25.0.7", + "@playwright/test": "^1.44.1", + "@rollup/plugin-commonjs": "^25.0.8", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", - "bun": "^1.1.8", + "bun": "^1.1.10", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^9.2.0", - "rollup": "^4.17.2", + "eslint": "^9.3.0", + "rollup": "^4.18.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", @@ -104,9 +104,9 @@ } }, "node_modules/@codemirror/lint": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.7.1.tgz", - "integrity": "sha512-rELba6QJD20/bNXWP/cKTGLrwVEcpa2ViwULCV03ONcY1Je85++7sczVRUlnE4TJMjatx3IJTz6HX4NXi+moXw==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.0.tgz", + "integrity": "sha512-lsFofvaw0lnPRJlQylNsC4IRt/1lI4OD/yYslrSGVndOJfStc58v+8p9dgGiD90ktOfL7OhBWns1ZETYgz0EJA==", "dev": true, "license": "MIT", "dependencies": { @@ -361,9 +361,9 @@ } }, "node_modules/@lezer/python": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.13.tgz", - "integrity": "sha512-AdbRAtdQq94PfTNd4kqMEJhH2fqa2JdoyyqqVewY6w34w2Gi6dg2JuOtOgR21Bi0zP9r0KjSSHOUq/tP7FVT8A==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.14.tgz", + "integrity": "sha512-ykDOb2Ti24n76PJsSa4ZoDF0zH12BSw1LGfQXCYJhJyOGiFTfGaX0Du66Ze72R+u/P35U+O6I9m8TFXov1JzsA==", "dev": true, "license": "MIT", "dependencies": { @@ -411,9 +411,9 @@ } }, "node_modules/@oven/bun-darwin-aarch64": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.8.tgz", - "integrity": "sha512-M9qPzCYbSsQOsPNhyr8h8hIyZ1T7fgeg8QJPIIXppWHzL6nqqOn+12ombFuDy0EdetVjrUSDmSPO8cR8j3Kv0Q==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.10.tgz", + "integrity": "sha512-5x6QGEzTurmCPZM3OLosIJE0QynhKfKZZ6uSVl7C36mNPFAZfTXjK64LgbM+4P9Kr0PyEQnZweLlScl+HaEJcw==", "cpu": [ "arm64" ], @@ -425,9 +425,9 @@ ] }, "node_modules/@oven/bun-darwin-x64": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.8.tgz", - "integrity": "sha512-al0V8PlWWFRprptwAQTdhMYacc0K1RyaoW+FvLtwZis1Lzl8o+NDHnxOhRzfzafttYIjssPOEz9zGTYuACBn8w==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.10.tgz", + "integrity": "sha512-DYbp2koaATwWikMIyeWLq2LhLZtvxzr4WuFIBe4+KwoWLGXJEC8uK9QsTwis/tCLPH45ov9DMwDmBA31oX+0iA==", "cpu": [ "x64" ], @@ -439,9 +439,9 @@ ] }, "node_modules/@oven/bun-darwin-x64-baseline": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.8.tgz", - "integrity": "sha512-YV7pETCt3k5Xc4soR3kFx3AxbPco3w/17JhDHTDajkw033aSqCMWLvd2fHLUA0xPn46ktOMhe/aESULymvvo5w==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.10.tgz", + "integrity": "sha512-a/P612tHH86gpBiITwHmrpFMLT9Z/v6VxBKpPK+FgejIgLDGvzfIOxbNtBeGygWbZaAFDQfRRQJFGpVHvjwGQA==", "cpu": [ "x64" ], @@ -453,9 +453,9 @@ ] }, "node_modules/@oven/bun-linux-aarch64": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.8.tgz", - "integrity": "sha512-C/QL5vgmBXWm0JsHWEKXlwG/gSB+MiOdvgfbnADRDaGPgZMGRK7uXFj/TLtw9CBRXugfty/lLkzY+18fQ8LVfw==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.10.tgz", + "integrity": "sha512-iR7TRUWtVtrPe+iZu1ISQNbz7M6HxMRtn4PCr/a6dswuPkIhvXxTJUD6WTpHnHxsgioS5GHG9eonu03PTeBY0Q==", "cpu": [ "arm64" ], @@ -467,9 +467,9 @@ ] }, "node_modules/@oven/bun-linux-x64": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.8.tgz", - "integrity": "sha512-Z6Lyd8oH8EjER4rpC3L+B7G4ub7DW6IjPqmaov445jByOK/KZktzlNEJgdrcrPVocAA/xZ+eYtzeyQ/z4ITdhg==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.10.tgz", + "integrity": "sha512-pUgLdu/5Yn+hV8aIwZE0x2H/t2QQRIPWUibnUdDLglnNtGjaqNUyST9iVN5TD7NdMk1p342GDc9rouA8VxAHHA==", "cpu": [ "x64" ], @@ -481,9 +481,9 @@ ] }, "node_modules/@oven/bun-linux-x64-baseline": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.8.tgz", - "integrity": "sha512-RlWLFVvSbHkpNyorzeapfYUKuZYfhBgQV5N7EwiG8Kul8BPiRKAW+uOK6BuwJyA0vduF7Z4/cBeIO4XygXb5QQ==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.10.tgz", + "integrity": "sha512-TjBH/KIyI/4Ms3PJYRm2QEgI7HOyV5fXdwqwB/40SCPXND6wq0u4voHDIINc9rdHDRXpmO8RPUFWsKNuN3Mf5w==", "cpu": [ "x64" ], @@ -495,9 +495,9 @@ ] }, "node_modules/@oven/bun-windows-x64": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.8.tgz", - "integrity": "sha512-svZHc2sGLqJrzXiD/6XaJNvJ0PE+WpdZv/pRkn9tXgA2j0gOawN3oAiHXUOWoYS5kQQ7GiksEJlYVPA4JyJY0A==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.10.tgz", + "integrity": "sha512-+KiITh1xyrDGoRXM3HLHyO9iweaMZ9T41KP4cbov92D78SKxR5jpq1LDLPhWK668a0aNX/r9PGePkPNt4yg/HA==", "cpu": [ "x64" ], @@ -509,9 +509,9 @@ ] }, "node_modules/@oven/bun-windows-x64-baseline": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.8.tgz", - "integrity": "sha512-RXoCcY5DnVaF5HAGZ8Hms8Izo6yTHgTZsy/rqmaZLjfntOf4Gn8vw3YVE4Pa0AqW6oQYTSmSlgxM47kVWOv3+w==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.10.tgz", + "integrity": "sha512-+q2pDLq9VCXYJ89pcT5AevXUTGdDoqgq+scE3qlKLclSxtSR25K18C61D9rpqgiueC6jLrxIN13w5qOi4B3LfQ==", "cpu": [ "x64" ], @@ -523,13 +523,13 @@ ] }, "node_modules/@playwright/test": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.44.0.tgz", - "integrity": "sha512-rNX5lbNidamSUorBhB4XZ9SQTjAqfe5M+p37Z8ic0jPFBMo5iCtQz1kRWkEMg+rYOKSlVycpQmpqjSFq7LXOfg==", + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.44.1.tgz", + "integrity": "sha512-1hZ4TNvD5z9VuhNJ/walIjvMVvYkZKf71axoF/uiAqpntQJXpG64dlXhoDXE3OczPuTuvjf/M5KWFg5VAVUS3Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.44.0" + "playwright": "1.44.1" }, "bin": { "playwright": "cli.js" @@ -539,9 +539,9 @@ } }, "node_modules/@rollup/plugin-commonjs": { - "version": "25.0.7", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.7.tgz", - "integrity": "sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==", + "version": "25.0.8", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.8.tgz", + "integrity": "sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==", "dev": true, "license": "MIT", "dependencies": { @@ -637,9 +637,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz", - "integrity": "sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", "cpu": [ "arm" ], @@ -651,9 +651,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz", - "integrity": "sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", "cpu": [ "arm64" ], @@ -665,9 +665,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz", - "integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", "cpu": [ "arm64" ], @@ -679,9 +679,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz", - "integrity": "sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", "cpu": [ "x64" ], @@ -693,9 +693,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz", - "integrity": "sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", "cpu": [ "arm" ], @@ -707,9 +707,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz", - "integrity": "sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", "cpu": [ "arm" ], @@ -721,9 +721,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz", - "integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", "cpu": [ "arm64" ], @@ -735,9 +735,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz", - "integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", "cpu": [ "arm64" ], @@ -749,9 +749,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz", - "integrity": "sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", "cpu": [ "ppc64" ], @@ -763,9 +763,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz", - "integrity": "sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", "cpu": [ "riscv64" ], @@ -777,9 +777,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz", - "integrity": "sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", "cpu": [ "s390x" ], @@ -791,9 +791,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz", - "integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", "cpu": [ "x64" ], @@ -805,9 +805,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz", - "integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", "cpu": [ "x64" ], @@ -819,9 +819,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz", - "integrity": "sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", "cpu": [ "arm64" ], @@ -833,9 +833,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz", - "integrity": "sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", "cpu": [ "ia32" ], @@ -847,9 +847,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz", - "integrity": "sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", "cpu": [ "x64" ], @@ -1068,13 +1068,13 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -1134,9 +1134,9 @@ } }, "node_modules/bun": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.8.tgz", - "integrity": "sha512-TSL3POeJspEvIsfVqQZ/Sbl81kkzuUYCdE5fPdaDw0V6uU1j9d6JzfjYwNyDRnaacAAPnz3ZJukwGz3d6qJNzw==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.10.tgz", + "integrity": "sha512-qOJXrQZSzJ5DbJMt47GZGWtUSmIkbwD7fPSN/XS/T46D4cTTnPK46QDHlyC8VD+Anvs6uKNwuwKIyB31kUdHmQ==", "cpu": [ "arm64", "x64" @@ -1154,14 +1154,14 @@ "bunx": "bin/bun.exe" }, "optionalDependencies": { - "@oven/bun-darwin-aarch64": "1.1.8", - "@oven/bun-darwin-x64": "1.1.8", - "@oven/bun-darwin-x64-baseline": "1.1.8", - "@oven/bun-linux-aarch64": "1.1.8", - "@oven/bun-linux-x64": "1.1.8", - "@oven/bun-linux-x64-baseline": "1.1.8", - "@oven/bun-windows-x64": "1.1.8", - "@oven/bun-windows-x64-baseline": "1.1.8" + "@oven/bun-darwin-aarch64": "1.1.10", + "@oven/bun-darwin-x64": "1.1.10", + "@oven/bun-darwin-x64-baseline": "1.1.10", + "@oven/bun-linux-aarch64": "1.1.10", + "@oven/bun-linux-x64": "1.1.10", + "@oven/bun-linux-x64-baseline": "1.1.10", + "@oven/bun-windows-x64": "1.1.10", + "@oven/bun-windows-x64-baseline": "1.1.10" } }, "node_modules/callsites": { @@ -1188,9 +1188,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001620", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001620.tgz", - "integrity": "sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==", + "version": "1.0.30001624", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001624.tgz", + "integrity": "sha512-0dWnQG87UevOCPYaOR49CBcLBwoZLpws+k6W37nLjWUhumP1Isusj0p2u+3KhjNloRWK9OKMgjBBzPujQHw4nA==", "dev": true, "funding": [ { @@ -1630,9 +1630,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.775", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.775.tgz", - "integrity": "sha512-JpOfl1aNAiZ88wFzjPczTLwYIoPIsij8S9/XQH9lqMpiJOf23kxea68B8wje4f68t4rOIq4Bh+vP4I65njiJBw==", + "version": "1.4.783", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.783.tgz", + "integrity": "sha512-bT0jEz/Xz1fahQpbZ1D7LgmPYZ3iHVY39NcWWro1+hA2IvjiPeaXtfSqrQ+nXjApMvQRE2ASt1itSLRrebHMRQ==", "dev": true, "license": "ISC" }, @@ -1894,9 +1894,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", "dependencies": { @@ -1996,6 +1996,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -2187,6 +2188,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "license": "ISC", "dependencies": { @@ -2752,13 +2754,13 @@ "license": "ISC" }, "node_modules/playwright": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.0.tgz", - "integrity": "sha512-F9b3GUCLQ3Nffrfb6dunPOkE5Mh68tR7zN32L4jCk4FjQamgesGay7/dAAe1WaMEGV04DkdJfcJzjoCKygUaRQ==", + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.1.tgz", + "integrity": "sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.44.0" + "playwright-core": "1.44.1" }, "bin": { "playwright": "cli.js" @@ -2771,9 +2773,9 @@ } }, "node_modules/playwright-core": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.0.tgz", - "integrity": "sha512-ZTbkNpFfYcGWohvTTl+xewITm7EOuqIqex0c7dNZ+aXsbrLj0qI8XlGKfPpipjm0Wny/4Lt4CJsWJk1stVS5qQ==", + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.1.tgz", + "integrity": "sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2799,9 +2801,9 @@ } }, "node_modules/polyscript": { - "version": "0.12.10", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.10.tgz", - "integrity": "sha512-aHVHm6cphwGIlz7tHv3dY8KleVVYJfoGOHjlYyw6w/9HBiX9DHqI0X0SDdS1frXphLEF8B6OtbzqRYtKmUBNeg==", + "version": "0.12.12", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.12.tgz", + "integrity": "sha512-W+bJ3Z8CnbGA6j/ShyWYbtSGhb3nABnA4g/2qtEHkf3JHem5NvFVYcPZ3UeECBbaRBLoHYle+pybozWrPddF6A==", "license": "APACHE-2.0", "dependencies": { "@ungap/structured-clone": "^1.2.0", @@ -3360,9 +3362,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", - "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", + "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3533,9 +3535,9 @@ } }, "node_modules/rollup": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz", - "integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", "dev": true, "license": "MIT", "dependencies": { @@ -3549,22 +3551,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.17.2", - "@rollup/rollup-android-arm64": "4.17.2", - "@rollup/rollup-darwin-arm64": "4.17.2", - "@rollup/rollup-darwin-x64": "4.17.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.17.2", - "@rollup/rollup-linux-arm-musleabihf": "4.17.2", - "@rollup/rollup-linux-arm64-gnu": "4.17.2", - "@rollup/rollup-linux-arm64-musl": "4.17.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.17.2", - "@rollup/rollup-linux-riscv64-gnu": "4.17.2", - "@rollup/rollup-linux-s390x-gnu": "4.17.2", - "@rollup/rollup-linux-x64-gnu": "4.17.2", - "@rollup/rollup-linux-x64-musl": "4.17.2", - "@rollup/rollup-win32-arm64-msvc": "4.17.2", - "@rollup/rollup-win32-ia32-msvc": "4.17.2", - "@rollup/rollup-win32-x64-msvc": "4.17.2", + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", "fsevents": "~2.3.2" } }, diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 2d3fdef75ad..9d8d1c5403e 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.34", + "version": "0.4.38", "type": "module", "description": "PyScript", "module": "./index.js", @@ -43,7 +43,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.10", + "polyscript": "^0.12.12", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -54,18 +54,18 @@ "@codemirror/language": "^6.10.1", "@codemirror/state": "^6.4.1", "@codemirror/view": "^6.26.3", - "@playwright/test": "^1.44.0", - "@rollup/plugin-commonjs": "^25.0.7", + "@playwright/test": "^1.44.1", + "@rollup/plugin-commonjs": "^25.0.8", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", - "bun": "^1.1.8", + "bun": "^1.1.10", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^9.2.0", - "rollup": "^4.17.2", + "eslint": "^9.3.0", + "rollup": "^4.18.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", diff --git a/pyscript.core/src/core.js b/pyscript.core/src/core.js index 735d9c56f96..e1e45ffdc5c 100644 --- a/pyscript.core/src/core.js +++ b/pyscript.core/src/core.js @@ -24,10 +24,17 @@ import sync from "./sync.js"; import bootstrapNodeAndPlugins from "./plugins-helper.js"; import { ErrorCode } from "./exceptions.js"; import { robustFetch as fetch, getText } from "./fetch.js"; -import { hooks, main, worker, codeFor, createFunction } from "./hooks.js"; +import { + hooks, + main, + worker, + codeFor, + createFunction, + inputFailure, +} from "./hooks.js"; import { stdlib, optional } from "./stdlib.js"; -export { stdlib, optional }; +export { stdlib, optional, inputFailure }; // generic helper to disambiguate between custom element and script const isScript = ({ tagName }) => tagName === "SCRIPT"; diff --git a/pyscript.core/src/hooks.js b/pyscript.core/src/hooks.js index 03950bf4da2..acad61b1d50 100644 --- a/pyscript.core/src/hooks.js +++ b/pyscript.core/src/hooks.js @@ -46,7 +46,7 @@ export const createFunction = (self, name) => { const SetFunction = typedSet({ typeof: "function" }); const SetString = typedSet({ typeof: "string" }); -const inputFailure = ` +export const inputFailure = ` import builtins def input(prompt=""): raise Exception("\\n ".join([ diff --git a/pyscript.core/src/plugins/py-terminal.js b/pyscript.core/src/plugins/py-terminal.js index 54f1cdad382..4dfc4eb293d 100644 --- a/pyscript.core/src/plugins/py-terminal.js +++ b/pyscript.core/src/plugins/py-terminal.js @@ -1,11 +1,14 @@ // PyScript py-terminal plugin -import { TYPES, hooks } from "../core.js"; +import { TYPES } from "../core.js"; import { notify } from "./error.js"; -import { customObserver, defineProperties } from "polyscript/exports"; +import { customObserver } from "polyscript/exports"; // will contain all valid selectors const SELECTORS = []; +// avoid processing same elements twice +const processed = new WeakSet(); + // show the error on main and // stops the module from keep executing const notifyAndThrow = (message) => { @@ -15,265 +18,10 @@ const notifyAndThrow = (message) => { const onceOnMain = ({ attributes: { worker } }) => !worker; -const bootstrapped = new WeakSet(); - let addStyle = true; -// this callback will be serialized as string and it never needs -// to be invoked multiple times. Each xworker here is bootstrapped -// only once thanks to the `sync.is_pyterminal()` check. -const workerReady = ({ interpreter, io, run, type }, { sync }) => { - if (!sync.is_pyterminal()) return; - - // in workers it's always safe to grab the polyscript currentScript - // the ugly `_` dance is due MicroPython not able to import via: - // `from polyscript.currentScript import terminal as __terminal__` - run( - "from polyscript import currentScript as _; __terminal__ = _.terminal; del _", - ); - - let data = ""; - const { pyterminal_read, pyterminal_write } = sync; - const decoder = new TextDecoder(); - const generic = { - isatty: false, - write(buffer) { - data = decoder.decode(buffer); - pyterminal_write(data); - return buffer.length; - }, - }; - - // This part works already in both Pyodide and MicroPython - io.stderr = (error) => { - pyterminal_write(String(error.message || error)); - }; - - // MicroPython has no code or code.interact() - // This part patches it in a way that simulates - // the code.interact() module in Pyodide. - if (type === "mpy") { - // monkey patch global input otherwise broken in MicroPython - interpreter.registerJsModule("_pyscript_input", { - input: pyterminal_read, - }); - run("from _pyscript_input import input"); - - // this is needed to avoid truncated unicode in MicroPython - // the reason is that `linebuffer` false just send one byte - // per time and readline here doesn't like it much. - // MicroPython also has issues with code-points and - // replProcessChar(byte) but that function accepts only - // one byte per time so ... we have an issue! - // @see https://github.com/pyscript/pyscript/pull/2018 - // @see https://github.com/WebReflection/buffer-points - const bufferPoints = (stdio) => { - const bytes = []; - let needed = 0; - return (buffer) => { - let written = 0; - for (const byte of buffer) { - bytes.push(byte); - // @see https://encoding.spec.whatwg.org/#utf-8-bytes-needed - if (needed) needed--; - else if (0xc2 <= byte && byte <= 0xdf) needed = 1; - else if (0xe0 <= byte && byte <= 0xef) needed = 2; - else if (0xf0 <= byte && byte <= 0xf4) needed = 3; - if (!needed) { - written += bytes.length; - stdio(new Uint8Array(bytes.splice(0))); - } - } - return written; - }; - }; - - io.stdout = bufferPoints(generic.write); - - // tiny shim of the code module with only interact - // to bootstrap a REPL like environment - interpreter.registerJsModule("code", { - interact() { - let input = ""; - let length = 1; - - const encoder = new TextEncoder(); - const acc = []; - const handlePoints = bufferPoints((buffer) => { - acc.push(...buffer); - pyterminal_write(decoder.decode(buffer)); - }); - - // avoid duplicating the output produced by the input - io.stdout = (buffer) => - length++ > input.length ? handlePoints(buffer) : 0; - - interpreter.replInit(); - - // loop forever waiting for user inputs - (function repl() { - const out = decoder.decode(new Uint8Array(acc.splice(0))); - // print in current line only the last line produced by the REPL - const data = `${pyterminal_read(out.split("\n").at(-1))}\r`; - length = 0; - input = encoder.encode(data); - for (const c of input) interpreter.replProcessChar(c); - repl(); - })(); - }, - }); - } else { - interpreter.setStdout(generic); - interpreter.setStderr(generic); - interpreter.setStdin({ - isatty: false, - stdin: () => pyterminal_read(data), - }); - } -}; - -const pyTerminal = async (element) => { - // lazy load these only when a valid terminal is found - const [{ Terminal }, { Readline }, { FitAddon }, { WebLinksAddon }] = - await Promise.all([ - import(/* webpackIgnore: true */ "../3rd-party/xterm.js"), - import(/* webpackIgnore: true */ "../3rd-party/xterm-readline.js"), - import(/* webpackIgnore: true */ "../3rd-party/xterm_addon-fit.js"), - import( - /* webpackIgnore: true */ "../3rd-party/xterm_addon-web-links.js" - ), - ]); - - const readline = new Readline(); - - // common main thread initialization for both worker - // or main case, bootstrapping the terminal on its target - const init = (options) => { - let target = element; - const selector = element.getAttribute("target"); - if (selector) { - target = - document.getElementById(selector) || - document.querySelector(selector); - if (!target) throw new Error(`Unknown target ${selector}`); - } else { - target = document.createElement("py-terminal"); - target.style.display = "block"; - element.after(target); - } - const terminal = new Terminal({ - theme: { - background: "#191A19", - foreground: "#F5F2E7", - }, - ...options, - }); - const fitAddon = new FitAddon(); - terminal.loadAddon(fitAddon); - terminal.loadAddon(readline); - terminal.loadAddon(new WebLinksAddon()); - terminal.open(target); - fitAddon.fit(); - terminal.focus(); - defineProperties(element, { - terminal: { value: terminal }, - process: { - value: async (code) => { - // this loop is the only way I could find to actually simulate - // the user input char after char in a way that works in both - // MicroPython and Pyodide - for (const line of code.split(/(?:\r|\n|\r\n)/)) { - terminal.paste(`${line}\n`); - do { - await new Promise((resolve) => - setTimeout(resolve, 0), - ); - } while (!readline.activeRead?.resolve); - readline.activeRead.resolve(line); - } - }, - }, - }); - return terminal; - }; - - // branch logic for the worker - if (element.hasAttribute("worker")) { - // add a hook on the main thread to setup all sync helpers - // also bootstrapping the XTerm target on main *BUT* ... - hooks.main.onWorker.add(function worker(_, xworker) { - // ... as multiple workers will add multiple callbacks - // be sure no xworker is ever initialized twice! - if (bootstrapped.has(xworker)) return; - bootstrapped.add(xworker); - - // still cleanup this callback for future scripts/workers - hooks.main.onWorker.delete(worker); - - init({ - disableStdin: false, - cursorBlink: true, - cursorStyle: "block", - }); - - xworker.sync.is_pyterminal = () => true; - xworker.sync.pyterminal_read = readline.read.bind(readline); - xworker.sync.pyterminal_write = readline.write.bind(readline); - }); - - // setup remote thread JS/Python code for whenever the - // worker is ready to become a terminal - hooks.worker.onReady.add(workerReady); - } else { - // in the main case, just bootstrap XTerm without - // allowing any input as that's not possible / awkward - hooks.main.onReady.add(function main({ interpreter, io, run, type }) { - console.warn("py-terminal is read only on main thread"); - hooks.main.onReady.delete(main); - - // on main, it's easy to trash and clean the current terminal - globalThis.__py_terminal__ = init({ - disableStdin: true, - cursorBlink: false, - cursorStyle: "underline", - }); - run("from js import __py_terminal__ as __terminal__"); - delete globalThis.__py_terminal__; - - io.stderr = (error) => { - readline.write(String(error.message || error)); - }; - - if (type === "mpy") { - interpreter.setStdin = Object; // as no-op - interpreter.setStderr = Object; // as no-op - interpreter.setStdout = ({ write }) => { - io.stdout = write; - }; - } - - let data = ""; - const decoder = new TextDecoder(); - const generic = { - isatty: false, - write(buffer) { - data = decoder.decode(buffer); - readline.write(data); - return buffer.length; - }, - }; - interpreter.setStdout(generic); - interpreter.setStderr(generic); - interpreter.setStdin({ - isatty: false, - stdin: () => readline.read(data), - }); - }); - } -}; - -for (const key of TYPES.keys()) { - const selector = `script[type="${key}"][terminal],${key}-script[terminal]`; +for (const type of TYPES.keys()) { + const selector = `script[type="${type}"][terminal],${type}-script[terminal]`; SELECTORS.push(selector); customObserver.set(selector, async (element) => { // we currently support only one terminal on main as in "classic" @@ -292,6 +40,21 @@ for (const key of TYPES.keys()) { ); } - await pyTerminal(element); + if (processed.has(element)) return; + processed.add(element); + + const bootstrap = (module) => module.default(element); + + // we can't be smart with template literals for the dynamic import + // or bundlers are incapable of producing multiple files around + if (type === "mpy") { + await import(/* webpackIgnore: true */ "./py-terminal/mpy.js").then( + bootstrap, + ); + } else { + await import(/* webpackIgnore: true */ "./py-terminal/py.js").then( + bootstrap, + ); + } }); } diff --git a/pyscript.core/src/plugins/py-terminal/mpy.js b/pyscript.core/src/plugins/py-terminal/mpy.js new file mode 100644 index 00000000000..6e4a163eed1 --- /dev/null +++ b/pyscript.core/src/plugins/py-terminal/mpy.js @@ -0,0 +1,239 @@ +// PyScript pyodide terminal plugin +import { hooks, inputFailure } from "../../core.js"; +import { defineProperties } from "polyscript/exports"; + +const bootstrapped = new WeakSet(); + +// this callback will be serialized as string and it never needs +// to be invoked multiple times. Each xworker here is bootstrapped +// only once thanks to the `sync.is_pyterminal()` check. +const workerReady = ({ interpreter, io, run, type }, { sync }) => { + if (type !== "mpy" || !sync.is_pyterminal()) return; + + const { pyterminal_ready, pyterminal_read, pyterminal_write } = sync; + + interpreter.registerJsModule("_pyscript_input", { + input: pyterminal_read, + }); + + run( + [ + "from _pyscript_input import input", + "from polyscript import currentScript as _", + "__terminal__ = _.terminal", + "del _", + ].join(";"), + ); + + const missingReturn = new Uint8Array([13]); + io.stdout = (buffer) => { + if (buffer[0] === 10) pyterminal_write(missingReturn); + pyterminal_write(buffer); + }; + io.stderr = (error) => { + pyterminal_write(String(error.message || error)); + }; + + // tiny shim of the code module with only interact + // to bootstrap a REPL like environment + interpreter.registerJsModule("code", { + interact() { + const encoder = new TextEncoderStream(); + encoder.readable.pipeTo( + new WritableStream({ + write(buffer) { + for (const c of buffer) interpreter.replProcessChar(c); + }, + }), + ); + + const writer = encoder.writable.getWriter(); + sync.pyterminal_stream_write = (buffer) => writer.write(buffer); + pyterminal_ready(); + + interpreter.replInit(); + }, + }); +}; + +export default async (element) => { + // lazy load these only when a valid terminal is found + const [{ Terminal }, { FitAddon }, { WebLinksAddon }] = await Promise.all([ + import(/* webpackIgnore: true */ "../../3rd-party/xterm.js"), + import(/* webpackIgnore: true */ "../../3rd-party/xterm_addon-fit.js"), + import( + /* webpackIgnore: true */ "../../3rd-party/xterm_addon-web-links.js" + ), + ]); + + const terminalOptions = { + disableStdin: false, + cursorBlink: true, + cursorStyle: "block", + }; + + let stream; + + // common main thread initialization for both worker + // or main case, bootstrapping the terminal on its target + const init = () => { + let target = element; + const selector = element.getAttribute("target"); + if (selector) { + target = + document.getElementById(selector) || + document.querySelector(selector); + if (!target) throw new Error(`Unknown target ${selector}`); + } else { + target = document.createElement("py-terminal"); + target.style.display = "block"; + element.after(target); + } + const terminal = new Terminal({ + theme: { + background: "#191A19", + foreground: "#F5F2E7", + }, + ...terminalOptions, + }); + const fitAddon = new FitAddon(); + terminal.loadAddon(fitAddon); + terminal.loadAddon(new WebLinksAddon()); + terminal.open(target); + fitAddon.fit(); + terminal.focus(); + defineProperties(element, { + terminal: { value: terminal }, + process: { + value: async (code) => { + for (const line of code.split(/(?:\r\n|\r|\n)/)) { + await stream.write(`${line}\r`); + } + }, + }, + }); + return terminal; + }; + + // branch logic for the worker + if (element.hasAttribute("worker")) { + // add a hook on the main thread to setup all sync helpers + // also bootstrapping the XTerm target on main *BUT* ... + hooks.main.onWorker.add(function worker(_, xworker) { + // ... as multiple workers will add multiple callbacks + // be sure no xworker is ever initialized twice! + if (bootstrapped.has(xworker)) return; + bootstrapped.add(xworker); + + // still cleanup this callback for future scripts/workers + hooks.main.onWorker.delete(worker); + + const terminal = init(); + + const { sync } = xworker; + + // handle the read mode on input + let promisedChunks = null; + let readChunks = ""; + + sync.is_pyterminal = () => true; + + // put the terminal in a read-only state + // frees the worker on \r + sync.pyterminal_read = (buffer) => { + terminal.write(buffer); + promisedChunks = Promise.withResolvers(); + return promisedChunks.promise; + }; + + // write if not reading input + sync.pyterminal_write = (buffer) => { + if (!promisedChunks) terminal.write(buffer); + }; + + // add the onData terminal listener which forwards to the worker + // everything typed in a queued char-by-char way + sync.pyterminal_ready = () => { + let queue = Promise.resolve(); + stream = { + write: (buffer) => + (queue = queue.then(() => + sync.pyterminal_stream_write(buffer), + )), + }; + terminal.onData((buffer) => { + if (promisedChunks) { + readChunks += buffer; + terminal.write(buffer); + if (readChunks.endsWith("\r")) { + terminal.write("\n"); + promisedChunks.resolve(readChunks.slice(0, -1)); + promisedChunks = null; + readChunks = ""; + } + } else { + stream.write(buffer); + } + }); + }; + }); + + // setup remote thread JS/Python code for whenever the + // worker is ready to become a terminal + hooks.worker.onReady.add(workerReady); + } else { + // ⚠️ In an ideal world the inputFailure should never be used on main. + // However, Pyodide still can't compete with MicroPython REPL mode + // so while it's OK to keep that entry on main as default, we need + // to remove it ASAP from `mpy` use cases, otherwise MicroPython would + // also throw whenever an `input(...)` is required / digited. + hooks.main.codeBeforeRun.delete(inputFailure); + + // in the main case, just bootstrap XTerm without + // allowing any input as that's not possible / awkward + hooks.main.onReady.add(function main({ interpreter, io, run, type }) { + if (type !== "mpy") return; + + hooks.main.onReady.delete(main); + + const terminal = init(); + + const missingReturn = new Uint8Array([13]); + io.stdout = (buffer) => { + if (buffer[0] === 10) terminal.write(missingReturn); + terminal.write(buffer); + }; + + // expose the __terminal__ one-off reference + globalThis.__py_terminal__ = terminal; + run( + [ + "from js import prompt as input", + "from js import __py_terminal__ as __terminal__", + ].join(";"), + ); + delete globalThis.__py_terminal__; + + // NOTE: this is NOT the same as the one within + // the onWorkerReady callback! + interpreter.registerJsModule("code", { + interact() { + const encoder = new TextEncoderStream(); + encoder.readable.pipeTo( + new WritableStream({ + write(buffer) { + for (const c of buffer) + interpreter.replProcessChar(c); + }, + }), + ); + + stream = encoder.writable.getWriter(); + terminal.onData((buffer) => stream.write(buffer)); + + interpreter.replInit(); + }, + }); + }); + } +}; diff --git a/pyscript.core/src/plugins/py-terminal/py.js b/pyscript.core/src/plugins/py-terminal/py.js new file mode 100644 index 00000000000..4ca6d1f7e4d --- /dev/null +++ b/pyscript.core/src/plugins/py-terminal/py.js @@ -0,0 +1,179 @@ +// PyScript py-terminal plugin +import { hooks } from "../../core.js"; +import { defineProperties } from "polyscript/exports"; + +const bootstrapped = new WeakSet(); + +// this callback will be serialized as string and it never needs +// to be invoked multiple times. Each xworker here is bootstrapped +// only once thanks to the `sync.is_pyterminal()` check. +const workerReady = ({ interpreter, io, run, type }, { sync }) => { + if (type !== "py" || !sync.is_pyterminal()) return; + + run( + [ + "from polyscript import currentScript as _", + "__terminal__ = _.terminal", + "del _", + ].join(";"), + ); + + let data = ""; + const { pyterminal_read, pyterminal_write } = sync; + const decoder = new TextDecoder(); + const generic = { + isatty: false, + write(buffer) { + data = decoder.decode(buffer); + pyterminal_write(data); + return buffer.length; + }, + }; + + io.stderr = (error) => { + pyterminal_write(String(error.message || error)); + }; + + interpreter.setStdout(generic); + interpreter.setStderr(generic); + interpreter.setStdin({ + isatty: false, + stdin: () => pyterminal_read(data), + }); +}; + +export default async (element) => { + // lazy load these only when a valid terminal is found + const [{ Terminal }, { Readline }, { FitAddon }, { WebLinksAddon }] = + await Promise.all([ + import(/* webpackIgnore: true */ "../../3rd-party/xterm.js"), + import( + /* webpackIgnore: true */ "../../3rd-party/xterm-readline.js" + ), + import( + /* webpackIgnore: true */ "../../3rd-party/xterm_addon-fit.js" + ), + import( + /* webpackIgnore: true */ "../../3rd-party/xterm_addon-web-links.js" + ), + ]); + + const readline = new Readline(); + + // common main thread initialization for both worker + // or main case, bootstrapping the terminal on its target + const init = (options) => { + let target = element; + const selector = element.getAttribute("target"); + if (selector) { + target = + document.getElementById(selector) || + document.querySelector(selector); + if (!target) throw new Error(`Unknown target ${selector}`); + } else { + target = document.createElement("py-terminal"); + target.style.display = "block"; + element.after(target); + } + const terminal = new Terminal({ + theme: { + background: "#191A19", + foreground: "#F5F2E7", + }, + ...options, + }); + const fitAddon = new FitAddon(); + terminal.loadAddon(fitAddon); + terminal.loadAddon(readline); + terminal.loadAddon(new WebLinksAddon()); + terminal.open(target); + fitAddon.fit(); + terminal.focus(); + defineProperties(element, { + terminal: { value: terminal }, + process: { + value: async (code) => { + for (const line of code.split(/(?:\r\n|\r|\n)/)) { + terminal.paste(`${line}`); + terminal.write("\r\n"); + do { + await new Promise((resolve) => + setTimeout(resolve, 0), + ); + } while (!readline.activeRead?.resolve); + readline.activeRead.resolve(line); + } + }, + }, + }); + return terminal; + }; + + // branch logic for the worker + if (element.hasAttribute("worker")) { + // add a hook on the main thread to setup all sync helpers + // also bootstrapping the XTerm target on main *BUT* ... + hooks.main.onWorker.add(function worker(_, xworker) { + // ... as multiple workers will add multiple callbacks + // be sure no xworker is ever initialized twice! + if (bootstrapped.has(xworker)) return; + bootstrapped.add(xworker); + + // still cleanup this callback for future scripts/workers + hooks.main.onWorker.delete(worker); + + init({ + disableStdin: false, + cursorBlink: true, + cursorStyle: "block", + }); + + xworker.sync.is_pyterminal = () => true; + xworker.sync.pyterminal_read = readline.read.bind(readline); + xworker.sync.pyterminal_write = readline.write.bind(readline); + }); + + // setup remote thread JS/Python code for whenever the + // worker is ready to become a terminal + hooks.worker.onReady.add(workerReady); + } else { + // in the main case, just bootstrap XTerm without + // allowing any input as that's not possible / awkward + hooks.main.onReady.add(function main({ interpreter, io, run, type }) { + if (type !== "py") return; + + console.warn("py-terminal is read only on main thread"); + hooks.main.onReady.delete(main); + + // on main, it's easy to trash and clean the current terminal + globalThis.__py_terminal__ = init({ + disableStdin: true, + cursorBlink: false, + cursorStyle: "underline", + }); + run("from js import __py_terminal__ as __terminal__"); + delete globalThis.__py_terminal__; + + io.stderr = (error) => { + readline.write(String(error.message || error)); + }; + + let data = ""; + const decoder = new TextDecoder(); + const generic = { + isatty: false, + write(buffer) { + data = decoder.decode(buffer); + readline.write(data); + return buffer.length; + }, + }; + interpreter.setStdout(generic); + interpreter.setStderr(generic); + interpreter.setStdin({ + isatty: false, + stdin: () => readline.read(data), + }); + }); + } +}; diff --git a/pyscript.core/test-results/.last-run.json b/pyscript.core/test-results/.last-run.json deleted file mode 100644 index f740f7c7003..00000000000 --- a/pyscript.core/test-results/.last-run.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "status": "passed", - "failedTests": [] -} diff --git a/pyscript.core/test/py-terminal-worker.html b/pyscript.core/test/py-terminal-worker.html index 1e4e138e9b3..3201c99ee12 100644 --- a/pyscript.core/test/py-terminal-worker.html +++ b/pyscript.core/test/py-terminal-worker.html @@ -10,6 +10,6 @@ - + diff --git a/pyscript.core/types/core.d.ts b/pyscript.core/types/core.d.ts index 0b3f20b6943..142ca999a81 100644 --- a/pyscript.core/types/core.d.ts +++ b/pyscript.core/types/core.d.ts @@ -1,6 +1,7 @@ export function offline_interpreter(config: any): string; import { stdlib } from "./stdlib.js"; import { optional } from "./stdlib.js"; +import { inputFailure } from "./hooks.js"; import TYPES from "./types.js"; /** * A `Worker` facade able to bootstrap on the worker thread only a PyScript module. @@ -53,4 +54,4 @@ declare const exportedHooks: { }; declare const exportedConfig: {}; declare const exportedWhenDefined: (type: string) => Promise; -export { stdlib, optional, TYPES, exportedPyWorker as PyWorker, exportedMPWorker as MPWorker, exportedHooks as hooks, exportedConfig as config, exportedWhenDefined as whenDefined }; +export { stdlib, optional, inputFailure, TYPES, exportedPyWorker as PyWorker, exportedMPWorker as MPWorker, exportedHooks as hooks, exportedConfig as config, exportedWhenDefined as whenDefined }; diff --git a/pyscript.core/types/hooks.d.ts b/pyscript.core/types/hooks.d.ts index 6e676d42e8b..cb52f57a64e 100644 --- a/pyscript.core/types/hooks.d.ts +++ b/pyscript.core/types/hooks.d.ts @@ -2,6 +2,7 @@ export function main(name: any): any; export function worker(name: any): any; export function codeFor(branch: any, type: any): {}; export function createFunction(self: any, name: any): any; +export const inputFailure: "\n import builtins\n def input(prompt=\"\"):\n raise Exception(\"\\n \".join([\n \"input() doesn't work when PyScript runs in the main thread.\",\n \"Consider using the worker attribute: https://pyscript.github.io/docs/2023.11.2/user-guide/workers/\"\n ]))\n\n builtins.input = input\n del builtins\n del input\n"; export namespace hooks { namespace main { let onWorker: Set; diff --git a/pyscript.core/types/plugins/py-terminal/mpy.d.ts b/pyscript.core/types/plugins/py-terminal/mpy.d.ts new file mode 100644 index 00000000000..a45471b4e48 --- /dev/null +++ b/pyscript.core/types/plugins/py-terminal/mpy.d.ts @@ -0,0 +1,2 @@ +declare function _default(element: any): Promise; +export default _default; diff --git a/pyscript.core/types/plugins/py-terminal/py.d.ts b/pyscript.core/types/plugins/py-terminal/py.d.ts new file mode 100644 index 00000000000..a45471b4e48 --- /dev/null +++ b/pyscript.core/types/plugins/py-terminal/py.d.ts @@ -0,0 +1,2 @@ +declare function _default(element: any): Promise; +export default _default; From 320a537db2cea6d5522c0981957e5927cf75d931 Mon Sep 17 00:00:00 2001 From: Brendan Date: Thu, 30 May 2024 09:25:58 -0500 Subject: [PATCH 056/179] Add step in build process to publish a tarfile (#2077) Co-authored-by: Andrea Giammarchi --- .github/workflows/publish-release.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 64f4f9ef693..0a5052bf4a0 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -46,6 +46,10 @@ jobs: working-directory: . run: sed 's#_PATH_#https://pyscript.net/releases/${{ github.ref_name }}/#' ./public/index.html > ./pyscript.core/dist/index.html + - name: Generate release.tar from snapshot and put it in dist/ + working-directory: . + run: tar -cvf ../release.tar * && mv ../release.tar . + - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: From 9abaef33bdedc7b31611484dfd0c5031f32a0efe Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Fri, 31 May 2024 11:50:30 +0200 Subject: [PATCH 057/179] Fix #2067 - Enable .whl packages (#2084) --- pyscript.core/package-lock.json | 12 ++++++------ pyscript.core/package.json | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 102864a4301..84dbdf68a04 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.4.38", + "version": "0.4.40", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.38", + "version": "0.4.40", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.12", + "polyscript": "^0.12.14", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -2801,9 +2801,9 @@ } }, "node_modules/polyscript": { - "version": "0.12.12", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.12.tgz", - "integrity": "sha512-W+bJ3Z8CnbGA6j/ShyWYbtSGhb3nABnA4g/2qtEHkf3JHem5NvFVYcPZ3UeECBbaRBLoHYle+pybozWrPddF6A==", + "version": "0.12.14", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.14.tgz", + "integrity": "sha512-inflltAxoMmZZ1qGYIPPBe8KZFPtcatqUCbJjvTzR/gRHpa6PfcZQi2p4HobqDVZLc3LXdODi/GtRxZuRK8a3w==", "license": "APACHE-2.0", "dependencies": { "@ungap/structured-clone": "^1.2.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 9d8d1c5403e..133b127557f 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.38", + "version": "0.4.40", "type": "module", "description": "PyScript", "module": "./index.js", @@ -43,7 +43,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.12", + "polyscript": "^0.12.14", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" From cb9ee6f7e29f91d943225e5b87cfb114f66bab11 Mon Sep 17 00:00:00 2001 From: Jeff Glass Date: Mon, 3 Jun 2024 04:14:27 -0400 Subject: [PATCH 058/179] Update README.md, `2023.11.2` -> `2024.5.2` (#2085) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cf3bdd5a326..3e658ac1fef 100644 --- a/README.md +++ b/README.md @@ -38,11 +38,11 @@ To try PyScript, import the appropriate pyscript files into the `` tag of From 2ac5ca79d7d9d9aab350d26008e45bb5062d33b9 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Mon, 3 Jun 2024 12:32:54 +0200 Subject: [PATCH 059/179] Expose py-editor code content read/write (#2087) * Expose py-editor code content read/write * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/package-lock.json | 131 +++++++++++++------------ pyscript.core/package.json | 6 +- pyscript.core/src/plugins/py-editor.js | 15 +++ 3 files changed, 85 insertions(+), 67 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 84dbdf68a04..6b5620cd007 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.40", + "version": "0.4.41", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.40", + "version": "0.4.41", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", @@ -29,10 +29,10 @@ "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", - "bun": "^1.1.10", + "bun": "^1.1.12", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^9.3.0", + "eslint": "^9.4.0", "rollup": "^4.18.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", @@ -185,6 +185,21 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.15.1.tgz", + "integrity": "sha512-K4gzNq+yymn/EVsXYmf+SBcBro8MTf+aXJZUphM96CdzUEr+ClGDvAbpmaEK+cGVigVXIgs9gNmvHAlrzzY5JQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", @@ -210,28 +225,23 @@ } }, "node_modules/@eslint/js": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.3.0.tgz", - "integrity": "sha512-niBqk8iwv96+yuTwjM6bWg8ovzAPF9qkICsGtcoa5/dmqcEMfdwNAX7+/OHcJHc7wj7XqPxH98oAHytFYlw6Sw==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.4.0.tgz", + "integrity": "sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg==", "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "node_modules/@eslint/object-schema": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.3.tgz", + "integrity": "sha512-HAbhAYKfsAC2EkTqve00ibWIZlaU74Z1EHwAjYr4PXF0YU2VEA1zSIKSSpKszRLRWwHzzRZXvK632u+uXzvsvw==", "dev": true, "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, "engines": { - "node": ">=10.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -248,13 +258,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/@humanwhocodes/retry": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", @@ -411,9 +414,9 @@ } }, "node_modules/@oven/bun-darwin-aarch64": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.10.tgz", - "integrity": "sha512-5x6QGEzTurmCPZM3OLosIJE0QynhKfKZZ6uSVl7C36mNPFAZfTXjK64LgbM+4P9Kr0PyEQnZweLlScl+HaEJcw==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.12.tgz", + "integrity": "sha512-g8nmDXIYDmbEnP6moX3ZTS5BsikX8dz/XB0PAfL+LEBJEGECyor2Hv1yvhGQfeR1/lvfSXsWnk0Hhk9Mrj6uoQ==", "cpu": [ "arm64" ], @@ -425,9 +428,9 @@ ] }, "node_modules/@oven/bun-darwin-x64": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.10.tgz", - "integrity": "sha512-DYbp2koaATwWikMIyeWLq2LhLZtvxzr4WuFIBe4+KwoWLGXJEC8uK9QsTwis/tCLPH45ov9DMwDmBA31oX+0iA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.12.tgz", + "integrity": "sha512-XWL6atcLxyh4KgOlqqyHUOh4Ylm46CExipJmAdKs30gyYqbw3E+HTFhADsyFEtugOe0qPUNlo0aMo+ZMc1yIQA==", "cpu": [ "x64" ], @@ -439,9 +442,9 @@ ] }, "node_modules/@oven/bun-darwin-x64-baseline": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.10.tgz", - "integrity": "sha512-a/P612tHH86gpBiITwHmrpFMLT9Z/v6VxBKpPK+FgejIgLDGvzfIOxbNtBeGygWbZaAFDQfRRQJFGpVHvjwGQA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.12.tgz", + "integrity": "sha512-KXBwaeD9y4GuxSqC1uDNIktTC/jY2DtagiURuUOF1rniYxkkLRNgXotTvVA5NvP2PBCoWyrxZ67WJSBm0AIyjQ==", "cpu": [ "x64" ], @@ -453,9 +456,9 @@ ] }, "node_modules/@oven/bun-linux-aarch64": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.10.tgz", - "integrity": "sha512-iR7TRUWtVtrPe+iZu1ISQNbz7M6HxMRtn4PCr/a6dswuPkIhvXxTJUD6WTpHnHxsgioS5GHG9eonu03PTeBY0Q==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.12.tgz", + "integrity": "sha512-6Jen4+b5BzInF7bbRjMIWoy3xIuK/kQQn9xehvrAYnr3J9p3vCD5VhzDP20hW9yQcmZtO2kE6pIYCbaaxPNKtg==", "cpu": [ "arm64" ], @@ -467,9 +470,9 @@ ] }, "node_modules/@oven/bun-linux-x64": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.10.tgz", - "integrity": "sha512-pUgLdu/5Yn+hV8aIwZE0x2H/t2QQRIPWUibnUdDLglnNtGjaqNUyST9iVN5TD7NdMk1p342GDc9rouA8VxAHHA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.12.tgz", + "integrity": "sha512-X4dqnIOv4M9HAL4tAj9bb14WjsfKby5xWNV/otUxtfSDsDrV2ukYUekivEmHqchxHFUHOHyc/cv+/jtfvedDZg==", "cpu": [ "x64" ], @@ -481,9 +484,9 @@ ] }, "node_modules/@oven/bun-linux-x64-baseline": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.10.tgz", - "integrity": "sha512-TjBH/KIyI/4Ms3PJYRm2QEgI7HOyV5fXdwqwB/40SCPXND6wq0u4voHDIINc9rdHDRXpmO8RPUFWsKNuN3Mf5w==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.12.tgz", + "integrity": "sha512-luwWf/QGMJ23+yIRBMDnhjYuxh9zXy+Vw4lAzwvLB7phYXCs7IPEhIhZxhcZQ3XMafWtHlWAVo5P6NZZdFRMUQ==", "cpu": [ "x64" ], @@ -495,9 +498,9 @@ ] }, "node_modules/@oven/bun-windows-x64": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.10.tgz", - "integrity": "sha512-+KiITh1xyrDGoRXM3HLHyO9iweaMZ9T41KP4cbov92D78SKxR5jpq1LDLPhWK668a0aNX/r9PGePkPNt4yg/HA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.12.tgz", + "integrity": "sha512-ufvTeXXI9tJSJUhvdPnFUmGqCNBKBazEwjvQ5c8vhtZ8hdBHV54LoURVDIBYCgzfdv5NQT3sr8qRLFqy4mlMLg==", "cpu": [ "x64" ], @@ -509,9 +512,9 @@ ] }, "node_modules/@oven/bun-windows-x64-baseline": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.10.tgz", - "integrity": "sha512-+q2pDLq9VCXYJ89pcT5AevXUTGdDoqgq+scE3qlKLclSxtSR25K18C61D9rpqgiueC6jLrxIN13w5qOi4B3LfQ==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.12.tgz", + "integrity": "sha512-MRn+zcJO1hcVqwJmFxpUSdb6ZvrYC8Xp2N1fPOzdw3YSskz9iHkJuUKzx7s9iCC7jTpo6XI/H51EFr/M2U7Ipg==", "cpu": [ "x64" ], @@ -1134,9 +1137,9 @@ } }, "node_modules/bun": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.10.tgz", - "integrity": "sha512-qOJXrQZSzJ5DbJMt47GZGWtUSmIkbwD7fPSN/XS/T46D4cTTnPK46QDHlyC8VD+Anvs6uKNwuwKIyB31kUdHmQ==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.12.tgz", + "integrity": "sha512-NZzeZuZk7VwCs8VAXnXUHCPOlTS/IyHCscChtT1M1FLSwhBcVMsGVStYlXaaoqsinBKgp0CGJdhnJw2gR3NkDw==", "cpu": [ "arm64", "x64" @@ -1154,14 +1157,14 @@ "bunx": "bin/bun.exe" }, "optionalDependencies": { - "@oven/bun-darwin-aarch64": "1.1.10", - "@oven/bun-darwin-x64": "1.1.10", - "@oven/bun-darwin-x64-baseline": "1.1.10", - "@oven/bun-linux-aarch64": "1.1.10", - "@oven/bun-linux-x64": "1.1.10", - "@oven/bun-linux-x64-baseline": "1.1.10", - "@oven/bun-windows-x64": "1.1.10", - "@oven/bun-windows-x64-baseline": "1.1.10" + "@oven/bun-darwin-aarch64": "1.1.12", + "@oven/bun-darwin-x64": "1.1.12", + "@oven/bun-darwin-x64-baseline": "1.1.12", + "@oven/bun-linux-aarch64": "1.1.12", + "@oven/bun-linux-x64": "1.1.12", + "@oven/bun-linux-x64-baseline": "1.1.12", + "@oven/bun-windows-x64": "1.1.12", + "@oven/bun-windows-x64-baseline": "1.1.12" } }, "node_modules/callsites": { @@ -1677,17 +1680,17 @@ } }, "node_modules/eslint": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.3.0.tgz", - "integrity": "sha512-5Iv4CsZW030lpUqHBapdPo3MJetAPtejVW8B84GIcIIv8+ohFaddXsrn1Gn8uD9ijDb+kcYKFUVmC8qG8B2ORQ==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.4.0.tgz", + "integrity": "sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", + "@eslint/config-array": "^0.15.1", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.3.0", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint/js": "9.4.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 133b127557f..2808f3f439c 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.40", + "version": "0.4.41", "type": "module", "description": "PyScript", "module": "./index.js", @@ -61,10 +61,10 @@ "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", - "bun": "^1.1.10", + "bun": "^1.1.12", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^9.3.0", + "eslint": "^9.4.0", "rollup": "^4.18.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", diff --git a/pyscript.core/src/plugins/py-editor.js b/pyscript.core/src/plugins/py-editor.js index 73494b95c6e..a87087d7cff 100644 --- a/pyscript.core/src/plugins/py-editor.js +++ b/pyscript.core/src/plugins/py-editor.js @@ -184,6 +184,21 @@ const init = async (script, type, interpreter) => { let target; defineProperties(script, { target: { get: () => target }, + code: { + get: () => context.pySrc, + set: (insert) => { + if (isSetup) return; + editor.update([ + editor.state.update({ + changes: { + from: 0, + to: editor.state.doc.length, + insert, + }, + }), + ]); + }, + }, process: { /** * Simulate a setup node overriding the source to evaluate. From ac56f82c6d731031f81ed1ac9041875d101dbe6f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 09:36:04 +0200 Subject: [PATCH 060/179] [pre-commit.ci] pre-commit autoupdate (#2089) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/codespell-project/codespell: v2.2.6 → v2.3.0](https://github.com/codespell-project/codespell/compare/v2.2.6...v2.3.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6240966201a..89c9b304ca1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: exclude: pyscript\.core/src/stdlib/pyscript/__init__\.py - repo: https://github.com/codespell-project/codespell - rev: v2.2.6 + rev: v2.3.0 hooks: - id: codespell # See 'pyproject.toml' for args exclude: \.js\.map$ From 1c675307e1d8ad5ccfe8198e2e9cdb9b918d314e Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Tue, 4 Jun 2024 19:08:52 +0200 Subject: [PATCH 061/179] Expose pyscript.py_import and js_import for lazy Python/JS modules (#2091) * Expose pyscript.py_modules for lazy Python modules * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- pyscript.core/package-lock.json | 30 +++++++++---------- pyscript.core/package.json | 8 ++--- pyscript.core/src/core.js | 1 + pyscript.core/src/stdlib/pyscript/__init__.py | 2 ++ pyscript.core/src/stdlib/pyscript/magic_js.py | 6 +++- pyscript.core/test/py_modules.html | 27 +++++++++++++++++ 6 files changed, 54 insertions(+), 20 deletions(-) create mode 100644 pyscript.core/test/py_modules.html diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 6b5620cd007..dda92be5dbf 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.41", + "version": "0.4.42", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.41", + "version": "0.4.42", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", @@ -17,11 +17,11 @@ "type-checked-collections": "^0.1.7" }, "devDependencies": { - "@codemirror/commands": "^6.5.0", + "@codemirror/commands": "^6.6.0", "@codemirror/lang-python": "^6.1.6", - "@codemirror/language": "^6.10.1", + "@codemirror/language": "^6.10.2", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.26.3", + "@codemirror/view": "^6.27.0", "@playwright/test": "^1.44.1", "@rollup/plugin-commonjs": "^25.0.8", "@rollup/plugin-node-resolve": "^15.2.3", @@ -62,15 +62,15 @@ } }, "node_modules/@codemirror/commands": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.5.0.tgz", - "integrity": "sha512-rK+sj4fCAN/QfcY9BEzYMgp4wwL/q5aj/VfNSoH1RWPF9XS/dUwBkvlL3hpWgEjOqlpdN1uLC9UkjJ4tmyjJYg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.6.0.tgz", + "integrity": "sha512-qnY+b7j1UNcTS31Eenuc/5YJB6gQOzkUoNmJQc0rznwqSRpeaWWpjkWy2C/MPTcePpsKJEM26hXrOXl1+nceXg==", "dev": true, "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.4.0", - "@codemirror/view": "^6.0.0", + "@codemirror/view": "^6.27.0", "@lezer/common": "^1.1.0" } }, @@ -89,9 +89,9 @@ } }, "node_modules/@codemirror/language": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.1.tgz", - "integrity": "sha512-5GrXzrhq6k+gL5fjkAwt90nYDmjlzTIJV8THnxNFtNKWotMIlzzN+CpqxqwXOECnUdOndmSeWntVrVcv5axWRQ==", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.2.tgz", + "integrity": "sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==", "dev": true, "license": "MIT", "dependencies": { @@ -135,9 +135,9 @@ "license": "MIT" }, "node_modules/@codemirror/view": { - "version": "6.26.3", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.3.tgz", - "integrity": "sha512-gmqxkPALZjkgSxIeeweY/wGQXBfwTUaLs8h7OKtSwfbj9Ct3L11lD+u1sS7XHppxFQoMDiMDp07P9f3I2jWOHw==", + "version": "6.27.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.27.0.tgz", + "integrity": "sha512-8kqX1sHbVW1lVzWwrjAbh4dR7eKhV8eIQ952JKaBXOoXE04WncoqCy4DMU701LSrPZ3N2Q4zsTawz7GQ+2mrUw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 2808f3f439c..a52aae3ffab 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.41", + "version": "0.4.42", "type": "module", "description": "PyScript", "module": "./index.js", @@ -49,11 +49,11 @@ "type-checked-collections": "^0.1.7" }, "devDependencies": { - "@codemirror/commands": "^6.5.0", + "@codemirror/commands": "^6.6.0", "@codemirror/lang-python": "^6.1.6", - "@codemirror/language": "^6.10.1", + "@codemirror/language": "^6.10.2", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.26.3", + "@codemirror/view": "^6.27.0", "@playwright/test": "^1.44.1", "@rollup/plugin-commonjs": "^25.0.8", "@rollup/plugin-node-resolve": "^15.2.3", diff --git a/pyscript.core/src/core.js b/pyscript.core/src/core.js index e1e45ffdc5c..56f7117a954 100644 --- a/pyscript.core/src/core.js +++ b/pyscript.core/src/core.js @@ -157,6 +157,7 @@ for (const [TYPE, interpreter] of TYPES) { // enrich the Python env with some JS utility for main interpreter.registerJsModule("_pyscript", { PyWorker, + js_import: (...urls) => Promise.all(urls.map((url) => import(url))), get target() { return isScript(currentElement) ? currentElement.target.id diff --git a/pyscript.core/src/stdlib/pyscript/__init__.py b/pyscript.core/src/stdlib/pyscript/__init__.py index 594e528b83f..f291e491607 100644 --- a/pyscript.core/src/stdlib/pyscript/__init__.py +++ b/pyscript.core/src/stdlib/pyscript/__init__.py @@ -29,6 +29,7 @@ # pyscript.magic_js. This is the blessed way to access them from pyscript, # as it works transparently in both the main thread and worker cases. +from polyscript import lazy_py_modules as py_import from pyscript.display import HTML, display from pyscript.fetch import fetch from pyscript.magic_js import ( @@ -37,6 +38,7 @@ config, current_target, document, + js_import, js_modules, sync, window, diff --git a/pyscript.core/src/stdlib/pyscript/magic_js.py b/pyscript.core/src/stdlib/pyscript/magic_js.py index 845799134a9..3e772b20309 100644 --- a/pyscript.core/src/stdlib/pyscript/magic_js.py +++ b/pyscript.core/src/stdlib/pyscript/magic_js.py @@ -42,6 +42,10 @@ def __getattr__(self, field): window = polyscript.xworker.window document = window.document js.document = document + # this is the same as js_import on main and it lands modules on main + js_import = window.Function( + "return (...urls) => Promise.all(urls.map((url) => import(url)))" + )() except: globalThis.console.debug("SharedArrayBuffer is not available") # in this scenario none of the utilities would work @@ -64,7 +68,7 @@ def current_target(): else: import _pyscript - from _pyscript import PyWorker + from _pyscript import PyWorker, js_import window = globalThis document = globalThis.document diff --git a/pyscript.core/test/py_modules.html b/pyscript.core/test/py_modules.html new file mode 100644 index 00000000000..58c837149a1 --- /dev/null +++ b/pyscript.core/test/py_modules.html @@ -0,0 +1,27 @@ + + + + + + + + + + + + From b41cfb7b60675d2ed89b6517019a7f0930fe6816 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Tue, 4 Jun 2024 16:30:34 -0400 Subject: [PATCH 062/179] UI creation API (#1960) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add JSProperty to pydom so it can be used to create descriptors mapping to specific JS attributes * add pyweb.ui * fix pyweb imports * fix link and a elements and add a script element * fix imports and add initialization to load resources to shoelace module * new pyweb.ui test folder * remove comments * add Icon to shoelace components * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * use html property rather than accessing _js directly * add markdown suppport * move examples section out of stdlib pyweb to examples.py in the demo itself * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * simplify demo code * improve docstrings * precommit fixes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * simplify code for main page * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add load_resources to markdown * add showlace extra style dynamically * precommit * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add gallery files * add global attributes and dynamic property assignment * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add shoelace radio component (#1961) * add shoelace radio component * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * fix type that lead using the the JSDescriptor directly instead of the factory method * add missing marked dependency * refactor gallary to simplify codebase * precommig lint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add text attribute to pydom Elements * add global JS attributes to elements and improve demos * lint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix image instantiation on card since the API has changed * add attributes to all classes in elements * lint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * change example creation functions to take the label and the object directly * fix input name clashing with input keyword * refactor examples to better simplify and automate * fix div clashing names * fix demo left menu width * simplify base elements demo by moving all the examples to the examples module * rename Grid to grid to align to other elements * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * reorg classes order in elements.py and add missing elements to examples * fix issue related to now importing div from pyweb.ui * improve demo * link and fix spelling typo * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add a bunch more elements (#1966) * Add copy button * Add skeleton and spinner * Add Switch * Add text area * Add more elements * More styling to each component * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Fabio Pliger * Add radio group (#1963) * add radio group * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Fabio Pliger * Small tweaks to main demo page (#1962) * Small tweaks to main demo page * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Fabio Pliger * fix post merge issues * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fixed issues with renaming Grid to grid, after we merged * lint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add multple HTML elements in alphabetical order from abbr to em * fix attributes of some of the elements added in the previous commit and add embed * fix embed attributes and add fieldset * add figcation, figure and form. Also fix ordering of definitoin of img and input_ * add style and lint * wrap up adding all major html elements * fix test failing due to different error message from fake server compared to a real test server * change default docstring associated with all classes dynamically patched * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * lint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add pyweb tests * lint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add global attributes and change abbr test * fix abbr to inherit from TextElementBase * add address test and improve error messaging when ElementBase gets a bad input as style * change test helper function to be more flexible on attributes and manage content vs non content based elements. Also adds area tests * add test for more elements up to caption * fix canvas and caption as elements that have content and fix name typo on figcaption * fix another typo on figcaption * minor fixes and complete tests for all elements * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * adapt shoelace to latest upates in ui.elements * fix issue with example code not showing created button * move global attributes to base class * replace all the calls to _add_js_properties with defining attributes directly in the classes * finish moving all properties manually on each class * remove _add_js_properties * replace JSProperty with js_property * replace JSProperty with js_property * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fixed merge conflicts * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * remove js_property and just use JSProperty with name and allow_nones as arguments * fix bug around Element not being able to map global attributes in subclasses * remove js_property and fix references * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * precommit * precommit again * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * lint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * enable pyweb on micropython * switch examples to micropython * fix pydom issue with micropython, created by the monkeypatch around JsProxy * print micropython version on micropython pydom example * lint and remove of textwrap in stdlib for micropython compatibility * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * added msising attributes on the option Element. Tests are all passing now * fix tests * lint * temp ugly fix for micropython, using the when decorator with a function without arguments * small fixes and improvements to examples * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix examples and broken link from the removal of markdown and shoelace from stdlib * lint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * dynamically change the server address in tests * use the right element in test_a * lint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * skipping test_audio in CI due to different behavior of fake_server vs a real server, that runs in local tests * add conditional expected_missing_file_errors property to manage different behaviour between local tests and CI (due to fake_server) * lint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Askat Co-authored-by: Fábio Rosado Co-authored-by: Andrea Giammarchi --- pyscript.core/src/stdlib.js | 2 +- .../src/stdlib/pyscript/event_handling.py | 7 +- pyscript.core/src/stdlib/pyweb/__init__.py | 1 + pyscript.core/src/stdlib/pyweb/pydom.py | 21 +- pyscript.core/src/stdlib/pyweb/ui/__init__.py | 1 + pyscript.core/src/stdlib/pyweb/ui/elements.py | 947 ++++++++++++++++++ pyscript.core/test/pydom.html | 2 +- pyscript.core/test/pydom.py | 3 + pyscript.core/test/pydom_mp.html | 2 + pyscript.core/test/ui/demo.py | 251 +++++ pyscript.core/test/ui/examples.py | 300 ++++++ pyscript.core/test/ui/gallery.html | 31 + pyscript.core/test/ui/gallery.py | 180 ++++ pyscript.core/test/ui/index.html | 39 + pyscript.core/test/ui/pyscript.toml | 8 + .../tests/integration/test_00_support.py | 26 +- pyscript.core/tests/integration/test_pyweb.py | 605 +++++++++++ pyscript.core/types/stdlib/pyscript.d.ts | 4 + 18 files changed, 2412 insertions(+), 18 deletions(-) create mode 100644 pyscript.core/src/stdlib/pyweb/ui/__init__.py create mode 100644 pyscript.core/src/stdlib/pyweb/ui/elements.py create mode 100644 pyscript.core/test/ui/demo.py create mode 100644 pyscript.core/test/ui/examples.py create mode 100644 pyscript.core/test/ui/gallery.html create mode 100644 pyscript.core/test/ui/gallery.py create mode 100644 pyscript.core/test/ui/index.html create mode 100644 pyscript.core/test/ui/pyscript.toml create mode 100644 pyscript.core/tests/integration/test_pyweb.py diff --git a/pyscript.core/src/stdlib.js b/pyscript.core/src/stdlib.js index 45f2e162a9d..545a006e23e 100644 --- a/pyscript.core/src/stdlib.js +++ b/pyscript.core/src/stdlib.js @@ -37,7 +37,7 @@ const python = [ "_path = None", ]; -const ignore = new Ignore(python, "./pyweb"); +const ignore = new Ignore(python, "-"); const write = (base, literal) => { for (const [key, value] of entries(literal)) { diff --git a/pyscript.core/src/stdlib/pyscript/event_handling.py b/pyscript.core/src/stdlib/pyscript/event_handling.py index 23f930ce9f6..6c2339402eb 100644 --- a/pyscript.core/src/stdlib/pyscript/event_handling.py +++ b/pyscript.core/src/stdlib/pyscript/event_handling.py @@ -47,13 +47,14 @@ def wrapper(*args, **kwargs): wrapper = func except AttributeError: - # TODO: this is currently an quick hack to get micropython working but we need - # to actually properly replace inspect.signature with something else + # TODO: this is very ugly hack to get micropython working because inspect.signature + # doesn't exist, but we need to actually properly replace inspect.signature. + # It may be actually better to not try any magic for now and raise the error def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except TypeError as e: - if "takes 0 positional arguments" in str(e): + if "takes" in str(e) and "positional arguments" in str(e): return func() raise diff --git a/pyscript.core/src/stdlib/pyweb/__init__.py b/pyscript.core/src/stdlib/pyweb/__init__.py index 0a5b12ffe4c..80843cf2da0 100644 --- a/pyscript.core/src/stdlib/pyweb/__init__.py +++ b/pyscript.core/src/stdlib/pyweb/__init__.py @@ -1 +1,2 @@ +from .pydom import JSProperty from .pydom import dom as pydom diff --git a/pyscript.core/src/stdlib/pyweb/pydom.py b/pyscript.core/src/stdlib/pyweb/pydom.py index 0e7286743fd..0ba41b25260 100644 --- a/pyscript.core/src/stdlib/pyweb/pydom.py +++ b/pyscript.core/src/stdlib/pyweb/pydom.py @@ -1,3 +1,5 @@ +import inspect + try: from typing import Any except ImportError: @@ -34,6 +36,23 @@ def JsProxy(obj): alert = window.alert +class JSProperty: + """JS property descriptor that directly maps to the property with the same + name in the underlying JS component.""" + + def __init__(self, name: str, allow_nones: bool = False): + self.name = name + self.allow_nones = allow_nones + + def __get__(self, obj, objtype=None): + return getattr(obj._js, self.name) + + def __set__(self, obj, value): + if not self.allow_nones and value is None: + return + setattr(obj._js, self.name, value) + + class BaseElement: def __init__(self, js_element): self._js = js_element @@ -104,7 +123,7 @@ def append(self, child): # TODO: this is Pyodide specific for now!!!!!! # if we get passed a JSProxy Element directly we just map it to the # higher level Python element - if isinstance(child, JsProxy): + if inspect.isclass(JsProxy) and isinstance(child, JsProxy): return self.append(Element(child)) elif isinstance(child, Element): diff --git a/pyscript.core/src/stdlib/pyweb/ui/__init__.py b/pyscript.core/src/stdlib/pyweb/ui/__init__.py new file mode 100644 index 00000000000..a50ec40cefb --- /dev/null +++ b/pyscript.core/src/stdlib/pyweb/ui/__init__.py @@ -0,0 +1 @@ +from . import elements diff --git a/pyscript.core/src/stdlib/pyweb/ui/elements.py b/pyscript.core/src/stdlib/pyweb/ui/elements.py new file mode 100644 index 00000000000..540e8f59f33 --- /dev/null +++ b/pyscript.core/src/stdlib/pyweb/ui/elements.py @@ -0,0 +1,947 @@ +import inspect +import sys + +from pyscript import document, when, window +from pyweb import JSProperty, pydom + +#: A flag to show if MicroPython is the current Python interpreter. +is_micropython = "MicroPython" in sys.version + + +def getmembers_static(cls): + """Cross-interpreter implementation of inspect.getmembers_static.""" + + if is_micropython: # pragma: no cover + return [(name, getattr(cls, name)) for name, _ in inspect.getmembers(cls)] + + return inspect.getmembers_static(cls) + + +class ElementBase(pydom.Element): + tag = "div" + + # GLOBAL ATTRIBUTES + # These are attribute that all elements have (this list is a subset of the official one) + # We are trying to capture the most used ones + accesskey = JSProperty("accesskey") + autofocus = JSProperty("autofocus") + autocapitalize = JSProperty("autocapitalize") + className = JSProperty("className") + contenteditable = JSProperty("contenteditable") + draggable = JSProperty("draggable") + enterkeyhint = JSProperty("enterkeyhint") + hidden = JSProperty("hidden") + id = JSProperty("id") + lang = JSProperty("lang") + nonce = JSProperty("nonce") + part = JSProperty("part") + popover = JSProperty("popover") + slot = JSProperty("slot") + spellcheck = JSProperty("spellcheck") + tabindex = JSProperty("tabindex") + title = JSProperty("title") + translate = JSProperty("translate") + virtualkeyboardpolicy = JSProperty("virtualkeyboardpolicy") + + def __init__(self, style=None, **kwargs): + super().__init__(document.createElement(self.tag)) + + # set all the style properties provided in input + if isinstance(style, dict): + for key, value in style.items(): + self.style[key] = value + elif style is None: + pass + else: + raise ValueError( + f"Style should be a dictionary, received {style} (type {type(style)}) instead." + ) + + # IMPORTANT!!! This is used to auto-harvest all input arguments and set them as properties + self._init_properties(**kwargs) + + def _init_properties(self, **kwargs): + """Set all the properties (of type JSProperties) provided in input as properties + of the class instance. + + Args: + **kwargs: The properties to set + """ + # Look at all the properties of the class and see if they were provided in kwargs + for attr_name, attr in getmembers_static(self.__class__): + # For each one, actually check if it is a property of the class and set it + if isinstance(attr, JSProperty) and attr_name in kwargs: + try: + setattr(self, attr_name, kwargs[attr_name]) + except Exception as e: + print(f"Error setting {attr_name} to {kwargs[attr_name]}: {e}") + raise + + +class TextElementBase(ElementBase): + def __init__(self, content=None, style=None, **kwargs): + super().__init__(style=style, **kwargs) + + # If it's an element, append the element + if isinstance(content, pydom.Element): + self.append(content) + # If it's a list of elements + elif isinstance(content, list): + for item in content: + self.append(item) + # If the content wasn't set just ignore + elif content is None: + pass + else: + # Otherwise, set content as the html of the element + self.html = content + + +# IMPORTANT: For all HTML components defined below, we are not mapping all +# available attributes, just the global and the most common ones. +# If you need to access a specific attribute, you can always use the `_js.` +class a(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a""" + + tag = "a" + + download = JSProperty("download") + href = JSProperty("href") + referrerpolicy = JSProperty("referrerpolicy") + rel = JSProperty("rel") + target = JSProperty("target") + type = JSProperty("type") + + +class abbr(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/abbr""" + + tag = "abbr" + + +class address(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/address""" + + tag = "address" + + +class area(ElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area""" + + tag = "area" + + alt = JSProperty("alt") + coords = JSProperty("coords") + download = JSProperty("download") + href = JSProperty("href") + ping = JSProperty("ping") + referrerpolicy = JSProperty("referrerpolicy") + rel = JSProperty("rel") + shape = JSProperty("shape") + target = JSProperty("target") + + +class article(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article""" + + tag = "article" + + +class aside(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside""" + + tag = "aside" + + +class audio(ElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio""" + + tag = "audio" + + autoplay = JSProperty("autoplay") + controls = JSProperty("controls") + controlslist = JSProperty("controlslist") + crossorigin = JSProperty("crossorigin") + disableremoteplayback = JSProperty("disableremoteplayback") + loop = JSProperty("loop") + muted = JSProperty("muted") + preload = JSProperty("preload") + src = JSProperty("src") + + +class b(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/b""" + + tag = "b" + + +class blockquote(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote""" + + tag = "blockquote" + + cite = JSProperty("cite") + + +class br(ElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br""" + + tag = "br" + + +class button(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button""" + + tag = "button" + + autofocus = JSProperty("autofocus") + disabled = JSProperty("disabled") + form = JSProperty("form") + formaction = JSProperty("formaction") + formenctype = JSProperty("formenctype") + formmethod = JSProperty("formmethod") + formnovalidate = JSProperty("formnovalidate") + formtarget = JSProperty("formtarget") + name = JSProperty("name") + type = JSProperty("type") + value = JSProperty("value") + + +class canvas(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas""" + + tag = "canvas" + + height = JSProperty("height") + width = JSProperty("width") + + +class caption(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption""" + + tag = "caption" + + +class cite(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite""" + + tag = "cite" + + +class code(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code""" + + tag = "code" + + +class data(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/data""" + + tag = "data" + + value = JSProperty("value") + + +class datalist(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist""" + + tag = "datalist" + + +class dd(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd""" + + tag = "dd" + + +class del_(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del""" + + tag = "del" + + cite = JSProperty("cite") + datetime = JSProperty("datetime") + + +class details(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details""" + + tag = "details" + + open = JSProperty("open") + + +class dialog(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog""" + + tag = "dialog" + + open = JSProperty("open") + + +class div(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div""" + + tag = "div" + + +class dl(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl""" + + tag = "dl" + + value = JSProperty("value") + + +class dt(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt""" + + tag = "dt" + + +class em(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em""" + + tag = "em" + + +class embed(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed""" + + tag = "embed" + + height = JSProperty("height") + src = JSProperty("src") + type = JSProperty("type") + width = JSProperty("width") + + +class fieldset(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset""" + + tag = "fieldset" + + disabled = JSProperty("disabled") + form = JSProperty("form") + name = JSProperty("name") + + +class figcaption(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figcaption""" + + tag = "figcaption" + + +class figure(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure""" + + tag = "figure" + + +class footer(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer""" + + tag = "footer" + + +class form(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form""" + + tag = "form" + + accept_charset = JSProperty("accept-charset") + action = JSProperty("action") + autocapitalize = JSProperty("autocapitalize") + autocomplete = JSProperty("autocomplete") + enctype = JSProperty("enctype") + name = JSProperty("name") + method = JSProperty("method") + nonvalidate = JSProperty("nonvalidate") + rel = JSProperty("rel") + target = JSProperty("target") + + +class h1(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h1""" + + tag = "h1" + + +class h2(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h2""" + + tag = "h2" + + +class h3(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h3""" + + tag = "h3" + + +class h4(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h4""" + + tag = "h4" + + +class h5(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h5""" + + tag = "h5" + + +class h6(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h6""" + + tag = "h6" + + +class header(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header""" + + tag = "header" + + +class hgroup(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup""" + + tag = "hgroup" + + +class hr(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hr""" + + tag = "hr" + + +class i(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/i""" + + tag = "i" + + +class iframe(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe""" + + tag = "iframe" + + allow = JSProperty("allow") + allowfullscreen = JSProperty("allowfullscreen") + height = JSProperty("height") + loading = JSProperty("loading") + name = JSProperty("name") + referrerpolicy = JSProperty("referrerpolicy") + sandbox = JSProperty("sandbox") + src = JSProperty("src") + srcdoc = JSProperty("srcdoc") + width = JSProperty("width") + + +class img(ElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img""" + + tag = "img" + + alt = JSProperty("alt") + crossorigin = JSProperty("crossorigin") + decoding = JSProperty("decoding") + fetchpriority = JSProperty("fetchpriority") + height = JSProperty("height") + ismap = JSProperty("ismap") + loading = JSProperty("loading") + referrerpolicy = JSProperty("referrerpolicy") + sizes = JSProperty("sizes") + src = JSProperty("src") + width = JSProperty("width") + + +# NOTE: Input is a reserved keyword in Python, so we use input_ instead +class input_(ElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input""" + + tag = "input" + + accept = JSProperty("accept") + alt = JSProperty("alt") + autofocus = JSProperty("autofocus") + capture = JSProperty("capture") + checked = JSProperty("checked") + dirname = JSProperty("dirname") + disabled = JSProperty("disabled") + form = JSProperty("form") + formaction = JSProperty("formaction") + formenctype = JSProperty("formenctype") + formmethod = JSProperty("formmethod") + formnovalidate = JSProperty("formnovalidate") + formtarget = JSProperty("formtarget") + height = JSProperty("height") + list = JSProperty("list") + max = JSProperty("max") + maxlength = JSProperty("maxlength") + min = JSProperty("min") + minlength = JSProperty("minlength") + multiple = JSProperty("multiple") + name = JSProperty("name") + pattern = JSProperty("pattern") + placeholder = JSProperty("placeholder") + popovertarget = JSProperty("popovertarget") + popovertargetaction = JSProperty("popovertargetaction") + readonly = JSProperty("readonly") + required = JSProperty("required") + size = JSProperty("size") + src = JSProperty("src") + step = JSProperty("step") + type = JSProperty("type") + value = JSProperty("value") + width = JSProperty("width") + + +class ins(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins""" + + tag = "ins" + + cite = JSProperty("cite") + datetime = JSProperty("datetime") + + +class kbd(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/kbd""" + + tag = "kbd" + + +class label(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label""" + + tag = "label" + + for_ = JSProperty("for") + + +class legend(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend""" + + tag = "legend" + + +class li(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li""" + + tag = "li" + + value = JSProperty("value") + + +class link(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link""" + + tag = "link" + + as_ = JSProperty("as") + crossorigin = JSProperty("crossorigin") + disabled = JSProperty("disabled") + fetchpriority = JSProperty("fetchpriority") + href = JSProperty("href") + imagesizes = JSProperty("imagesizes") + imagesrcset = JSProperty("imagesrcset") + integrity = JSProperty("integrity") + media = JSProperty("media") + rel = JSProperty("rel") + referrerpolicy = JSProperty("referrerpolicy") + sizes = JSProperty("sizes") + title = JSProperty("title") + type = JSProperty("type") + + +class main(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main""" + + tag = "main" + + +class map_(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map""" + + tag = "map" + + name = JSProperty("name") + + +class mark(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark""" + + tag = "mark" + + +class menu(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menu""" + + tag = "menu" + + +class meter(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter""" + + tag = "meter" + + form = JSProperty("form") + high = JSProperty("high") + low = JSProperty("low") + max = JSProperty("max") + min = JSProperty("min") + optimum = JSProperty("optimum") + value = JSProperty("value") + + +class nav(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav""" + + tag = "nav" + + +class object_(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object""" + + tag = "object" + + data = JSProperty("data") + form = JSProperty("form") + height = JSProperty("height") + name = JSProperty("name") + type = JSProperty("type") + usemap = JSProperty("usemap") + width = JSProperty("width") + + +class ol(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol""" + + tag = "ol" + + reversed = JSProperty("reversed") + start = JSProperty("start") + type = JSProperty("type") + + +class optgroup(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup""" + + tag = "optgroup" + + disabled = JSProperty("disabled") + label = JSProperty("label") + + +class option(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option""" + + tag = "option" + + disabled = JSProperty("value") + label = JSProperty("label") + selected = JSProperty("selected") + value = JSProperty("value") + + +class output(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output""" + + tag = "output" + + for_ = JSProperty("for") + form = JSProperty("form") + name = JSProperty("name") + + +class p(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p""" + + tag = "p" + + +class picture(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture""" + + tag = "picture" + + +class pre(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre""" + + tag = "pre" + + +class progress(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress""" + + tag = "progress" + + max = JSProperty("max") + value = JSProperty("value") + + +class q(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q""" + + tag = "q" + + cite = JSProperty("cite") + + +class s(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s""" + + tag = "s" + + +class script(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script""" + + tag = "script" + + # Let's add async manually since it's a reserved keyword in Python + async_ = JSProperty("async") + blocking = JSProperty("blocking") + crossorigin = JSProperty("crossorigin") + defer = JSProperty("defer") + fetchpriority = JSProperty("fetchpriority") + integrity = JSProperty("integrity") + nomodule = JSProperty("nomodule") + nonce = JSProperty("nonce") + referrerpolicy = JSProperty("referrerpolicy") + src = JSProperty("src") + type = JSProperty("type") + + +class section(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section""" + + tag = "section" + + +class select(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select""" + + tag = "select" + + +class small(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small""" + + tag = "small" + + +class source(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source""" + + tag = "source" + + media = JSProperty("media") + sizes = JSProperty("sizes") + src = JSProperty("src") + srcset = JSProperty("srcset") + type = JSProperty("type") + + +class span(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span""" + + tag = "span" + + +class strong(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong""" + + tag = "strong" + + +class style(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style""" + + tag = "style" + + blocking = JSProperty("blocking") + media = JSProperty("media") + nonce = JSProperty("nonce") + title = JSProperty("title") + + +class sub(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub""" + + tag = "sub" + + +class summary(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary""" + + tag = "summary" + + +class sup(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup""" + + tag = "sup" + + +class table(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table""" + + tag = "table" + + +class tbody(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody""" + + tag = "tbody" + + +class td(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td""" + + tag = "td" + + colspan = JSProperty("colspan") + headers = JSProperty("headers") + rowspan = JSProperty("rowspan") + + +class template(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template""" + + tag = "template" + + shadowrootmode = JSProperty("shadowrootmode") + + +class textarea(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea""" + + tag = "textarea" + + autocapitalize = JSProperty("autocapitalize") + autocomplete = JSProperty("autocomplete") + autofocus = JSProperty("autofocus") + cols = JSProperty("cols") + dirname = JSProperty("dirname") + disabled = JSProperty("disabled") + form = JSProperty("form") + maxlength = JSProperty("maxlength") + minlength = JSProperty("minlength") + name = JSProperty("name") + placeholder = JSProperty("placeholder") + readonly = JSProperty("readonly") + required = JSProperty("required") + rows = JSProperty("rows") + spellcheck = JSProperty("spellcheck") + wrap = JSProperty("wrap") + + +class tfoot(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot""" + + tag = "tfoot" + + +class th(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th""" + + tag = "th" + + +class thead(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead""" + + tag = "thead" + + +class time(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time""" + + tag = "time" + + datetime = JSProperty("datetime") + + +class title(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title""" + + tag = "title" + + +class tr(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr""" + + tag = "tr" + + abbr = JSProperty("abbr") + colspan = JSProperty("colspan") + headers = JSProperty("headers") + rowspan = JSProperty("rowspan") + scope = JSProperty("scope") + + +class track(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track""" + + tag = "track" + + default = JSProperty("default") + kind = JSProperty("kind") + label = JSProperty("label") + src = JSProperty("src") + srclang = JSProperty("srclang") + + +class u(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/u""" + + tag = "u" + + +class ul(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul""" + + tag = "ul" + + +class var(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/var""" + + tag = "var" + + +class video(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video""" + + tag = "video" + + autoplay = JSProperty("autoplay") + controls = JSProperty("controls") + crossorigin = JSProperty("crossorigin") + disablepictureinpicture = JSProperty("disablepictureinpicture") + disableremoteplayback = JSProperty("disableremoteplayback") + height = JSProperty("height") + loop = JSProperty("loop") + muted = JSProperty("muted") + playsinline = JSProperty("playsinline") + poster = JSProperty("poster") + preload = JSProperty("preload") + src = JSProperty("src") + width = JSProperty("width") + + +# Custom Elements +class grid(TextElementBase): + tag = "div" + + def __init__(self, layout, content=None, gap=None, **kwargs): + super().__init__(content, **kwargs) + self.style["display"] = "grid" + self.style["grid-template-columns"] = layout + + # TODO: This should be a property + if not gap is None: + self.style["gap"] = gap diff --git a/pyscript.core/test/pydom.html b/pyscript.core/test/pydom.html index cc959de4871..90f97a23dbb 100644 --- a/pyscript.core/test/pydom.html +++ b/pyscript.core/test/pydom.html @@ -8,7 +8,7 @@ - + diff --git a/pyscript.core/test/pydom.py b/pyscript.core/test/pydom.py index ab8d0377c5b..2f134688c19 100644 --- a/pyscript.core/test/pydom.py +++ b/pyscript.core/test/pydom.py @@ -1,10 +1,13 @@ import random +import sys import time from datetime import datetime as dt from pyscript import display, when from pyweb import pydom +display(sys.version, target="system-info") + @when("click", "#just-a-button") def on_click(): diff --git a/pyscript.core/test/pydom_mp.html b/pyscript.core/test/pydom_mp.html index 770e00b9c90..ef1a883b7be 100644 --- a/pyscript.core/test/pydom_mp.html +++ b/pyscript.core/test/pydom_mp.html @@ -10,6 +10,8 @@ +

+ diff --git a/pyscript.core/test/ui/demo.py b/pyscript.core/test/ui/demo.py new file mode 100644 index 00000000000..2f1ea894ada --- /dev/null +++ b/pyscript.core/test/ui/demo.py @@ -0,0 +1,251 @@ +try: + from textwrap import dedent +except ImportError: + dedent = lambda x: x + +import examples +import shoelace +import styles +from markdown import markdown +from pyscript import when, window +from pyweb import pydom +from pyweb.ui import elements as el +from pyweb.ui.elements import a, button, div, grid, h1, h2, h3 + +MAIN_PAGE_MARKDOWN = dedent( + """ + ## What is pyweb.ui? + Pyweb UI is a totally immagnary exercise atm but..... imagine it is a Python library that allows you to create + web applications using Python only. + + It is based on base HTML/JS components but is extensible, for instance, it can have a [Shoelace](https://shoelace.style/) backend... + + PyWeb is a Python library that allows you to create web applications using Python only. + + ## What can I do with Pyweb.ui? + + You can create web applications using Python only. + """ +) + +# First thing we do is to load all the external resources we need +shoelace.load_resources() + + +# Let's define some convenience functions first +def create_component_details(component_label, component): + """Create a component details card. + + Args: + component (str): The name of the component to create. + + Returns: + the component created + + """ + # Get the example from the examples catalog + example = component["instance"] + details = ( + getattr(example, "__doc__", "") + or f"Details missing for component {component_label}" + ) + + return div( + [ + # Title and description (description is picked from the class docstring) + h1(component_label), + markdown(details), + # Example section + h2("Example:"), + create_component_example(component["instance"], component["code"]), + ], + style={"margin": "20px"}, + ) + + +def add_component_section(component_label, component, parent_div): + """Create a link to a component and add it to the left panel. + + Args: + component (str): The name of the component to add. + + Returns: + the component created + + """ + # Create the component link element + div_ = div( + a(component_label, href="#"), + style={"display": "block", "text-align": "center", "margin": "auto"}, + ) + + # Create a handler that opens the component details when the link is clicked + @when("click", div_) + def _change(): + new_main = create_component_details(component_label, component) + main_area.html = "" + main_area.append(new_main) + + # Add the new link element to the parent div (left panel) + parent_div.append(div_) + return div_ + + +def create_component_example(widget, code): + """Create a grid div with the widget on the left side and the relate code + on the right side. + + Args: + widget (ElementBase): The widget to add to the grid. + code (str): The code to add to the grid. + + Returns: + the grid created + + """ + # Create the grid that splits the window in two columns (25% and 75%) + grid_ = grid("29% 2% 74%") + + # Add the widget + grid_.append(div(widget, style=styles.STYLE_EXAMPLE_INSTANCE)) + + # Add the code div + widget_code = markdown(dedent(f"""```python\n{code}\n```""")) + grid_.append(shoelace.Divider(vertical=True)) + grid_.append(div(widget_code, style=styles.STYLE_CODE_BLOCK)) + + return grid_ + + +def create_main_area(): + """Create the main area of the right side of page, with the description of the + demo itself and how to use it. + + Returns: + the main area + + """ + div_ = div( + [ + h1("Welcome to PyWeb UI!", style={"text-align": "center"}), + markdown(MAIN_PAGE_MARKDOWN), + ] + ) + + main = el.main( + style={ + "padding-top": "4rem", + "padding-bottom": "7rem", + "max-width": "52rem", + "margin-left": "auto", + "margin-right": "auto", + "padding-left": "1.5rem", + "padding-right": "1.5rem", + "width": "100%", + } + ) + main.append(div_) + + return main + + +def create_basic_components_page(label, kit_name): + """Create the basic components page. + + Returns: + the main area + + """ + div_ = div(h2(label)) + + for component_label, component in examples.kits[kit_name].items(): + div_.append(h3(component_label)) + div_.append(create_component_example(component["instance"], component["code"])) + + return div_ + + +# ********** CREATE ALL THE LAYOUT ********** + +main_grid = grid("140px 20px auto", style={"min-height": "100%"}) + +# ********** MAIN PANEL ********** +main_area = create_main_area() + + +def write_to_main(content): + main_area.html = "" + main_area.append(content) + + +def restore_home(): + write_to_main(create_main_area()) + + +def basic_components(): + write_to_main( + create_basic_components_page(label="Basic Components", kit_name="elements") + ) + # Make sure we highlight the code + window.hljs.highlightAll() + + +def markdown_components(): + write_to_main(create_basic_components_page(label="", kit_name="markdown")) + + +def create_new_section(title, parent_div): + basic_components_text = h3( + title, style={"text-align": "left", "margin": "20px auto 0"} + ) + parent_div.append(basic_components_text) + parent_div.append( + shoelace.Divider(style={"margin-top": "5px", "margin-bottom": "30px"}) + ) + return basic_components_text + + +# ********** LEFT PANEL ********** +left_div = div() +left_panel_title = h1( + "PyWeb.UI", style={"text-align": "center", "margin": "20px auto 30px"} +) +left_div.append(left_panel_title) +left_div.append(shoelace.Divider(style={"margin-bottom": "30px"})) +# Let's map the creation of the main area to when the user clocks on "Components" +when("click", left_panel_title)(restore_home) + +# BASIC COMPONENTS +basic_components_text = h3( + "Basic Components", + style={"text-align": "left", "margin": "20px auto 0", "cursor": "pointer"}, +) +left_div.append(basic_components_text) +left_div.append(shoelace.Divider(style={"margin-top": "5px", "margin-bottom": "30px"})) +# Let's map the creation of the main area to when the user clocks on "Components" +when("click", basic_components_text)(basic_components) + +# MARKDOWN COMPONENTS +markdown_title = create_new_section("Markdown", left_div) +when("click", markdown_title)(markdown_components) + + +# SHOELACE COMPONENTS +shoe_components_text = h3( + "Shoe Components", style={"text-align": "left", "margin": "20px auto 0"} +) +left_div.append(shoe_components_text) +left_div.append(shoelace.Divider(style={"margin-top": "5px", "margin-bottom": "30px"})) + +# Create the links to the components on th left panel +print("SHOELACE EXAMPLES", examples.kits["shoelace"]) +for component_label, component in examples.kits["shoelace"].items(): + add_component_section(component_label, component, left_div) + +left_div.append(shoelace.Divider(style={"margin-top": "5px", "margin-bottom": "30px"})) +left_div.append(a("Gallery", href="gallery.html", style={"text-align": "left"})) +# ********** ADD LEFT AND MAIN PANEL TO MAIN ********** +main_grid.append(left_div) +main_grid.append(shoelace.Divider(vertical=True)) +main_grid.append(main_area) +pydom.body.append(main_grid) diff --git a/pyscript.core/test/ui/examples.py b/pyscript.core/test/ui/examples.py new file mode 100644 index 00000000000..48b06ebd268 --- /dev/null +++ b/pyscript.core/test/ui/examples.py @@ -0,0 +1,300 @@ +from markdown import markdown +from pyscript import when, window +from pyweb import pydom +from pyweb.ui.elements import ( + a, + br, + button, + code, + div, + grid, + h1, + h2, + h3, + h4, + h5, + h6, + img, + input_, + p, + small, + strong, +) +from shoelace import ( + Alert, + Button, + Card, + CopyButton, + Details, + Dialog, + Divider, + Icon, + Radio, + RadioGroup, + Range, + Rating, + RelativeTime, + Skeleton, + Spinner, + Switch, + Tag, + Textarea, +) + +LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." +details_code = """ +LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." +Details(LOREM_IPSUM, summary="Try me") +""" +example_dialog_close_btn = Button("Close") +example_dialog = Dialog(div([p(LOREM_IPSUM), example_dialog_close_btn]), label="Try me") +example_dialog_btn = Button("Open Dialog") + + +def toggle_dialog(): + example_dialog.open = not (example_dialog.open) + + +when("click", example_dialog_btn)(toggle_dialog) +when("click", example_dialog_close_btn)(toggle_dialog) + +pydom.body.append(example_dialog) + + +# ELEMENTS + +# Button +btn = button("Click me!") +when("click", btn)(lambda: window.alert("Clicked!")) + +# Inputs +inputs_div = div() +inputs_code = [] +for input_type in [ + "text", + "password", + "email", + "number", + "date", + "time", + "color", + "range", +]: + inputs_div.append(input_(type=input_type, style={"display": "block"})) + inputs_code.append(f"input_(type='{input_type}')") + + +headers_div = div() +headers_code = [] +for header in [h1, h2, h3, h4, h5, h6]: + headers_div.append(header(f"{header.tag.upper()} header")) + headers_code.append(f'{header.tag}("{header.tag.upper()} header")') +headers_code = "\n".join(headers_code) + +rich_input = input_( + type="text", + name="some name", + autofocus=True, + pattern="\w{3,16}", + placeholder="add text with > 3 chars", + required=True, + size="20", +) +inputs_div.append(rich_input) +inputs_code.append("# You can create inputs with more options like") +inputs_code.append("# this by passing properties as kwargs") +inputs_code.append( + "input_(type='text', name='some name', autofocus=True, pattern='\\w{3,16}', placeholder='add text with > 3 chars', required=True, size='20')" +) +inputs_code = "\n".join(inputs_code) + +MARKDOWN_EXAMPLE = """# This is a header + +This is a ~~paragraph~~ text with **bold** and *italic* text in it! +""" + +kits = { + "shoelace": { + "Alert": { + "instance": Alert( + "This is a standard alert. You can customize its content and even the icon." + ), + "code": "Alert('This is a standard alert. You can customize its content and even the icon.'", + }, + "Icon": { + "instance": Icon(name="heart"), + "code": 'Icon(name="heart")', + }, + "Button": { + "instance": Button("Try me"), + "code": 'Button("Try me")', + }, + "Card": { + "instance": Card( + p("This is a cool card!"), + image="https://pyscript.net/assets/images/pyscript-sticker-black.svg", + footer=div([Button("More Info"), Rating()]), + ), + "code": """ +Card(p("This is a cool card!"), image="https://pyscript.net/assets/images/pyscript-sticker-black.svg", footer=div([Button("More Info"), Rating()])) +""", + }, + "Details": { + "instance": Details(LOREM_IPSUM, summary="Try me"), + "code": 'Details(LOREM_IPSUM, summary="Try me")', + }, + "Dialog": { + "instance": example_dialog_btn, + "code": 'Dialog(div([p(LOREM_IPSUM), Button("Close")]), summary="Try me")', + }, + "Divider": { + "instance": Divider(), + "code": "Divider()", + }, + "Rating": { + "instance": Rating(), + "code": "Rating()", + }, + "Radio": { + "instance": Radio("Option 42"), + "code": code('Radio("Option 42")'), + }, + "Radio Group": { + "instance": RadioGroup( + [ + Radio("radio 1", name="radio 1", value=1, style={"margin": "20px"}), + Radio("radio 2", name="radio 2", value=2, style={"margin": "20px"}), + Radio("radio 3", name="radio 3", value=3, style={"margin": "20px"}), + ], + label="Select an option", + ), + "code": code( + """ + RadioGroup([Radio("radio 1", name="radio 1", value=1, style={"margin": "20px"}), + Radio("radio 2", name="radio 2", value=2, style={"margin": "20px"}), + Radio("radio 3", name="radio 3", value=3, style={"margin": "20px"})], + label="Select an option"),""" + ), + }, + "CopyButton": { + "instance": CopyButton( + value="PyShoes!", + copy_label="Copy me!", + sucess_label="Copied, check your clipboard!", + error_label="Oops, something went wrong!", + feedback_timeout=2000, + tooltip_placement="top", + ), + "code": 'CopyButton(value="PyShoes!", copy_label="Copy me!", sucess_label="Copied, check your clipboard!", error_label="Oops, something went wrong!", feedback_timeout=2000, tooltip_placement="top")', + }, + "Skeleton": { + "instance": Skeleton(effect="pulse"), + "code": "Skeleton(effect='pulse')", + }, + "Spinner": { + "instance": Spinner(), + "code": "Spinner()", + }, + "Switch": { + "instance": Switch(name="switch", size="large"), + "code": 'Switch(name="switch", size="large")', + }, + "Textarea": { + "instance": Textarea( + name="textarea", + label="Textarea", + size="medium", + help_text="This is a textarea", + resize="auto", + ), + "code": 'Textarea(name="textarea", label="Textarea", size="medium", help_text="This is a textarea", resize="auto")', + }, + "Tag": { + "instance": Tag("Tag", variant="primary", size="medium"), + "code": 'Tag("Tag", variant="primary", size="medium")', + }, + "Range": { + "instance": Range(min=0, max=100, value=50), + "code": "Range(min=0, max=100, value=50)", + }, + "RelativeTime": { + "instance": RelativeTime(date="2021-01-01T00:00:00Z"), + "code": 'RelativeTime(date="2021-01-01T00:00:00Z")', + }, + # "SplitPanel": { + # "instance": SplitPanel( + # div("First panel"), div("Second panel"), orientation="vertical" + # ), + # "code": code( + # 'SplitPanel(div("First panel"), div("Second panel"), orientation="vertical")' + # ), + # }, + }, + "elements": { + "button": { + "instance": btn, + "code": """btn = button("Click me!") +when('click', btn)(lambda: window.alert("Clicked!")) +parentdiv.append(btn) +""", + }, + "div": { + "instance": div( + "This is a div", + style={ + "text-align": "center", + "margin": "0 auto", + "background-color": "cornsilk", + }, + ), + "code": 'div("This is a div", style={"text-align": "center", "margin": "0 auto", "background-color": "cornsilk"})', + }, + "input": {"instance": inputs_div, "code": inputs_code}, + "grid": { + "instance": grid( + "30% 70%", + [ + div("This is a grid", style={"background-color": "lightblue"}), + p("with 2 elements", style={"background-color": "lightyellow"}), + ], + ), + "code": 'grid([div("This is a grid")])', + }, + "headers": {"instance": headers_div, "code": headers_code}, + "a": { + "instance": a( + "Click here for something awesome", + href="https://pyscript.net", + target="_blank", + ), + "code": 'a("Click here for something awesome", href="https://pyscript.net", target="_blank")', + }, + "br": { + "instance": div([p("This is a paragraph"), br(), p("with a line break")]), + "code": 'div([p("This is a paragraph"), br(), p("with a line break")])', + }, + "img": { + "instance": img(src="./giphy_winner.gif", style={"max-width": "200px"}), + "code": 'img(src="./giphy_winner.gif", style={"max-width": "200px"})', + }, + "code": { + "instance": code("print('Hello, World!')"), + "code": "code(\"print('Hello, World!')\")", + }, + "p": {"instance": p("This is a paragraph"), "code": 'p("This is a paragraph")'}, + "small": { + "instance": small("This is a small text"), + "code": 'small("This is a small text")', + }, + "strong": { + "instance": strong("This is a strong text"), + "code": 'strong("This is a strong text")', + }, + }, + "markdown": { + "markdown": { + "instance": markdown(MARKDOWN_EXAMPLE), + "code": f'markdown("""{MARKDOWN_EXAMPLE}""")', + }, + }, +} diff --git a/pyscript.core/test/ui/gallery.html b/pyscript.core/test/ui/gallery.html new file mode 100644 index 00000000000..7fd0614d204 --- /dev/null +++ b/pyscript.core/test/ui/gallery.html @@ -0,0 +1,31 @@ + + + + PyDom UI + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pyscript.core/test/ui/gallery.py b/pyscript.core/test/ui/gallery.py new file mode 100644 index 00000000000..32196ffcd7f --- /dev/null +++ b/pyscript.core/test/ui/gallery.py @@ -0,0 +1,180 @@ +try: + from textwrap import dedent +except ImportError: + dedent = lambda x: x + +import inspect + +import shoelace +import styles +import tictactoe +from markdown import markdown +from pyscript import when, window +from pyweb import pydom +from pyweb.ui import elements as el + +MAIN_PAGE_MARKDOWN = dedent( + """ + This gallery is a collection of demos using the PyWeb.UI library. There are meant + to be examples of how to use the library to create GUI applications using Python + only. + + ## How to use the gallery + + Simply click on the demo you want to see and the details will appear on the right + """ +) + +# First thing we do is to load all the external resources we need +shoelace.load_resources() + + +def add_demo(demo_name, demo_creator_cb, parent_div, source=None): + """Create a link to a component and add it to the left panel. + + Args: + component (str): The name of the component to add. + + Returns: + the component created + + """ + # Create the component link element + div = el.div(el.a(demo_name, href="#"), style=styles.STYLE_LEFT_PANEL_LINKS) + + # Create a handler that opens the component details when the link is clicked + @when("click", div) + def _change(): + if source: + demo_div = el.grid("50% 50%") + demo_div.append(demo_creator_cb()) + widget_code = markdown(dedent(f"""```python\n{source}\n```""")) + demo_div.append(el.div(widget_code, style=styles.STYLE_CODE_BLOCK)) + else: + demo_div = demo_creator_cb() + demo_div.style["margin"] = "20px" + write_to_main(demo_div) + window.hljs.highlightAll() + + # Add the new link element to the parent div (left panel) + parent_div.append(div) + return div + + +def create_main_area(): + """Create the main area of the right side of page, with the description of the + demo itself and how to use it. + + Returns: + the main area + + """ + return el.div( + [ + el.h1("PyWeb UI Gallery", style={"text-align": "center"}), + markdown(MAIN_PAGE_MARKDOWN), + ] + ) + + +def create_markdown_app(): + """Create the basic components page. + + Returns: + the main area + + """ + translate_button = shoelace.Button("Convert", variant="primary") + markdown_txt_area = shoelace.TextArea(label="Use this to write your Markdown") + result_div = el.div(style=styles.STYLE_MARKDOWN_RESULT) + + @when("click", translate_button) + def translate_markdown(): + result_div.html = markdown(markdown_txt_area.value).html + + return el.div( + [ + el.h2("Markdown"), + markdown_txt_area, + translate_button, + result_div, + ], + style={"margin": "20px"}, + ) + + +# ********** MAIN PANEL ********** +main_area = create_main_area() + + +def write_to_main(content): + main_area.html = "" + main_area.append(content) + + +def restore_home(): + write_to_main(create_main_area()) + + +def create_new_section(title, parent_div): + basic_components_text = el.h3( + title, style={"text-align": "left", "margin": "20px auto 0"} + ) + parent_div.append(basic_components_text) + parent_div.append( + shoelace.Divider(style={"margin-top": "5px", "margin-bottom": "30px"}) + ) + return basic_components_text + + +# ********** LEFT PANEL ********** +left_panel_title = el.h1("PyWeb.UI", style=styles.STYLE_LEFT_PANEL_TITLE) +left_div = el.div( + [ + left_panel_title, + shoelace.Divider(style={"margin-bottom": "30px"}), + el.h3("Demos", style=styles.STYLE_LEFT_PANEL_TITLE), + ] +) + +# Let's map the creation of the main area to when the user clocks on "Components" +when("click", left_panel_title)(restore_home) + +# ------ ADD DEMOS ------ +markdown_source = """ +translate_button = shoelace.Button("Convert", variant="primary") +markdown_txt_area = shoelace.TextArea(label="Markdown", + help_text="Write your Mardown here and press convert to see the result", +) +result_div = el.div(style=styles.STYLE_MARKDOWN_RESULT) +@when("click", translate_button) +def translate_markdown(): + result_div.html = markdown(markdown_txt_area.value).html + +el.div([ + el.h2("Markdown"), + markdown_txt_area, + translate_button, + result_div, +]) +""" +add_demo("Markdown", create_markdown_app, left_div, source=markdown_source) +add_demo( + "Tic Tac Toe", + tictactoe.create_tic_tac_toe, + left_div, + source=inspect.getsource(tictactoe), +) + +left_div.append(shoelace.Divider(style={"margin-top": "5px", "margin-bottom": "30px"})) +left_div.append(el.a("Examples", href="/test/ui/", style={"text-align": "left"})) + +# ********** CREATE ALL THE LAYOUT ********** +grid = el.grid("minmax(100px, 200px) 20px auto", style={"min-height": "100%"}) +grid.append(left_div) +grid.append(shoelace.Divider(vertical=True)) +grid.append(main_area) + +pydom.body.append(grid) +pydom.body.append(el.a("Back to the main page", href="/test/ui/", target="_blank")) +pydom.body.append(el.a("Hidden!!!", href="/test/ui/", target="_blank", hidden=True)) diff --git a/pyscript.core/test/ui/index.html b/pyscript.core/test/ui/index.html new file mode 100644 index 00000000000..05c6e54dcb8 --- /dev/null +++ b/pyscript.core/test/ui/index.html @@ -0,0 +1,39 @@ + + + + PyDom UI + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pyscript.core/test/ui/pyscript.toml b/pyscript.core/test/ui/pyscript.toml new file mode 100644 index 00000000000..8e699cea90a --- /dev/null +++ b/pyscript.core/test/ui/pyscript.toml @@ -0,0 +1,8 @@ +packages = [] + +[files] +"./examples.py" = "./examples.py" +"./tictactoe.py" = "./tictactoe.py" +"./styles.py" = "./styles.py" +"./shoelace.py" = "./shoelace.py" +"./markdown.py" = "./markdown.py" diff --git a/pyscript.core/tests/integration/test_00_support.py b/pyscript.core/tests/integration/test_00_support.py index f3500a65ee3..82bd09638d9 100644 --- a/pyscript.core/tests/integration/test_00_support.py +++ b/pyscript.core/tests/integration/test_00_support.py @@ -186,12 +186,12 @@ def test_check_js_errors_multiple(self): # msg = str(exc.value) expected = textwrap.dedent( - """ + f""" JS errors found: 2 Error: error 1 - at https://fake_server/mytest.html:.* + at {self.http_server_addr}/mytest.html:.* Error: error 2 - at https://fake_server/mytest.html:.* + at {self.http_server_addr}/mytest.html:.* """ ).strip() assert re.search(expected, msg) @@ -217,12 +217,12 @@ def test_check_js_errors_some_expected_but_others_not(self): # msg = str(exc.value) expected = textwrap.dedent( - """ + f""" JS errors found: 2 Error: NOT expected 2 - at https://fake_server/mytest.html:.* + at {self.http_server_addr}/mytest.html:.* Error: NOT expected 4 - at https://fake_server/mytest.html:.* + at {self.http_server_addr}/mytest.html:.* """ ).strip() assert re.search(expected, msg) @@ -243,15 +243,15 @@ def test_check_js_errors_expected_not_found_but_other_errors(self): # msg = str(exc.value) expected = textwrap.dedent( - """ + f""" The following JS errors were expected but could not be found: - this is not going to be found --- The following JS errors were raised but not expected: Error: error 1 - at https://fake_server/mytest.html:.* + at {self.http_server_addr}/mytest.html:.* Error: error 2 - at https://fake_server/mytest.html:.* + at {self.http_server_addr}/mytest.html:.* """ ).strip() assert re.search(expected, msg) @@ -471,6 +471,8 @@ def test_404(self): Test that we capture a 404 in loading a page that does not exist. """ self.goto("this_url_does_not_exist.html") - assert [ - "Failed to load resource: the server responded with a status of 404 (Not Found)" - ] == self.console.all.lines + if self.dev_server: + error = "Failed to load resource: the server responded with a status of 404 (File not found)" + else: + error = "Failed to load resource: the server responded with a status of 404 (Not Found)" + assert [error] == self.console.all.lines diff --git a/pyscript.core/tests/integration/test_pyweb.py b/pyscript.core/tests/integration/test_pyweb.py new file mode 100644 index 00000000000..d83424c8c00 --- /dev/null +++ b/pyscript.core/tests/integration/test_pyweb.py @@ -0,0 +1,605 @@ +import re + +import pytest + +from .support import PyScriptTest, only_main, skip_worker + +DEFAULT_ELEMENT_ATTRIBUTES = { + "accesskey": "s", + "autocapitalize": "off", + "autofocus": True, + "contenteditable": True, + "draggable": True, + "enterkeyhint": "go", + "hidden": False, + "id": "whateverid", + "lang": "br", + "nonce": "123", + "part": "part1:exposed1", + "popover": True, + "slot": "slot1", + "spellcheck": False, + "tabindex": 3, + "title": "whatevertitle", + "translate": "no", + "virtualkeyboardpolicy": "manual", +} + +INTERPRETERS = ["py", "mpy"] + + +@pytest.fixture(params=INTERPRETERS) +def interpreter(request): + return request.param + + +class TestElements(PyScriptTest): + """Test all elements in the pyweb.ui.elements module. + + This class tests all elements in the pyweb.ui.elements module. It creates + an element of each type, both executing in the main thread and in a worker. + It runs each test for each interpreter defined in `INTERPRETERS` + + Each individual element test looks for the element properties, sets a value + on each the supported properties and checks if the element was created correctly + and all it's properties were set correctly. + """ + + @property + def expected_missing_file_errors(self): + # In fake server conditions this test will not throw an error due to missing files. + # If we want to skip the test, use: + # pytest.skip("Skipping: fake server doesn't throw 404 errors on missing local files.") + return ( + [ + "Failed to load resource: the server responded with a status of 404 (File not found)" + ] + if self.dev_server + else [] + ) + + def _create_el_and_basic_asserts( + self, + el_type, + el_text=None, + interpreter="py", + properties=None, + expected_errors=None, + additional_selector_rules=None, + ): + """Create an element with all its properties set, by running + """ + self.pyscript_run(code_) + + # Let's keep the tag in 2 variables, one for the selector and another to + # check the return tag from the selector + locator_type = el_tag = el_type[:-1] if el_type.endswith("_") else el_type + if additional_selector_rules: + locator_type += f"{additional_selector_rules}" + + el = self.page.locator(locator_type) + tag = el.evaluate("node => node.tagName") + assert tag == el_tag.upper() + if el_text: + assert el.inner_html() == el_text + assert el.text_content() == el_text + + # if we expect specific errors, check that they are in the console + if expected_errors: + for error in expected_errors: + assert error in self.console.error.lines + else: + # if we don't expect errors, check that there are no errors + assert self.console.error.lines == [] + + if properties: + for k, v in properties.items(): + actual_val = el.evaluate(f"node => node.{k}") + assert actual_val == v + return el + + def test_a(self, interpreter): + a = self._create_el_and_basic_asserts("a", "click me", interpreter) + assert a.text_content() == "click me" + + def test_abbr(self, interpreter): + abbr = self._create_el_and_basic_asserts( + "abbr", "some text", interpreter=interpreter + ) + assert abbr.text_content() == "some text" + + def test_address(self, interpreter): + address = self._create_el_and_basic_asserts("address", "some text", interpreter) + assert address.text_content() == "some text" + + def test_area(self, interpreter): + properties = { + "shape": "poly", + "coords": "129,0,260,95,129,138", + "href": "https://developer.mozilla.org/docs/Web/HTTP", + "target": "_blank", + "alt": "HTTP", + } + # TODO: Check why click times out + self._create_el_and_basic_asserts( + "area", interpreter=interpreter, properties=properties + ) + + def test_article(self, interpreter): + self._create_el_and_basic_asserts("article", "some text", interpreter) + + def test_aside(self, interpreter): + self._create_el_and_basic_asserts("aside", "some text", interpreter) + + def test_audio(self, interpreter): + self._create_el_and_basic_asserts( + "audio", + interpreter=interpreter, + properties={"src": "http://localhost:8080/somefile.ogg", "controls": True}, + expected_errors=self.expected_missing_file_errors, + ) + + def test_b(self, interpreter): + self._create_el_and_basic_asserts("aside", "some text", interpreter) + + def test_blockquote(self, interpreter): + self._create_el_and_basic_asserts("blockquote", "some text", interpreter) + + def test_br(self, interpreter): + self._create_el_and_basic_asserts("br", interpreter=interpreter) + + def test_element_button(self, interpreter): + button = self._create_el_and_basic_asserts("button", "click me", interpreter) + assert button.inner_html() == "click me" + + def test_element_button_attributes(self, interpreter): + button = self._create_el_and_basic_asserts( + "button", "click me", interpreter, None + ) + assert button.inner_html() == "click me" + + def test_canvas(self, interpreter): + properties = { + "height": 100, + "width": 120, + } + # TODO: Check why click times out + self._create_el_and_basic_asserts( + "canvas", "alt text for canvas", interpreter, properties=properties + ) + + def test_caption(self, interpreter): + self._create_el_and_basic_asserts("caption", "some text", interpreter) + + def test_cite(self, interpreter): + self._create_el_and_basic_asserts("cite", "some text", interpreter) + + def test_code(self, interpreter): + self._create_el_and_basic_asserts("code", "import pyweb", interpreter) + + def test_data(self, interpreter): + self._create_el_and_basic_asserts( + "data", "some text", interpreter, properties={"value": "123"} + ) + + def test_datalist(self, interpreter): + self._create_el_and_basic_asserts("datalist", "some items", interpreter) + + def test_dd(self, interpreter): + self._create_el_and_basic_asserts("dd", "some text", interpreter) + + def test_del_(self, interpreter): + self._create_el_and_basic_asserts( + "del_", "some text", interpreter, properties={"cite": "http://example.com/"} + ) + + def test_details(self, interpreter): + self._create_el_and_basic_asserts( + "details", "some text", interpreter, properties={"open": True} + ) + + def test_dialog(self, interpreter): + self._create_el_and_basic_asserts( + "dialog", "some text", interpreter, properties={"open": True} + ) + + def test_div(self, interpreter): + div = self._create_el_and_basic_asserts("div", "click me", interpreter) + assert div.inner_html() == "click me" + + def test_dl(self, interpreter): + self._create_el_and_basic_asserts("dl", "some text", interpreter) + + def test_dt(self, interpreter): + self._create_el_and_basic_asserts("dt", "some text", interpreter) + + def test_em(self, interpreter): + self._create_el_and_basic_asserts("em", "some text", interpreter) + + def test_embed(self, interpreter): + # NOTE: Types actually matter and embed expects a string for height and width + # while other elements expect an int + + # TODO: It's important that we add typing soon to help with the user experience + properties = { + "src": "http://localhost:8080/somefile.ogg", + "type": "video/ogg", + "width": "250", + "height": "200", + } + self._create_el_and_basic_asserts( + "embed", + interpreter=interpreter, + properties=properties, + expected_errors=self.expected_missing_file_errors, + ) + + def test_fieldset(self, interpreter): + self._create_el_and_basic_asserts( + "fieldset", "some text", interpreter, properties={"name": "some name"} + ) + + def test_figcaption(self, interpreter): + self._create_el_and_basic_asserts("figcaption", "some text", interpreter) + + def test_figure(self, interpreter): + self._create_el_and_basic_asserts("figure", "some text", interpreter) + + def test_footer(self, interpreter): + self._create_el_and_basic_asserts("footer", "some text", interpreter) + + def test_form(self, interpreter): + properties = { + "action": "https://example.com/submit", + "method": "post", + "name": "some name", + "autocomplete": "on", + "rel": "external", + } + self._create_el_and_basic_asserts( + "form", "some text", interpreter, properties=properties + ) + + def test_h1(self, interpreter): + self._create_el_and_basic_asserts("h1", "some text", interpreter) + + def test_h2(self, interpreter): + self._create_el_and_basic_asserts("h2", "some text", interpreter) + + def test_h3(self, interpreter): + self._create_el_and_basic_asserts("h3", "some text", interpreter) + + def test_h4(self, interpreter): + self._create_el_and_basic_asserts("h4", "some text", interpreter) + + def test_h5(self, interpreter): + self._create_el_and_basic_asserts("h5", "some text", interpreter) + + def test_h6(self, interpreter): + self._create_el_and_basic_asserts("h6", "some text", interpreter) + + def test_header(self, interpreter): + self._create_el_and_basic_asserts("header", "some text", interpreter) + + def test_hgroup(self, interpreter): + self._create_el_and_basic_asserts("hgroup", "some text", interpreter) + + def test_hr(self, interpreter): + self._create_el_and_basic_asserts("hr", interpreter=interpreter) + + def test_i(self, interpreter): + self._create_el_and_basic_asserts("i", "some text", interpreter) + + def test_iframe(self, interpreter): + # TODO: same comment about defining the right types + properties = { + "src": "http://localhost:8080/somefile.html", + "width": "250", + "height": "200", + } + self._create_el_and_basic_asserts( + "iframe", + interpreter, + properties=properties, + expected_errors=self.expected_missing_file_errors, + ) + + def test_img(self, interpreter): + properties = { + "src": "http://localhost:8080/somefile.png", + "alt": "some image", + "width": 250, + "height": 200, + } + self._create_el_and_basic_asserts( + "img", + interpreter=interpreter, + properties=properties, + expected_errors=self.expected_missing_file_errors, + ) + + def test_input(self, interpreter): + # TODO: we need multiple input tests + properties = { + "type": "text", + "value": "some value", + "name": "some name", + "autofocus": True, + "pattern": "[A-Za-z]{3}", + "placeholder": "some placeholder", + "required": True, + "size": 20, + } + self._create_el_and_basic_asserts( + "input_", interpreter=interpreter, properties=properties + ) + + def test_ins(self, interpreter): + self._create_el_and_basic_asserts( + "ins", "some text", interpreter, properties={"cite": "http://example.com/"} + ) + + def test_kbd(self, interpreter): + self._create_el_and_basic_asserts("kbd", "some text", interpreter) + + def test_label(self, interpreter): + self._create_el_and_basic_asserts("label", "some text", interpreter) + + def test_legend(self, interpreter): + self._create_el_and_basic_asserts("legend", "some text", interpreter) + + def test_li(self, interpreter): + self._create_el_and_basic_asserts("li", "some text", interpreter) + + def test_link(self, interpreter): + properties = { + "href": "http://localhost:8080/somefile.css", + "rel": "stylesheet", + "type": "text/css", + } + self._create_el_and_basic_asserts( + "link", + interpreter=interpreter, + properties=properties, + expected_errors=self.expected_missing_file_errors, + additional_selector_rules="[href='http://localhost:8080/somefile.css']", + ) + + def test_main(self, interpreter): + self._create_el_and_basic_asserts("main", "some text", interpreter) + + def test_map(self, interpreter): + self._create_el_and_basic_asserts( + "map_", "some text", interpreter, properties={"name": "somemap"} + ) + + def test_mark(self, interpreter): + self._create_el_and_basic_asserts("mark", "some text", interpreter) + + def test_menu(self, interpreter): + self._create_el_and_basic_asserts("menu", "some text", interpreter) + + def test_meter(self, interpreter): + properties = { + "value": 50, + "min": 0, + "max": 100, + "low": 30, + "high": 80, + "optimum": 50, + } + self._create_el_and_basic_asserts( + "meter", "some text", interpreter, properties=properties + ) + + def test_nav(self, interpreter): + self._create_el_and_basic_asserts("nav", "some text", interpreter) + + def test_object(self, interpreter): + properties = { + "data": "http://localhost:8080/somefile.swf", + "type": "application/x-shockwave-flash", + "width": "250", + "height": "200", + } + self._create_el_and_basic_asserts( + "object_", + interpreter=interpreter, + properties=properties, + ) + + def test_ol(self, interpreter): + self._create_el_and_basic_asserts("ol", "some text", interpreter) + + def test_optgroup(self, interpreter): + self._create_el_and_basic_asserts( + "optgroup", "some text", interpreter, properties={"label": "some label"} + ) + + def test_option(self, interpreter): + self._create_el_and_basic_asserts( + "option", "some text", interpreter, properties={"value": "some value"} + ) + + def test_output(self, interpreter): + self._create_el_and_basic_asserts("output", "some text", interpreter) + + def test_p(self, interpreter): + self._create_el_and_basic_asserts("p", "some text", interpreter) + + def test_picture(self, interpreter): + self._create_el_and_basic_asserts("picture", "some text", interpreter) + + def test_pre(self, interpreter): + self._create_el_and_basic_asserts("pre", "some text", interpreter) + + def test_progress(self, interpreter): + properties = { + "value": 50, + "max": 100, + } + self._create_el_and_basic_asserts( + "progress", "some text", interpreter, properties=properties + ) + + def test_q(self, interpreter): + self._create_el_and_basic_asserts( + "q", "some text", interpreter, properties={"cite": "http://example.com/"} + ) + + def test_s(self, interpreter): + self._create_el_and_basic_asserts("s", "some text", interpreter) + + # def test_script(self): + # self._create_el_and_basic_asserts("script", "some text") + + def test_section(self, interpreter): + self._create_el_and_basic_asserts("section", "some text", interpreter) + + def test_select(self, interpreter): + self._create_el_and_basic_asserts("select", "some text", interpreter) + + def test_small(self, interpreter): + self._create_el_and_basic_asserts("small", "some text", interpreter) + + def test_source(self, interpreter): + properties = { + "src": "http://localhost:8080/somefile.ogg", + "type": "audio/ogg", + } + self._create_el_and_basic_asserts( + "source", + interpreter=interpreter, + properties=properties, + ) + + def test_span(self, interpreter): + self._create_el_and_basic_asserts("span", "some text", interpreter) + + def test_strong(self, interpreter): + self._create_el_and_basic_asserts("strong", "some text", interpreter) + + def test_style(self, interpreter): + self._create_el_and_basic_asserts( + "style", + "body {background-color: red;}", + interpreter, + ) + + def test_sub(self, interpreter): + self._create_el_and_basic_asserts("sub", "some text", interpreter) + + def test_summary(self, interpreter): + self._create_el_and_basic_asserts("summary", "some text", interpreter) + + def test_sup(self, interpreter): + self._create_el_and_basic_asserts("sup", "some text", interpreter) + + def test_table(self, interpreter): + self._create_el_and_basic_asserts("table", "some text", interpreter) + + def test_tbody(self, interpreter): + self._create_el_and_basic_asserts("tbody", "some text", interpreter) + + def test_td(self, interpreter): + self._create_el_and_basic_asserts("td", "some text", interpreter) + + def test_template(self, interpreter): + # We are not checking the content of template since it's sort of + # special element + self._create_el_and_basic_asserts("template", interpreter=interpreter) + + def test_textarea(self, interpreter): + self._create_el_and_basic_asserts("textarea", "some text", interpreter) + + def test_tfoot(self, interpreter): + self._create_el_and_basic_asserts("tfoot", "some text", interpreter) + + def test_th(self, interpreter): + self._create_el_and_basic_asserts("th", "some text", interpreter) + + def test_thead(self, interpreter): + self._create_el_and_basic_asserts("thead", "some text", interpreter) + + def test_time(self, interpreter): + self._create_el_and_basic_asserts("time", "some text", interpreter) + + def test_title(self, interpreter): + self._create_el_and_basic_asserts("title", "some text", interpreter) + + def test_tr(self, interpreter): + self._create_el_and_basic_asserts("tr", "some text", interpreter) + + def test_track(self, interpreter): + properties = { + "src": "http://localhost:8080/somefile.vtt", + "kind": "subtitles", + "srclang": "en", + "label": "English", + } + self._create_el_and_basic_asserts( + "track", + interpreter=interpreter, + properties=properties, + ) + + def test_u(self, interpreter): + self._create_el_and_basic_asserts("u", "some text", interpreter) + + def test_ul(self, interpreter): + self._create_el_and_basic_asserts("ul", "some text", interpreter) + + def test_var(self, interpreter): + self._create_el_and_basic_asserts("var", "some text", interpreter) + + def test_video(self, interpreter): + properties = { + "src": "http://localhost:8080/somefile.ogg", + "controls": True, + "width": 250, + "height": 200, + } + self._create_el_and_basic_asserts( + "video", + interpreter=interpreter, + properties=properties, + expected_errors=self.expected_missing_file_errors, + ) diff --git a/pyscript.core/types/stdlib/pyscript.d.ts b/pyscript.core/types/stdlib/pyscript.d.ts index 0a9893a6f13..78a6035533d 100644 --- a/pyscript.core/types/stdlib/pyscript.d.ts +++ b/pyscript.core/types/stdlib/pyscript.d.ts @@ -13,6 +13,10 @@ declare namespace _default { "__init__.py": string; "media.py": string; "pydom.py": string; + ui: { + "__init__.py": string; + "elements.py": string; + }; }; } export default _default; From f1a787e031cc0192281f5b808ee501116abc49ad Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Thu, 6 Jun 2024 09:42:14 -0400 Subject: [PATCH 063/179] move pydom and elements from pyweb to pyscript.web (#2092) * change pydom example to use new pyscript.web namespace * change tests to use new pyscript.web namespace * create new pyscript.web package and move pydom to pyscript.web.dom * add __init__ to pyscript.web and expose the dom instance instead of the pyscript.web.dom module * move elements from pyweb.ui to pyscript.web and temp fix pydom import * moved of elements file completed * moved media from pyweb to pyscript.web * RIP pyweb * move JSProperty from pyscript.web.dom to pyscript.web.elements * move element classes from pyscript.web.dom to pyscript.web.elements * first round of fixes while running tests * fix test typo * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * restore right type type returned for Element.parent. ALL TESTS PASS LOCALLY NOW * lint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * clean up dom.py from dead commented code and osbolete comments * bugfix: dom shouldn't return None when it can't find any element for a specific selector so it now returns an empty collection * additional cleanup in tests * lint --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../src/stdlib/pyscript/event_handling.py | 9 +- .../src/stdlib/pyscript/web/__init__.py | 5 + pyscript.core/src/stdlib/pyscript/web/dom.py | 21 + .../{pyweb/ui => pyscript/web}/elements.py | 545 ++++++++++++++++- .../stdlib/{pyweb => pyscript/web}/media.py | 0 pyscript.core/src/stdlib/pyweb/__init__.py | 2 - pyscript.core/src/stdlib/pyweb/pydom.py | 569 ------------------ pyscript.core/src/stdlib/pyweb/ui/__init__.py | 1 - pyscript.core/test/pydom.html | 2 + pyscript.core/test/pydom.py | 11 +- .../test/pyscript_dom/tests/test_dom.py | 119 ++-- pyscript.core/tests/integration/test_pyweb.py | 7 +- pyscript.core/types/stdlib/pyscript.d.ts | 12 +- 13 files changed, 642 insertions(+), 661 deletions(-) create mode 100644 pyscript.core/src/stdlib/pyscript/web/__init__.py create mode 100644 pyscript.core/src/stdlib/pyscript/web/dom.py rename pyscript.core/src/stdlib/{pyweb/ui => pyscript/web}/elements.py (59%) rename pyscript.core/src/stdlib/{pyweb => pyscript/web}/media.py (100%) delete mode 100644 pyscript.core/src/stdlib/pyweb/__init__.py delete mode 100644 pyscript.core/src/stdlib/pyweb/pydom.py delete mode 100644 pyscript.core/src/stdlib/pyweb/ui/__init__.py diff --git a/pyscript.core/src/stdlib/pyscript/event_handling.py b/pyscript.core/src/stdlib/pyscript/event_handling.py index 6c2339402eb..5e4438c671e 100644 --- a/pyscript.core/src/stdlib/pyscript/event_handling.py +++ b/pyscript.core/src/stdlib/pyscript/event_handling.py @@ -19,16 +19,17 @@ def when(event_type=None, selector=None): """ def decorator(func): + + from pyscript.web.elements import Element, ElementCollection + if isinstance(selector, str): elements = document.querySelectorAll(selector) else: # TODO: This is a hack that will be removed when pyscript becomes a package # and we can better manage the imports without circular dependencies - from pyweb import pydom - - if isinstance(selector, pydom.Element): + if isinstance(selector, Element): elements = [selector._js] - elif isinstance(selector, pydom.ElementCollection): + elif isinstance(selector, ElementCollection): elements = [el._js for el in selector] else: raise ValueError( diff --git a/pyscript.core/src/stdlib/pyscript/web/__init__.py b/pyscript.core/src/stdlib/pyscript/web/__init__.py new file mode 100644 index 00000000000..2aa24957172 --- /dev/null +++ b/pyscript.core/src/stdlib/pyscript/web/__init__.py @@ -0,0 +1,5 @@ +from . import elements + +# Ugly trick to hide the dom module in the web package since we want the module +# to allow querying right away. +from .dom import dom diff --git a/pyscript.core/src/stdlib/pyscript/web/dom.py b/pyscript.core/src/stdlib/pyscript/web/dom.py new file mode 100644 index 00000000000..95d3398ad93 --- /dev/null +++ b/pyscript.core/src/stdlib/pyscript/web/dom.py @@ -0,0 +1,21 @@ +from pyscript import document +from pyscript.web.elements import Element, ElementCollection + + +class PyDom: + # Add objects we want to expose to the DOM namespace since this class instance is being + # remapped as "the module" itself + ElementCollection = ElementCollection + + def __init__(self): + self._js = document + + self.body = Element(document.body) + self.head = Element(document.head) + + def __getitem__(self, key): + elements = self._js.querySelectorAll(key) + return ElementCollection([Element(el) for el in elements]) + + +dom = PyDom() diff --git a/pyscript.core/src/stdlib/pyweb/ui/elements.py b/pyscript.core/src/stdlib/pyscript/web/elements.py similarity index 59% rename from pyscript.core/src/stdlib/pyweb/ui/elements.py rename to pyscript.core/src/stdlib/pyscript/web/elements.py index 540e8f59f33..cc4b2bbf995 100644 --- a/pyscript.core/src/stdlib/pyweb/ui/elements.py +++ b/pyscript.core/src/stdlib/pyscript/web/elements.py @@ -1,8 +1,40 @@ import inspect import sys -from pyscript import document, when, window -from pyweb import JSProperty, pydom +try: + from typing import Any +except ImportError: + Any = "Any" + +try: + import warnings +except ImportError: + # TODO: For now it probably means we are in MicroPython. We should figure + # out the "right" way to handle this. For now we just ignore the warning + # and logging to console + class warnings: + @staticmethod + def warn(*args, **kwargs): + print("WARNING: ", *args, **kwargs) + + +try: + from functools import cached_property +except ImportError: + # TODO: same comment about micropython as above + cached_property = property + +try: + from pyodide.ffi import JsProxy +except ImportError: + # TODO: same comment about micropython as above + def JsProxy(obj): + return obj + + +from pyscript import document, window + +# from pyscript.web import dom as pydom #: A flag to show if MicroPython is the current Python interpreter. is_micropython = "MicroPython" in sys.version @@ -17,7 +49,428 @@ def getmembers_static(cls): return inspect.getmembers_static(cls) -class ElementBase(pydom.Element): +class JSProperty: + """JS property descriptor that directly maps to the property with the same + name in the underlying JS component.""" + + def __init__(self, name: str, allow_nones: bool = False): + self.name = name + self.allow_nones = allow_nones + + def __get__(self, obj, objtype=None): + return getattr(obj._js, self.name) + + def __set__(self, obj, value): + if not self.allow_nones and value is None: + return + setattr(obj._js, self.name, value) + + +# ------ TODO: REMOVE!!!! pydom elements + + +class BaseElement: + def __init__(self, js_element): + self._js = js_element + self._parent = None + self.style = StyleProxy(self) + self._proxies = {} + + def __eq__(self, obj): + """Check if the element is the same as the other element by comparing + the underlying JS element""" + return isinstance(obj, BaseElement) and obj._js == self._js + + @property + def parent(self): + if self._parent: + return self._parent + + if self._js.parentElement: + # TODO: This should actually return the correct class (== to tagName) + self._parent = Element(self._js.parentElement) + + return self._parent + + # @property + # def __class(self): + # return self.__class__ if self.__class__ != PyDom else Element + + def create(self, type_, is_child=True, classes=None, html=None, label=None): + js_el = document.createElement(type_) + element = self.__class(js_el) + + if classes: + for class_ in classes: + element.add_class(class_) + + if html is not None: + element.html = html + + if label is not None: + element.label = label + + if is_child: + self.append(element) + + return element + + def find(self, selector): + """Return an ElementCollection representing all the child elements that + match the specified selector. + + Args: + selector (str): A string containing a selector expression + + Returns: + ElementCollection: A collection of elements matching the selector + """ + elements = self._js.querySelectorAll(selector) + if not elements: + return None + return ElementCollection([Element(el) for el in elements]) + + +class Element(BaseElement): + @property + def children(self): + return [self.__class__(el) for el in self._js.children] + + def append(self, child): + # TODO: this is Pyodide specific for now!!!!!! + # if we get passed a JSProxy Element directly we just map it to the + # higher level Python element + if inspect.isclass(JsProxy) and isinstance(child, JsProxy): + return self.append(Element(child)) + + elif isinstance(child, Element): + self._js.appendChild(child._js) + + return child + + elif isinstance(child, ElementCollection): + for el in child: + self.append(el) + + # -------- Pythonic Interface to Element -------- # + @property + def html(self): + return self._js.innerHTML + + @html.setter + def html(self, value): + self._js.innerHTML = value + + @property + def text(self): + return self._js.textContent + + @text.setter + def text(self, value): + self._js.textContent = value + + @property + def content(self): + # TODO: This breaks with with standard template elements. Define how to best + # handle this specifica use case. Just not support for now? + if self._js.tagName == "TEMPLATE": + warnings.warn( + "Content attribute not supported for template elements.", stacklevel=2 + ) + return None + return self._js.innerHTML + + @content.setter + def content(self, value): + # TODO: (same comment as above) + if self._js.tagName == "TEMPLATE": + warnings.warn( + "Content attribute not supported for template elements.", stacklevel=2 + ) + return + + display(value, target=self.id) + + @property + def id(self): + return self._js.id + + @id.setter + def id(self, value): + self._js.id = value + + @property + def options(self): + if "options" in self._proxies: + return self._proxies["options"] + + if not self._js.tagName.lower() in {"select", "datalist", "optgroup"}: + raise AttributeError( + f"Element {self._js.tagName} has no options attribute." + ) + self._proxies["options"] = OptionsProxy(self) + return self._proxies["options"] + + @property + def value(self): + return self._js.value + + @value.setter + def value(self, value): + # in order to avoid confusion to the user, we don't allow setting the + # value of elements that don't have a value attribute + if not hasattr(self._js, "value"): + raise AttributeError( + f"Element {self._js.tagName} has no value attribute. If you want to " + "force a value attribute, set it directly using the `_js.value = ` " + "javascript API attribute instead." + ) + self._js.value = value + + @property + def selected(self): + return self._js.selected + + @selected.setter + def selected(self, value): + # in order to avoid confusion to the user, we don't allow setting the + # value of elements that don't have a value attribute + if not hasattr(self._js, "selected"): + raise AttributeError( + f"Element {self._js.tagName} has no value attribute. If you want to " + "force a value attribute, set it directly using the `_js.value = ` " + "javascript API attribute instead." + ) + self._js.selected = value + + def clone(self, new_id=None): + clone = Element(self._js.cloneNode(True)) + clone.id = new_id + + return clone + + def remove_class(self, classname): + classList = self._js.classList + if isinstance(classname, list): + classList.remove(*classname) + else: + classList.remove(classname) + return self + + def add_class(self, classname): + classList = self._js.classList + if isinstance(classname, list): + classList.add(*classname) + else: + self._js.classList.add(classname) + return self + + @property + def classes(self): + classes = self._js.classList.values() + return [x for x in classes] + + def show_me(self): + self._js.scrollIntoView() + + def snap( + self, + to: BaseElement | str = None, + width: int | None = None, + height: int | None = None, + ): + """ + Captures a snapshot of a video element. (Only available for video elements) + + Inputs: + + * to: element where to save the snapshot of the video frame to + * width: width of the image + * height: height of the image + + Output: + (Element) canvas element where the video frame snapshot was drawn into + """ + if self._js.tagName != "VIDEO": + raise AttributeError("Snap method is only available for video Elements") + + if to is None: + canvas = self.create("canvas") + if width is None: + width = self._js.width + if height is None: + height = self._js.height + canvas._js.width = width + canvas._js.height = height + + elif isinstance(to, Element): + if to._js.tagName != "CANVAS": + raise TypeError("Element to snap to must a canvas.") + canvas = to + elif getattr(to, "tagName", "") == "CANVAS": + canvas = Element(to) + elif isinstance(to, str): + # TODO (fpliger): This needs a better fix but doing a local import here for a quick fix + from pyscript.web import dom + + canvas = dom[to][0] + if canvas._js.tagName != "CANVAS": + raise TypeError("Element to snap to must a be canvas.") + + canvas.draw(self, width, height) + + return canvas + + def download(self, filename: str = "snapped.png") -> None: + """Download the current element (only available for canvas elements) with the filename + provided in input. + + Inputs: + * filename (str): name of the file being downloaded + + Output: + None + """ + if self._js.tagName != "CANVAS": + raise AttributeError( + "The download method is only available for canvas Elements" + ) + + link = self.create("a") + link._js.download = filename + link._js.href = self._js.toDataURL() + link._js.click() + + def draw(self, what, width, height): + """Draw `what` on the current element (only available for canvas elements). + + Inputs: + + * what (canvas image source): An element to draw into the context. The specification permits any canvas + image source, specifically, an HTMLImageElement, an SVGImageElement, an HTMLVideoElement, + an HTMLCanvasElement, an ImageBitmap, an OffscreenCanvas, or a VideoFrame. + """ + if self._js.tagName != "CANVAS": + raise AttributeError( + "The draw method is only available for canvas Elements" + ) + + if isinstance(what, Element): + what = what._js + + # https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage + self._js.getContext("2d").drawImage(what, 0, 0, width, height) + + +class OptionsProxy: + """This class represents the options of a select element. It + allows to access to add and remove options by using the `add` and `remove` methods. + """ + + def __init__(self, element: Element) -> None: + self._element = element + if self._element._js.tagName.lower() != "select": + raise AttributeError( + f"Element {self._element._js.tagName} has no options attribute." + ) + + def add( + self, + value: Any = None, + html: str = None, + text: str = None, + before: Element | int = None, + **kws, + ) -> None: + """Add a new option to the select element""" + # create the option element and set the attributes + option = document.createElement("option") + if value is not None: + kws["value"] = value + if html is not None: + option.innerHTML = html + if text is not None: + kws["text"] = text + + for key, value in kws.items(): + option.setAttribute(key, value) + + if before: + if isinstance(before, Element): + before = before._js + + self._element._js.add(option, before) + + def remove(self, item: int) -> None: + """Remove the option at the specified index""" + self._element._js.remove(item) + + def clear(self) -> None: + """Remove all the options""" + for i in range(len(self)): + self.remove(0) + + @property + def options(self): + """Return the list of options""" + return [Element(opt) for opt in self._element._js.options] + + @property + def selected(self): + """Return the selected option""" + return self.options[self._element._js.selectedIndex] + + def __iter__(self): + yield from self.options + + def __len__(self): + return len(self.options) + + def __repr__(self): + return f"{self.__class__.__name__} (length: {len(self)}) {self.options}" + + def __getitem__(self, key): + return self.options[key] + + +class StyleProxy: # (dict): + def __init__(self, element: Element) -> None: + self._element = element + + @cached_property + def _style(self): + return self._element._js.style + + def __getitem__(self, key): + return self._style.getPropertyValue(key) + + def __setitem__(self, key, value): + self._style.setProperty(key, value) + + def remove(self, key): + self._style.removeProperty(key) + + def set(self, **kws): + for k, v in kws.items(): + self._element._js.style.setProperty(k, v) + + # CSS Properties + # Reference: https://github.com/microsoft/TypeScript/blob/main/src/lib/dom.generated.d.ts#L3799C1-L5005C2 + # Following prperties automatically generated from the above reference using + # tools/codegen_css_proxy.py + @property + def visible(self): + return self._element._js.style.visibility + + @visible.setter + def visible(self, value): + self._element._js.style.visibility = value + + +# --------- END OF PYDOM STUFF ------ + + +class ElementBase(Element): tag = "div" # GLOBAL ATTRIBUTES @@ -83,7 +536,7 @@ def __init__(self, content=None, style=None, **kwargs): super().__init__(style=style, **kwargs) # If it's an element, append the element - if isinstance(content, pydom.Element): + if isinstance(content, Element): self.append(content) # If it's a list of elements elif isinstance(content, list): @@ -945,3 +1398,87 @@ def __init__(self, layout, content=None, gap=None, **kwargs): # TODO: This should be a property if not gap is None: self.style["gap"] = gap + + +class StyleCollection: + def __init__(self, collection: "ElementCollection") -> None: + self._collection = collection + + def __get__(self, obj, objtype=None): + return obj._get_attribute("style") + + def __getitem__(self, key): + return self._collection._get_attribute("style")[key] + + def __setitem__(self, key, value): + for element in self._collection._elements: + element.style[key] = value + + def remove(self, key): + for element in self._collection._elements: + element.style.remove(key) + + +class ElementCollection: + def __init__(self, elements: [Element]) -> None: + self._elements = elements + self.style = StyleCollection(self) + + def __getitem__(self, key): + # If it's an integer we use it to access the elements in the collection + if isinstance(key, int): + return self._elements[key] + # If it's a slice we use it to support slice operations over the elements + # in the collection + elif isinstance(key, slice): + return ElementCollection(self._elements[key]) + + # If it's anything else (basically a string) we use it as a selector + # TODO: Write tests! + elements = self._element.querySelectorAll(key) + return ElementCollection([Element(el) for el in elements]) + + def __len__(self): + return len(self._elements) + + def __eq__(self, obj): + """Check if the element is the same as the other element by comparing + the underlying JS element""" + return isinstance(obj, ElementCollection) and obj._elements == self._elements + + def _get_attribute(self, attr, index=None): + if index is None: + return [getattr(el, attr) for el in self._elements] + + # As JQuery, when getting an attr, only return it for the first element + return getattr(self._elements[index], attr) + + def _set_attribute(self, attr, value): + for el in self._elements: + setattr(el, attr, value) + + @property + def html(self): + return self._get_attribute("html") + + @html.setter + def html(self, value): + self._set_attribute("html", value) + + @property + def value(self): + return self._get_attribute("value") + + @value.setter + def value(self, value): + self._set_attribute("value", value) + + @property + def children(self): + return self._elements + + def __iter__(self): + yield from self._elements + + def __repr__(self): + return f"{self.__class__.__name__} (length: {len(self._elements)}) {self._elements}" diff --git a/pyscript.core/src/stdlib/pyweb/media.py b/pyscript.core/src/stdlib/pyscript/web/media.py similarity index 100% rename from pyscript.core/src/stdlib/pyweb/media.py rename to pyscript.core/src/stdlib/pyscript/web/media.py diff --git a/pyscript.core/src/stdlib/pyweb/__init__.py b/pyscript.core/src/stdlib/pyweb/__init__.py deleted file mode 100644 index 80843cf2da0..00000000000 --- a/pyscript.core/src/stdlib/pyweb/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .pydom import JSProperty -from .pydom import dom as pydom diff --git a/pyscript.core/src/stdlib/pyweb/pydom.py b/pyscript.core/src/stdlib/pyweb/pydom.py deleted file mode 100644 index 0ba41b25260..00000000000 --- a/pyscript.core/src/stdlib/pyweb/pydom.py +++ /dev/null @@ -1,569 +0,0 @@ -import inspect - -try: - from typing import Any -except ImportError: - Any = "Any" - -try: - import warnings -except ImportError: - # TODO: For now it probably means we are in MicroPython. We should figure - # out the "right" way to handle this. For now we just ignore the warning - # and logging to console - class warnings: - @staticmethod - def warn(*args, **kwargs): - print("WARNING: ", *args, **kwargs) - - -try: - from functools import cached_property -except ImportError: - # TODO: same comment about micropython as above - cached_property = property - -try: - from pyodide.ffi import JsProxy -except ImportError: - # TODO: same comment about micropython as above - def JsProxy(obj): - return obj - - -from pyscript import display, document, window - -alert = window.alert - - -class JSProperty: - """JS property descriptor that directly maps to the property with the same - name in the underlying JS component.""" - - def __init__(self, name: str, allow_nones: bool = False): - self.name = name - self.allow_nones = allow_nones - - def __get__(self, obj, objtype=None): - return getattr(obj._js, self.name) - - def __set__(self, obj, value): - if not self.allow_nones and value is None: - return - setattr(obj._js, self.name, value) - - -class BaseElement: - def __init__(self, js_element): - self._js = js_element - self._parent = None - self.style = StyleProxy(self) - self._proxies = {} - - def __eq__(self, obj): - """Check if the element is the same as the other element by comparing - the underlying JS element""" - return isinstance(obj, BaseElement) and obj._js == self._js - - @property - def parent(self): - if self._parent: - return self._parent - - if self._js.parentElement: - self._parent = self.__class__(self._js.parentElement) - - return self._parent - - @property - def __class(self): - return self.__class__ if self.__class__ != PyDom else Element - - def create(self, type_, is_child=True, classes=None, html=None, label=None): - js_el = document.createElement(type_) - element = self.__class(js_el) - - if classes: - for class_ in classes: - element.add_class(class_) - - if html is not None: - element.html = html - - if label is not None: - element.label = label - - if is_child: - self.append(element) - - return element - - def find(self, selector): - """Return an ElementCollection representing all the child elements that - match the specified selector. - - Args: - selector (str): A string containing a selector expression - - Returns: - ElementCollection: A collection of elements matching the selector - """ - elements = self._js.querySelectorAll(selector) - if not elements: - return None - return ElementCollection([Element(el) for el in elements]) - - -class Element(BaseElement): - @property - def children(self): - return [self.__class__(el) for el in self._js.children] - - def append(self, child): - # TODO: this is Pyodide specific for now!!!!!! - # if we get passed a JSProxy Element directly we just map it to the - # higher level Python element - if inspect.isclass(JsProxy) and isinstance(child, JsProxy): - return self.append(Element(child)) - - elif isinstance(child, Element): - self._js.appendChild(child._js) - - return child - - elif isinstance(child, ElementCollection): - for el in child: - self.append(el) - - # -------- Pythonic Interface to Element -------- # - @property - def html(self): - return self._js.innerHTML - - @html.setter - def html(self, value): - self._js.innerHTML = value - - @property - def text(self): - return self._js.textContent - - @text.setter - def text(self, value): - self._js.textContent = value - - @property - def content(self): - # TODO: This breaks with with standard template elements. Define how to best - # handle this specifica use case. Just not support for now? - if self._js.tagName == "TEMPLATE": - warnings.warn( - "Content attribute not supported for template elements.", stacklevel=2 - ) - return None - return self._js.innerHTML - - @content.setter - def content(self, value): - # TODO: (same comment as above) - if self._js.tagName == "TEMPLATE": - warnings.warn( - "Content attribute not supported for template elements.", stacklevel=2 - ) - return - - display(value, target=self.id) - - @property - def id(self): - return self._js.id - - @id.setter - def id(self, value): - self._js.id = value - - @property - def options(self): - if "options" in self._proxies: - return self._proxies["options"] - - if not self._js.tagName.lower() in {"select", "datalist", "optgroup"}: - raise AttributeError( - f"Element {self._js.tagName} has no options attribute." - ) - self._proxies["options"] = OptionsProxy(self) - return self._proxies["options"] - - @property - def value(self): - return self._js.value - - @value.setter - def value(self, value): - # in order to avoid confusion to the user, we don't allow setting the - # value of elements that don't have a value attribute - if not hasattr(self._js, "value"): - raise AttributeError( - f"Element {self._js.tagName} has no value attribute. If you want to " - "force a value attribute, set it directly using the `_js.value = ` " - "javascript API attribute instead." - ) - self._js.value = value - - @property - def selected(self): - return self._js.selected - - @selected.setter - def selected(self, value): - # in order to avoid confusion to the user, we don't allow setting the - # value of elements that don't have a value attribute - if not hasattr(self._js, "selected"): - raise AttributeError( - f"Element {self._js.tagName} has no value attribute. If you want to " - "force a value attribute, set it directly using the `_js.value = ` " - "javascript API attribute instead." - ) - self._js.selected = value - - def clone(self, new_id=None): - clone = Element(self._js.cloneNode(True)) - clone.id = new_id - - return clone - - def remove_class(self, classname): - classList = self._js.classList - if isinstance(classname, list): - classList.remove(*classname) - else: - classList.remove(classname) - return self - - def add_class(self, classname): - classList = self._js.classList - if isinstance(classname, list): - classList.add(*classname) - else: - self._js.classList.add(classname) - return self - - @property - def classes(self): - classes = self._js.classList.values() - return [x for x in classes] - - def show_me(self): - self._js.scrollIntoView() - - def snap( - self, - to: BaseElement | str = None, - width: int | None = None, - height: int | None = None, - ): - """ - Captures a snapshot of a video element. (Only available for video elements) - - Inputs: - - * to: element where to save the snapshot of the video frame to - * width: width of the image - * height: height of the image - - Output: - (Element) canvas element where the video frame snapshot was drawn into - """ - if self._js.tagName != "VIDEO": - raise AttributeError("Snap method is only available for video Elements") - - if to is None: - canvas = self.create("canvas") - if width is None: - width = self._js.width - if height is None: - height = self._js.height - canvas._js.width = width - canvas._js.height = height - - elif isinstance(to, Element): - if to._js.tagName != "CANVAS": - raise TypeError("Element to snap to must a canvas.") - canvas = to - elif getattr(to, "tagName", "") == "CANVAS": - canvas = Element(to) - elif isinstance(to, str): - canvas = pydom[to][0] - if canvas._js.tagName != "CANVAS": - raise TypeError("Element to snap to must a be canvas.") - - canvas.draw(self, width, height) - - return canvas - - def download(self, filename: str = "snapped.png") -> None: - """Download the current element (only available for canvas elements) with the filename - provided in input. - - Inputs: - * filename (str): name of the file being downloaded - - Output: - None - """ - if self._js.tagName != "CANVAS": - raise AttributeError( - "The download method is only available for canvas Elements" - ) - - link = self.create("a") - link._js.download = filename - link._js.href = self._js.toDataURL() - link._js.click() - - def draw(self, what, width, height): - """Draw `what` on the current element (only available for canvas elements). - - Inputs: - - * what (canvas image source): An element to draw into the context. The specification permits any canvas - image source, specifically, an HTMLImageElement, an SVGImageElement, an HTMLVideoElement, - an HTMLCanvasElement, an ImageBitmap, an OffscreenCanvas, or a VideoFrame. - """ - if self._js.tagName != "CANVAS": - raise AttributeError( - "The draw method is only available for canvas Elements" - ) - - if isinstance(what, Element): - what = what._js - - # https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage - self._js.getContext("2d").drawImage(what, 0, 0, width, height) - - -class OptionsProxy: - """This class represents the options of a select element. It - allows to access to add and remove options by using the `add` and `remove` methods. - """ - - def __init__(self, element: Element) -> None: - self._element = element - if self._element._js.tagName.lower() != "select": - raise AttributeError( - f"Element {self._element._js.tagName} has no options attribute." - ) - - def add( - self, - value: Any = None, - html: str = None, - text: str = None, - before: Element | int = None, - **kws, - ) -> None: - """Add a new option to the select element""" - # create the option element and set the attributes - option = document.createElement("option") - if value is not None: - kws["value"] = value - if html is not None: - option.innerHTML = html - if text is not None: - kws["text"] = text - - for key, value in kws.items(): - option.setAttribute(key, value) - - if before: - if isinstance(before, Element): - before = before._js - - self._element._js.add(option, before) - - def remove(self, item: int) -> None: - """Remove the option at the specified index""" - self._element._js.remove(item) - - def clear(self) -> None: - """Remove all the options""" - for i in range(len(self)): - self.remove(0) - - @property - def options(self): - """Return the list of options""" - return [Element(opt) for opt in self._element._js.options] - - @property - def selected(self): - """Return the selected option""" - return self.options[self._element._js.selectedIndex] - - def __iter__(self): - yield from self.options - - def __len__(self): - return len(self.options) - - def __repr__(self): - return f"{self.__class__.__name__} (length: {len(self)}) {self.options}" - - def __getitem__(self, key): - return self.options[key] - - -class StyleProxy: # (dict): - def __init__(self, element: Element) -> None: - self._element = element - - @cached_property - def _style(self): - return self._element._js.style - - def __getitem__(self, key): - return self._style.getPropertyValue(key) - - def __setitem__(self, key, value): - self._style.setProperty(key, value) - - def remove(self, key): - self._style.removeProperty(key) - - def set(self, **kws): - for k, v in kws.items(): - self._element._js.style.setProperty(k, v) - - # CSS Properties - # Reference: https://github.com/microsoft/TypeScript/blob/main/src/lib/dom.generated.d.ts#L3799C1-L5005C2 - # Following prperties automatically generated from the above reference using - # tools/codegen_css_proxy.py - @property - def visible(self): - return self._element._js.style.visibility - - @visible.setter - def visible(self, value): - self._element._js.style.visibility = value - - -class StyleCollection: - def __init__(self, collection: "ElementCollection") -> None: - self._collection = collection - - def __get__(self, obj, objtype=None): - return obj._get_attribute("style") - - def __getitem__(self, key): - return self._collection._get_attribute("style")[key] - - def __setitem__(self, key, value): - for element in self._collection._elements: - element.style[key] = value - - def remove(self, key): - for element in self._collection._elements: - element.style.remove(key) - - -class ElementCollection: - def __init__(self, elements: [Element]) -> None: - self._elements = elements - self.style = StyleCollection(self) - - def __getitem__(self, key): - # If it's an integer we use it to access the elements in the collection - if isinstance(key, int): - return self._elements[key] - # If it's a slice we use it to support slice operations over the elements - # in the collection - elif isinstance(key, slice): - return ElementCollection(self._elements[key]) - - # If it's anything else (basically a string) we use it as a selector - # TODO: Write tests! - elements = self._element.querySelectorAll(key) - return ElementCollection([Element(el) for el in elements]) - - def __len__(self): - return len(self._elements) - - def __eq__(self, obj): - """Check if the element is the same as the other element by comparing - the underlying JS element""" - return isinstance(obj, ElementCollection) and obj._elements == self._elements - - def _get_attribute(self, attr, index=None): - if index is None: - return [getattr(el, attr) for el in self._elements] - - # As JQuery, when getting an attr, only return it for the first element - return getattr(self._elements[index], attr) - - def _set_attribute(self, attr, value): - for el in self._elements: - setattr(el, attr, value) - - @property - def html(self): - return self._get_attribute("html") - - @html.setter - def html(self, value): - self._set_attribute("html", value) - - @property - def value(self): - return self._get_attribute("value") - - @value.setter - def value(self, value): - self._set_attribute("value", value) - - @property - def children(self): - return self._elements - - def __iter__(self): - yield from self._elements - - def __repr__(self): - return f"{self.__class__.__name__} (length: {len(self._elements)}) {self._elements}" - - -class DomScope: - def __getattr__(self, __name: str): - element = document[f"#{__name}"] - if element: - return element[0] - - -class PyDom(BaseElement): - # Add objects we want to expose to the DOM namespace since this class instance is being - # remapped as "the module" itself - BaseElement = BaseElement - Element = Element - ElementCollection = ElementCollection - - def __init__(self): - # PyDom is a special case of BaseElement where we don't want to create a new JS element - # and it really doesn't have a need for styleproxy or parent to to call to __init__ - # (which actually fails in MP for some reason) - self._js = document - self._parent = None - self._proxies = {} - self.ids = DomScope() - self.body = Element(document.body) - self.head = Element(document.head) - - def create(self, type_, classes=None, html=None): - return super().create(type_, is_child=False, classes=classes, html=html) - - def __getitem__(self, key): - elements = self._js.querySelectorAll(key) - if not elements: - return None - return ElementCollection([Element(el) for el in elements]) - - -dom = PyDom() diff --git a/pyscript.core/src/stdlib/pyweb/ui/__init__.py b/pyscript.core/src/stdlib/pyweb/ui/__init__.py deleted file mode 100644 index a50ec40cefb..00000000000 --- a/pyscript.core/src/stdlib/pyweb/ui/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import elements diff --git a/pyscript.core/test/pydom.html b/pyscript.core/test/pydom.html index 90f97a23dbb..67ef4638d26 100644 --- a/pyscript.core/test/pydom.html +++ b/pyscript.core/test/pydom.html @@ -10,6 +10,8 @@ +
+ diff --git a/pyscript.core/test/pydom.py b/pyscript.core/test/pydom.py index 2f134688c19..3f579e8edb7 100644 --- a/pyscript.core/test/pydom.py +++ b/pyscript.core/test/pydom.py @@ -4,7 +4,7 @@ from datetime import datetime as dt from pyscript import display, when -from pyweb import pydom +from pyscript.web import dom display(sys.version, target="system-info") @@ -19,18 +19,15 @@ def on_click(): tstr = "{:02d}/{:02d}/{:04d} {:02d}:{:02d}:{:02d}" timenow = tstr.format(tnow[2], tnow[1], tnow[0], *tnow[2:]) - display(f"Hello from PyScript, time is: {timenow}", append=False, target="result") + display(f"Hello from PyScript, time is: {timenow}", append=False, target="#result") @when("click", "#color-button") def on_color_click(event): - btn = pydom["#result"] + btn = dom["#result"] btn.style["background-color"] = f"#{random.randrange(0x1000000):06x}" @when("click", "#color-reset-button") def reset_color(*args, **kwargs): - pydom["#result"].style["background-color"] = "white" - - -# btn_reset = pydom["#color-reset-button"][0].when('click', reset_color) + dom["#result"].style["background-color"] = "white" diff --git a/pyscript.core/test/pyscript_dom/tests/test_dom.py b/pyscript.core/test/pyscript_dom/tests/test_dom.py index d3a23c805b2..7f4af822855 100644 --- a/pyscript.core/test/pyscript_dom/tests/test_dom.py +++ b/pyscript.core/test/pyscript_dom/tests/test_dom.py @@ -2,22 +2,13 @@ import pytest from pyscript import document, when -from pyweb import pydom +from pyscript.web import dom +from pyscript.web import elements as el class TestDocument: def test__element(self): - assert pydom._js == document - - def test_no_parent(self): - assert pydom.parent is None - - def test_create_element(self): - new_el = pydom.create("div") - assert isinstance(new_el, pydom.BaseElement) - assert new_el._js.tagName == "DIV" - # EXPECT the new element to be associated with the document - assert new_el.parent == None + assert dom._js == document def test_getitem_by_id(): @@ -26,14 +17,14 @@ def test_getitem_by_id(): txt = "You found test_id_selector" selector = f"#{id_}" # EXPECT the element to be found by id - result = pydom[selector] + result = dom[selector] div = result[0] # EXPECT the element text value to match what we expect and what # the JS document.querySelector API would return assert document.querySelector(selector).innerHTML == div.html == txt # EXPECT the results to be of the right types - assert isinstance(div, pydom.BaseElement) - assert isinstance(result, pydom.ElementCollection) + assert isinstance(div, el.BaseElement) + assert isinstance(result, dom.ElementCollection) def test_getitem_by_class(): @@ -43,7 +34,7 @@ def test_getitem_by_class(): "test_selector_w_children_child_1", ] expected_class = "a-test-class" - result = pydom[f".{expected_class}"] + result = dom[f".{expected_class}"] div = result[0] # EXPECT to find exact number of elements with the class in the page (== 3) @@ -54,7 +45,7 @@ def test_getitem_by_class(): def test_read_n_write_collection_elements(): - elements = pydom[".multi-elems"] + elements = dom[".multi-elems"] for element in elements: assert element.html == f"Content {element.id.replace('#', '')}" @@ -69,15 +60,15 @@ class TestElement: def test_query(self): # GIVEN an existing element on the page, with at least 1 child element id_ = "test_selector_w_children" - parent_div = pydom[f"#{id_}"][0] + parent_div = dom[f"#{id_}"][0] # EXPECT it to be able to query for the first child element div = parent_div.find("div")[0] # EXPECT the new element to be associated with the parent assert div.parent == parent_div - # EXPECT the new element to be a BaseElement - assert isinstance(div, pydom.BaseElement) + # EXPECT the new element to be a el.BaseElement + assert isinstance(div, el.BaseElement) # EXPECT the div attributes to be == to how they are configured in the page assert div.html == "Child 1" assert div.id == "test_selector_w_children_child_1" @@ -86,8 +77,8 @@ def test_equality(self): # GIVEN 2 different Elements pointing to the same underlying element id_ = "test_id_selector" selector = f"#{id_}" - div = pydom[selector][0] - div2 = pydom[selector][0] + div = dom[selector][0] + div2 = dom[selector][0] # EXPECT them to be equal assert div == div2 @@ -102,27 +93,27 @@ def test_equality(self): def test_append_element(self): id_ = "element-append-tests" - div = pydom[f"#{id_}"][0] + div = dom[f"#{id_}"][0] len_children_before = len(div.children) - new_el = div.create("p") + new_el = el.p("new element") div.append(new_el) assert len(div.children) == len_children_before + 1 assert div.children[-1] == new_el def test_append_js_element(self): id_ = "element-append-tests" - div = pydom[f"#{id_}"][0] + div = dom[f"#{id_}"][0] len_children_before = len(div.children) - new_el = div.create("p") + new_el = el.p("new element") div.append(new_el._js) assert len(div.children) == len_children_before + 1 assert div.children[-1] == new_el def test_append_collection(self): id_ = "element-append-tests" - div = pydom[f"#{id_}"][0] + div = dom[f"#{id_}"][0] len_children_before = len(div.children) - collection = pydom[".collection"] + collection = dom[".collection"] div.append(collection) assert len(div.children) == len_children_before + len(collection) @@ -132,16 +123,16 @@ def test_append_collection(self): def test_read_classes(self): id_ = "test_class_selector" expected_class = "a-test-class" - div = pydom[f"#{id_}"][0] + div = dom[f"#{id_}"][0] assert div.classes == [expected_class] def test_add_remove_class(self): id_ = "div-no-classes" classname = "tester-class" - div = pydom[f"#{id_}"][0] + div = dom[f"#{id_}"][0] assert not div.classes div.add_class(classname) - same_div = pydom[f"#{id_}"][0] + same_div = dom[f"#{id_}"][0] assert div.classes == [classname] == same_div.classes div.remove_class(classname) assert div.classes == [] == same_div.classes @@ -149,7 +140,7 @@ def test_add_remove_class(self): def test_when_decorator(self): called = False - just_a_button = pydom["#a-test-button"][0] + just_a_button = dom["#a-test-button"][0] @when("click", just_a_button) def on_click(event): @@ -157,7 +148,7 @@ def on_click(event): called = True # Now let's simulate a click on the button (using the low level JS API) - # so we don't risk pydom getting in the way + # so we don't risk dom getting in the way assert not called just_a_button._js.click() @@ -165,7 +156,7 @@ def on_click(event): def test_html_attribute(self): # GIVEN an existing element on the page with a known empty text content - div = pydom["#element_attribute_tests"][0] + div = dom["#element_attribute_tests"][0] # WHEN we set the html attribute div.html = "New Content" @@ -177,7 +168,7 @@ def test_html_attribute(self): def test_text_attribute(self): # GIVEN an existing element on the page with a known empty text content - div = pydom["#element_attribute_tests"][0] + div = dom["#element_attribute_tests"][0] # WHEN we set the html attribute div.text = "New Content" @@ -190,12 +181,12 @@ def test_text_attribute(self): class TestCollection: def test_iter_eq_children(self): - elements = pydom[".multi-elems"] + elements = dom[".multi-elems"] assert [el for el in elements] == [el for el in elements.children] assert len(elements) == 3 def test_slices(self): - elements = pydom[".multi-elems"] + elements = dom[".multi-elems"] assert elements[0] _slice = elements[:2] assert len(_slice) == 2 @@ -205,26 +196,26 @@ def test_slices(self): def test_style_rule(self): selector = ".multi-elems" - elements = pydom[selector] + elements = dom[selector] for el in elements: assert el.style["background-color"] != "red" elements.style["background-color"] = "red" - for i, el in enumerate(pydom[selector]): + for i, el in enumerate(dom[selector]): assert elements[i].style["background-color"] == "red" assert el.style["background-color"] == "red" elements.style.remove("background-color") - for i, el in enumerate(pydom[selector]): + for i, el in enumerate(dom[selector]): assert el.style["background-color"] != "red" assert elements[i].style["background-color"] != "red" def test_when_decorator(self): called = False - buttons_collection = pydom["button"] + buttons_collection = dom["button"] @when("click", buttons_collection) def on_click(event): @@ -232,7 +223,7 @@ def on_click(event): called = True # Now let's simulate a click on the button (using the low level JS API) - # so we don't risk pydom getting in the way + # so we don't risk dom getting in the way assert not called for button in buttons_collection: button._js.click() @@ -242,32 +233,32 @@ def on_click(event): class TestCreation: def test_create_document_element(self): - new_el = pydom.create("div") + # TODO: This test should probably be removed since it's testing the elements module + new_el = el.div("new element") new_el.id = "new_el_id" - assert isinstance(new_el, pydom.BaseElement) + assert isinstance(new_el, el.BaseElement) assert new_el._js.tagName == "DIV" # EXPECT the new element to be associated with the document assert new_el.parent == None - pydom.body.append(new_el) + dom.body.append(new_el) - assert pydom["#new_el_id"][0].parent == pydom.body + assert dom["#new_el_id"][0].parent == dom.body def test_create_element_child(self): selector = "#element-creation-test" - parent_div = pydom[selector][0] + parent_div = dom[selector][0] # Creating an element from another element automatically creates that element # as a child of the original element - new_el = parent_div.create( - "p", classes=["code-description"], html="Ciao PyScripters!" - ) + new_el = el.p("a div", classes=["code-description"], html="Ciao PyScripters!") + parent_div.append(new_el) - assert isinstance(new_el, pydom.BaseElement) + assert isinstance(new_el, el.BaseElement) assert new_el._js.tagName == "P" + # EXPECT the new element to be associated with the document assert new_el.parent == parent_div - - assert pydom[selector][0].children[0] == new_el + assert dom[selector][0].children[0] == new_el class TestInput: @@ -281,7 +272,7 @@ class TestInput: def test_value(self): for id_ in self.input_ids: expected_type = id_.split("_")[-1] - result = pydom[f"#{id_}"] + result = dom[f"#{id_}"] input_el = result[0] assert input_el._js.type == expected_type assert input_el.value == f"Content {id_}" == input_el._js.value @@ -299,7 +290,7 @@ def test_value(self): def test_set_value_collection(self): for id_ in self.input_ids: - input_el = pydom[f"#{id_}"] + input_el = dom[f"#{id_}"] assert input_el.value[0] == f"Content {id_}" == input_el[0].value @@ -308,35 +299,35 @@ def test_set_value_collection(self): assert input_el.value[0] == new_value == input_el[0].value def test_element_without_value(self): - result = pydom[f"#tests-terminal"][0] + result = dom[f"#tests-terminal"][0] with pytest.raises(AttributeError): result.value = "some value" def test_element_without_collection(self): - result = pydom[f"#tests-terminal"] + result = dom[f"#tests-terminal"] with pytest.raises(AttributeError): result.value = "some value" def test_element_without_collection(self): - result = pydom[f"#tests-terminal"] + result = dom[f"#tests-terminal"] with pytest.raises(AttributeError): result.value = "some value" class TestSelect: def test_select_options_iter(self): - select = pydom[f"#test_select_element_w_options"][0] + select = dom[f"#test_select_element_w_options"][0] for i, option in enumerate(select.options, 1): assert option.value == f"{i}" assert option.html == f"Option {i}" def test_select_options_len(self): - select = pydom[f"#test_select_element_w_options"][0] + select = dom[f"#test_select_element_w_options"][0] assert len(select.options) == 2 def test_select_options_clear(self): - select = pydom[f"#test_select_element_to_clear"][0] + select = dom[f"#test_select_element_to_clear"][0] assert len(select.options) == 3 select.options.clear() @@ -345,7 +336,7 @@ def test_select_options_clear(self): def test_select_element_add(self): # GIVEN the existing select element with no options - select = pydom[f"#test_select_element"][0] + select = dom[f"#test_select_element"][0] # EXPECT the select element to have no options assert len(select.options) == 0 @@ -426,7 +417,7 @@ def test_select_element_add(self): def test_select_options_remove(self): # GIVEN the existing select element with 3 options - select = pydom[f"#test_select_element_to_remove"][0] + select = dom[f"#test_select_element_to_remove"][0] # EXPECT the select element to have 3 options assert len(select.options) == 4 @@ -448,7 +439,7 @@ def test_select_options_remove(self): def test_select_get_selected_option(self): # GIVEN the existing select element with one selected option - select = pydom[f"#test_select_element_w_options"][0] + select = dom[f"#test_select_element_w_options"][0] # WHEN we get the selected option selected_option = select.options.selected diff --git a/pyscript.core/tests/integration/test_pyweb.py b/pyscript.core/tests/integration/test_pyweb.py index d83424c8c00..80b2567d6ed 100644 --- a/pyscript.core/tests/integration/test_pyweb.py +++ b/pyscript.core/tests/integration/test_pyweb.py @@ -101,10 +101,11 @@ def parse_value(v): code_ = f""" from pyscript import when """ self.pyscript_run(code_) diff --git a/pyscript.core/types/stdlib/pyscript.d.ts b/pyscript.core/types/stdlib/pyscript.d.ts index 78a6035533d..330ea7b671d 100644 --- a/pyscript.core/types/stdlib/pyscript.d.ts +++ b/pyscript.core/types/stdlib/pyscript.d.ts @@ -7,16 +7,14 @@ declare namespace _default { "ffi.py": string; "magic_js.py": string; "util.py": string; - "websocket.py": string; - }; - let pyweb: { - "__init__.py": string; - "media.py": string; - "pydom.py": string; - ui: { + web: { "__init__.py": string; + "dom.py": string; "elements.py": string; + "media.py": string; }; + "websocket.py": string; }; + let pyweb: {}; } export default _default; From a1e5a05b493d0bb89a36ea12fbaf9387e44a3674 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Wed, 12 Jun 2024 18:55:36 +0200 Subject: [PATCH 064/179] PyEditor cumulative fixes & improvements (#2095) * PyEditor fixes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * PyEditor cumulative fixes & improvements --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- README.md | 4 +- pyscript.core/package-lock.json | 402 +++++++++++++++++++---- pyscript.core/package.json | 8 +- pyscript.core/src/plugins/py-editor.js | 58 +++- pyscript.core/types/stdlib/pyscript.d.ts | 1 - 5 files changed, 388 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index 3e658ac1fef..869c25b952c 100644 --- a/README.md +++ b/README.md @@ -38,11 +38,11 @@ To try PyScript, import the appropriate pyscript files into the `` tag of diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index dda92be5dbf..60de038bcce 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.42", + "version": "0.4.44", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.42", + "version": "0.4.44", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", @@ -21,9 +21,9 @@ "@codemirror/lang-python": "^6.1.6", "@codemirror/language": "^6.10.2", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.27.0", + "@codemirror/view": "^6.28.0", "@playwright/test": "^1.44.1", - "@rollup/plugin-commonjs": "^25.0.8", + "@rollup/plugin-commonjs": "^26.0.1", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", "@webreflection/toml-j0.4": "^1.1.3", @@ -135,9 +135,9 @@ "license": "MIT" }, "node_modules/@codemirror/view": { - "version": "6.27.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.27.0.tgz", - "integrity": "sha512-8kqX1sHbVW1lVzWwrjAbh4dR7eKhV8eIQ952JKaBXOoXE04WncoqCy4DMU701LSrPZ3N2Q4zsTawz7GQ+2mrUw==", + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.28.0.tgz", + "integrity": "sha512-fo7CelaUDKWIyemw4b+J57cWuRkOu4SWCCPfNDkPvfWkGjM9D5racHQXr4EQeYCD6zEBIBxGCeaKkQo+ysl0gA==", "dev": true, "license": "MIT", "dependencies": { @@ -272,6 +272,78 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -525,6 +597,17 @@ "win32" ] }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@playwright/test": { "version": "1.44.1", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.44.1.tgz", @@ -542,21 +625,21 @@ } }, "node_modules/@rollup/plugin-commonjs": { - "version": "25.0.8", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.8.tgz", - "integrity": "sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==", + "version": "26.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-26.0.1.tgz", + "integrity": "sha512-UnsKoZK6/aGIH6AdkptXhNvhaqftcjq3zZdT+LY5Ftms6JR06nADcDsYp5hTU9E2lbJUEOhdlY5J4DNTneM+jQ==", "dev": true, "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", - "glob": "^8.0.3", + "glob": "^10.4.1", "is-reference": "1.2.1", "magic-string": "^0.30.3" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0 || 14 >= 14.17" }, "peerDependencies": { "rollup": "^2.68.0||^3.0.0||^4.0.0" @@ -1632,6 +1715,13 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, "node_modules/electron-to-chromium": { "version": "1.4.783", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.783.tgz", @@ -1947,12 +2037,22 @@ "dev": true, "license": "ISC" }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", "dev": true, - "license": "ISC" + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/fsevents": { "version": "2.3.3", @@ -1996,21 +2096,23 @@ } }, "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", "dev": true, "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -2040,16 +2142,19 @@ } }, "node_modules/glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/globals": { @@ -2187,25 +2292,6 @@ "node": ">=0.8.19" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -2325,6 +2411,25 @@ "dev": true, "license": "ISC" }, + "node_modules/jackspeak": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", + "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2447,6 +2552,16 @@ "dev": true, "license": "MIT" }, + "node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/magic-string": { "version": "0.30.10", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", @@ -2500,6 +2615,16 @@ "node": "*" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -2577,16 +2702,6 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -2717,6 +2832,23 @@ "dev": true, "license": "MIT" }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", @@ -3713,6 +3845,19 @@ "node": ">=8" } }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/smob": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", @@ -3804,6 +3949,22 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -3817,6 +3978,20 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -4075,12 +4250,109 @@ "node": ">=0.10.0" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } }, "node_modules/ws": { "version": "8.17.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index a52aae3ffab..1fda1a75512 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.42", + "version": "0.4.44", "type": "module", "description": "PyScript", "module": "./index.js", @@ -20,7 +20,7 @@ }, "scripts": { "server": "npx static-handler --coi .", - "build": "export ESLINT_USE_FLAT_CONFIG=true;npm run build:3rd-party && npm run build:stdlib && npm run build:plugins && npm run build:core && eslint src/ && npm run ts && npm run test:mpy", + "build": "export ESLINT_USE_FLAT_CONFIG=true;npm run build:3rd-party && npm run build:stdlib && npm run build:plugins && npm run build:core && if [ -z \"$NO_MIN\" ]; then eslint src/ && npm run ts && npm run test:mpy; fi", "build:core": "rm -rf dist && rollup --config rollup/core.config.js && cp src/3rd-party/*.css dist/", "build:plugins": "node rollup/plugins.cjs", "build:stdlib": "node rollup/stdlib.cjs", @@ -53,9 +53,9 @@ "@codemirror/lang-python": "^6.1.6", "@codemirror/language": "^6.10.2", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.27.0", + "@codemirror/view": "^6.28.0", "@playwright/test": "^1.44.1", - "@rollup/plugin-commonjs": "^25.0.8", + "@rollup/plugin-commonjs": "^26.0.1", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", "@webreflection/toml-j0.4": "^1.1.3", diff --git a/pyscript.core/src/plugins/py-editor.js b/pyscript.core/src/plugins/py-editor.js index a87087d7cff..ecf07456083 100644 --- a/pyscript.core/src/plugins/py-editor.js +++ b/pyscript.core/src/plugins/py-editor.js @@ -86,21 +86,24 @@ async function execute({ currentTarget }) { }); } -const makeRunButton = (listener, type) => { +const makeRunButton = (handler, type) => { const runButton = document.createElement("button"); runButton.className = `absolute ${type}-editor-run-button`; runButton.innerHTML = RUN_BUTTON; runButton.setAttribute("aria-label", "Python Script Run Button"); - runButton.addEventListener("click", listener); + runButton.addEventListener("click", async (event) => { + runButton.blur(); + await handler.handleEvent(event); + }); return runButton; }; -const makeEditorDiv = (listener, type) => { +const makeEditorDiv = (handler, type) => { const editorDiv = document.createElement("div"); editorDiv.className = `${type}-editor-input`; editorDiv.setAttribute("aria-label", "Python Script Area"); - const runButton = makeRunButton(listener, type); + const runButton = makeRunButton(handler, type); const editorShadowContainer = document.createElement("div"); // avoid outer elements intercepting key events (reveal as example) @@ -120,15 +123,15 @@ const makeOutDiv = (type) => { return outDiv; }; -const makeBoxDiv = (listener, type) => { +const makeBoxDiv = (handler, type) => { const boxDiv = document.createElement("div"); boxDiv.className = `${type}-editor-box`; - const editorDiv = makeEditorDiv(listener, type); + const editorDiv = makeEditorDiv(handler, type); const outDiv = makeOutDiv(type); boxDiv.append(editorDiv, outDiv); - return [boxDiv, outDiv]; + return [boxDiv, outDiv, editorDiv.querySelector("button")]; }; const init = async (script, type, interpreter) => { @@ -138,7 +141,7 @@ const init = async (script, type, interpreter) => { { python }, { indentUnit }, { keymap }, - { defaultKeymap }, + { defaultKeymap, indentWithTab }, ] = await Promise.all([ import(/* webpackIgnore: true */ "../3rd-party/codemirror.js"), import(/* webpackIgnore: true */ "../3rd-party/codemirror_state.js"), @@ -168,6 +171,8 @@ const init = async (script, type, interpreter) => { ? await fetch(script.src).then((b) => b.text()) : script.textContent; const context = { + // allow the listener to be overridden at distance + handleEvent: execute, interpreter, env, config: @@ -184,6 +189,29 @@ const init = async (script, type, interpreter) => { let target; defineProperties(script, { target: { get: () => target }, + handleEvent: { + get: () => context.handleEvent, + set: (callback) => { + // do not bother with logic if it was set back as its original handler + if (callback === execute) context.handleEvent = execute; + // in every other case be sure that if the listener override returned + // `false` nothing happens, otherwise keep doing what it always did + else { + context.handleEvent = async (event) => { + // trap the currentTarget ASAP (if any) + // otherwise it gets lost asynchronously + const { currentTarget } = event; + // augment a code snapshot before invoking the override + defineProperties(event, { + code: { value: context.pySrc }, + }); + // avoid executing the default handler if the override returned `false` + if ((await callback(event)) !== false) + await execute.call(context, { currentTarget }); + }; + } + }, + }, code: { get: () => context.pySrc, set: (insert) => { @@ -214,8 +242,8 @@ const init = async (script, type, interpreter) => { isSetup = wasSetup; source = wasSource; }; - return execute - .call(context, { currentTarget: null }) + return context + .handleEvent({ currentTarget: null }) .then(restore, restore); }, }, @@ -227,7 +255,7 @@ const init = async (script, type, interpreter) => { }; if (isSetup) { - await execute.call(context, { currentTarget: null }); + await context.handleEvent({ currentTarget: null }); notify(); return; } @@ -250,8 +278,7 @@ const init = async (script, type, interpreter) => { if (!target.hasAttribute("root")) target.setAttribute("root", target.id); // @see https://github.com/JeffersGlass/mkdocs-pyscript/blob/main/mkdocs_pyscript/js/makeblocks.js - const listener = execute.bind(context); - const [boxDiv, outDiv] = makeBoxDiv(listener, type); + const [boxDiv, outDiv, runButton] = makeBoxDiv(context, type); boxDiv.dataset.env = script.hasAttribute("env") ? env : interpreter; const inputChild = boxDiv.querySelector(`.${type}-editor-input > div`); @@ -266,6 +293,7 @@ const init = async (script, type, interpreter) => { // preserve user indentation, if any const indentation = /^(\s+)/m.test(doc) ? RegExp.$1 : " "; + const listener = () => runButton.click(); const editor = new EditorView({ extensions: [ indentUnit.of(indentation), @@ -275,9 +303,13 @@ const init = async (script, type, interpreter) => { { key: "Ctrl-Enter", run: listener, preventDefault: true }, { key: "Cmd-Enter", run: listener, preventDefault: true }, { key: "Shift-Enter", run: listener, preventDefault: true }, + // @see https://codemirror.net/examples/tab/ + indentWithTab, ]), basicSetup, ], + foldGutter: true, + gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"], parent, doc, }); diff --git a/pyscript.core/types/stdlib/pyscript.d.ts b/pyscript.core/types/stdlib/pyscript.d.ts index 330ea7b671d..613e822c26c 100644 --- a/pyscript.core/types/stdlib/pyscript.d.ts +++ b/pyscript.core/types/stdlib/pyscript.d.ts @@ -15,6 +15,5 @@ declare namespace _default { }; "websocket.py": string; }; - let pyweb: {}; } export default _default; From aab015b9b85f10ad6804b49f0ab3143337e51b97 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Thu, 13 Jun 2024 11:34:14 +0200 Subject: [PATCH 065/179] Better py editor indentation (#2098) Better PyEditor Indentation --- pyscript.core/package-lock.json | 84 +++++++++++++------------- pyscript.core/package.json | 6 +- pyscript.core/src/plugins/py-editor.js | 2 +- 3 files changed, 46 insertions(+), 46 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 60de038bcce..21cf506ca52 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.44", + "version": "0.4.46", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.44", + "version": "0.4.46", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", @@ -21,7 +21,7 @@ "@codemirror/lang-python": "^6.1.6", "@codemirror/language": "^6.10.2", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.28.0", + "@codemirror/view": "^6.28.1", "@playwright/test": "^1.44.1", "@rollup/plugin-commonjs": "^26.0.1", "@rollup/plugin-node-resolve": "^15.2.3", @@ -29,7 +29,7 @@ "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", - "bun": "^1.1.12", + "bun": "^1.1.13", "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^9.4.0", @@ -135,9 +135,9 @@ "license": "MIT" }, "node_modules/@codemirror/view": { - "version": "6.28.0", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.28.0.tgz", - "integrity": "sha512-fo7CelaUDKWIyemw4b+J57cWuRkOu4SWCCPfNDkPvfWkGjM9D5racHQXr4EQeYCD6zEBIBxGCeaKkQo+ysl0gA==", + "version": "6.28.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.28.1.tgz", + "integrity": "sha512-BUWr+zCJpMkA/u69HlJmR+YkV4yPpM81HeMkOMZuwFa8iM5uJdEPKAs1icIRZKkKmy0Ub1x9/G3PQLTXdpBxrQ==", "dev": true, "license": "MIT", "dependencies": { @@ -486,9 +486,9 @@ } }, "node_modules/@oven/bun-darwin-aarch64": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.12.tgz", - "integrity": "sha512-g8nmDXIYDmbEnP6moX3ZTS5BsikX8dz/XB0PAfL+LEBJEGECyor2Hv1yvhGQfeR1/lvfSXsWnk0Hhk9Mrj6uoQ==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.13.tgz", + "integrity": "sha512-XjnL/B3i7s3xR7f7rYtXU5fyVb27g1Hd5fsmkyi1sNmB/34Lt/KRMmhp4C7brjxFtbI3NSkrvF+b3PkprQzPCA==", "cpu": [ "arm64" ], @@ -500,9 +500,9 @@ ] }, "node_modules/@oven/bun-darwin-x64": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.12.tgz", - "integrity": "sha512-XWL6atcLxyh4KgOlqqyHUOh4Ylm46CExipJmAdKs30gyYqbw3E+HTFhADsyFEtugOe0qPUNlo0aMo+ZMc1yIQA==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.13.tgz", + "integrity": "sha512-N9t2JHLIEs/n+d7R6ybU/3d7o7xGeKd1U3vip9RMLaEAaJM6mfByAHmhwaQesr3Z6ljcs1zkQJNaFMJA/cJqnA==", "cpu": [ "x64" ], @@ -514,9 +514,9 @@ ] }, "node_modules/@oven/bun-darwin-x64-baseline": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.12.tgz", - "integrity": "sha512-KXBwaeD9y4GuxSqC1uDNIktTC/jY2DtagiURuUOF1rniYxkkLRNgXotTvVA5NvP2PBCoWyrxZ67WJSBm0AIyjQ==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.13.tgz", + "integrity": "sha512-RvVAeFMIayd8HKJqkWnZdI9BQJbH87jAXhNVMLlHpGqP4JVvkPLCKJT5jr9/4FGeWtQmMMZufH6PzTxpHCc9HQ==", "cpu": [ "x64" ], @@ -528,9 +528,9 @@ ] }, "node_modules/@oven/bun-linux-aarch64": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.12.tgz", - "integrity": "sha512-6Jen4+b5BzInF7bbRjMIWoy3xIuK/kQQn9xehvrAYnr3J9p3vCD5VhzDP20hW9yQcmZtO2kE6pIYCbaaxPNKtg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.13.tgz", + "integrity": "sha512-5F9EKOjQauRXr+D3VjeMebKyq93xhdgrBOfpPnAn/C+NLFs1Wa2ZjwGAKjW2akmqht6milHft3sbsnCIR+MWIQ==", "cpu": [ "arm64" ], @@ -542,9 +542,9 @@ ] }, "node_modules/@oven/bun-linux-x64": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.12.tgz", - "integrity": "sha512-X4dqnIOv4M9HAL4tAj9bb14WjsfKby5xWNV/otUxtfSDsDrV2ukYUekivEmHqchxHFUHOHyc/cv+/jtfvedDZg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.13.tgz", + "integrity": "sha512-3mq50HhwJbAwu0Dw6OCB5PS6uD1bpFGb8XrEgxnOB3ZydCBOVRRjoY1Jb8HjYHVKzFJZoPrUqulToA8od3IzeQ==", "cpu": [ "x64" ], @@ -556,9 +556,9 @@ ] }, "node_modules/@oven/bun-linux-x64-baseline": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.12.tgz", - "integrity": "sha512-luwWf/QGMJ23+yIRBMDnhjYuxh9zXy+Vw4lAzwvLB7phYXCs7IPEhIhZxhcZQ3XMafWtHlWAVo5P6NZZdFRMUQ==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.13.tgz", + "integrity": "sha512-0zhCVLsFcIyfqqsum7XUejuF3QhRkhI1DxgHQrLs16EKS4gt4X4A49jgTIHOvyedHcKb3FZOLsyjpOejB8kIpg==", "cpu": [ "x64" ], @@ -570,9 +570,9 @@ ] }, "node_modules/@oven/bun-windows-x64": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.12.tgz", - "integrity": "sha512-ufvTeXXI9tJSJUhvdPnFUmGqCNBKBazEwjvQ5c8vhtZ8hdBHV54LoURVDIBYCgzfdv5NQT3sr8qRLFqy4mlMLg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.13.tgz", + "integrity": "sha512-PwFKQVFzhpUMAF86PwIEctfFT8ZQe1Gueqn1dKk07lwJOBve+Ou2NUEoQsq0eac0Cbw2C20fScjyVzDBwIMIPQ==", "cpu": [ "x64" ], @@ -584,9 +584,9 @@ ] }, "node_modules/@oven/bun-windows-x64-baseline": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.12.tgz", - "integrity": "sha512-MRn+zcJO1hcVqwJmFxpUSdb6ZvrYC8Xp2N1fPOzdw3YSskz9iHkJuUKzx7s9iCC7jTpo6XI/H51EFr/M2U7Ipg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.13.tgz", + "integrity": "sha512-7CVWrc/6LSRrdkxwBjAt4ehqQrLxC9k8+LI7VZKAYt1yNHM3JaOhcPyt3AJB10cmzc5HA/q/uSi6xcNUnlCWiA==", "cpu": [ "x64" ], @@ -1220,9 +1220,9 @@ } }, "node_modules/bun": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.12.tgz", - "integrity": "sha512-NZzeZuZk7VwCs8VAXnXUHCPOlTS/IyHCscChtT1M1FLSwhBcVMsGVStYlXaaoqsinBKgp0CGJdhnJw2gR3NkDw==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.13.tgz", + "integrity": "sha512-yrujTLEspzQJfh7hd2xkYM5skQsjBwVm/wq0cyYBkR5x4FRveOUqeAqtFOPH4aHvsDgwVN+dO0uIrlvE7dDsDQ==", "cpu": [ "arm64", "x64" @@ -1240,14 +1240,14 @@ "bunx": "bin/bun.exe" }, "optionalDependencies": { - "@oven/bun-darwin-aarch64": "1.1.12", - "@oven/bun-darwin-x64": "1.1.12", - "@oven/bun-darwin-x64-baseline": "1.1.12", - "@oven/bun-linux-aarch64": "1.1.12", - "@oven/bun-linux-x64": "1.1.12", - "@oven/bun-linux-x64-baseline": "1.1.12", - "@oven/bun-windows-x64": "1.1.12", - "@oven/bun-windows-x64-baseline": "1.1.12" + "@oven/bun-darwin-aarch64": "1.1.13", + "@oven/bun-darwin-x64": "1.1.13", + "@oven/bun-darwin-x64-baseline": "1.1.13", + "@oven/bun-linux-aarch64": "1.1.13", + "@oven/bun-linux-x64": "1.1.13", + "@oven/bun-linux-x64-baseline": "1.1.13", + "@oven/bun-windows-x64": "1.1.13", + "@oven/bun-windows-x64-baseline": "1.1.13" } }, "node_modules/callsites": { diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 1fda1a75512..93056f2df6c 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.44", + "version": "0.4.46", "type": "module", "description": "PyScript", "module": "./index.js", @@ -53,7 +53,7 @@ "@codemirror/lang-python": "^6.1.6", "@codemirror/language": "^6.10.2", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.28.0", + "@codemirror/view": "^6.28.1", "@playwright/test": "^1.44.1", "@rollup/plugin-commonjs": "^26.0.1", "@rollup/plugin-node-resolve": "^15.2.3", @@ -61,7 +61,7 @@ "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", - "bun": "^1.1.12", + "bun": "^1.1.13", "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^9.4.0", diff --git a/pyscript.core/src/plugins/py-editor.js b/pyscript.core/src/plugins/py-editor.js index ecf07456083..0a0f69a942e 100644 --- a/pyscript.core/src/plugins/py-editor.js +++ b/pyscript.core/src/plugins/py-editor.js @@ -291,7 +291,7 @@ const init = async (script, type, interpreter) => { const doc = dedent(script.textContent).trim(); // preserve user indentation, if any - const indentation = /^(\s+)/m.test(doc) ? RegExp.$1 : " "; + const indentation = /^([ \t]+)/m.test(doc) ? RegExp.$1 : " "; const listener = () => runButton.click(); const editor = new EditorView({ From d0406be84cb47b82e05e5a5826564a2e9a68dd7c Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Wed, 19 Jun 2024 14:11:57 +0200 Subject: [PATCH 066/179] A persistent IndexedDB store for PyScript (#2101) A persistent IndexedDB store for PyScript --- pyscript.core/package-lock.json | 367 ++++++++++-------- pyscript.core/package.json | 10 +- pyscript.core/rollup/flatted.cjs | 17 + pyscript.core/src/stdlib/pyscript/__init__.py | 1 + pyscript.core/src/stdlib/pyscript/flatted.py | 148 +++++++ pyscript.core/src/stdlib/pyscript/storage.py | 60 +++ pyscript.core/test/mpy.spec.js | 5 + pyscript.core/test/storage.html | 46 +++ pyscript.core/types/stdlib/pyscript.d.ts | 2 + 9 files changed, 489 insertions(+), 167 deletions(-) create mode 100644 pyscript.core/rollup/flatted.cjs create mode 100644 pyscript.core/src/stdlib/pyscript/flatted.py create mode 100644 pyscript.core/src/stdlib/pyscript/storage.py create mode 100644 pyscript.core/test/storage.html diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 21cf506ca52..048475c54c8 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.4.46", + "version": "0.4.47", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.46", + "version": "0.4.47", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.14", + "polyscript": "^0.13.4", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -29,10 +29,11 @@ "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", - "bun": "^1.1.13", + "bun": "^1.1.14", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^9.4.0", + "eslint": "^9.5.0", + "flatted": "^3.3.1", "rollup": "^4.18.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", @@ -43,9 +44,9 @@ } }, "node_modules/@codemirror/autocomplete": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.16.0.tgz", - "integrity": "sha512-P/LeCTtZHRTCU4xQsa89vSKWecYv1ZqwzOd5topheGRf+qtacFgBeIMQi3eL8Kt/BUNvxUWkx+5qP2jlGoARrg==", + "version": "6.16.2", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.16.2.tgz", + "integrity": "sha512-MjfDrHy0gHKlPWsvSsikhO1+BOh+eBHNgfH1OXs1+DAf30IonQldgMM3kxLDTG9ktE7kDLaA1j/l7KMPA4KNfw==", "dev": true, "license": "MIT", "dependencies": { @@ -176,9 +177,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", "dev": true, "license": "MIT", "engines": { @@ -186,13 +187,13 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.15.1.tgz", - "integrity": "sha512-K4gzNq+yymn/EVsXYmf+SBcBro8MTf+aXJZUphM96CdzUEr+ClGDvAbpmaEK+cGVigVXIgs9gNmvHAlrzzY5JQ==", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.16.0.tgz", + "integrity": "sha512-/jmuSd74i4Czf1XXn7wGRWZCuyaUZ330NH1Bek0Pplatt4Sy1S5haN21SCLLdbeKslQ+S0wEJ+++v5YibSi+Lg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.3", + "@eslint/object-schema": "^2.1.4", "debug": "^4.3.1", "minimatch": "^3.0.5" }, @@ -225,9 +226,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.4.0.tgz", - "integrity": "sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.5.0.tgz", + "integrity": "sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w==", "dev": true, "license": "MIT", "engines": { @@ -235,9 +236,9 @@ } }, "node_modules/@eslint/object-schema": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.3.tgz", - "integrity": "sha512-HAbhAYKfsAC2EkTqve00ibWIZlaU74Z1EHwAjYr4PXF0YU2VEA1zSIKSSpKszRLRWwHzzRZXvK632u+uXzvsvw==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -303,31 +304,6 @@ "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", @@ -426,9 +402,9 @@ } }, "node_modules/@lezer/lr": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.0.tgz", - "integrity": "sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.1.tgz", + "integrity": "sha512-CHsKq8DMKBf9b3yXPDIU4DbH+ZJd/sJdYOW2llbW/HudP5u0VS6Bfq1hLYfgU7uAYGFIyGGQIsSOXGPEErZiJw==", "dev": true, "license": "MIT", "dependencies": { @@ -486,9 +462,9 @@ } }, "node_modules/@oven/bun-darwin-aarch64": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.13.tgz", - "integrity": "sha512-XjnL/B3i7s3xR7f7rYtXU5fyVb27g1Hd5fsmkyi1sNmB/34Lt/KRMmhp4C7brjxFtbI3NSkrvF+b3PkprQzPCA==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.14.tgz", + "integrity": "sha512-zdgLlQ9+SUOgJzTMQyb0lnX2MRtFgVApXPR9c0lSVUqPbfcGogVDRuNFWdYK96wjUkrCJIvYeu5rbMGcnJD1Qg==", "cpu": [ "arm64" ], @@ -500,9 +476,9 @@ ] }, "node_modules/@oven/bun-darwin-x64": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.13.tgz", - "integrity": "sha512-N9t2JHLIEs/n+d7R6ybU/3d7o7xGeKd1U3vip9RMLaEAaJM6mfByAHmhwaQesr3Z6ljcs1zkQJNaFMJA/cJqnA==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.14.tgz", + "integrity": "sha512-CEoFw0udQRann0Vj3Et1/nW6MV3EY/kZ+lNkSCCmFEvq1HDLB+Wbicgnt9GbEElw6XXXKm4FdxMYnOJzfeanYQ==", "cpu": [ "x64" ], @@ -514,9 +490,9 @@ ] }, "node_modules/@oven/bun-darwin-x64-baseline": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.13.tgz", - "integrity": "sha512-RvVAeFMIayd8HKJqkWnZdI9BQJbH87jAXhNVMLlHpGqP4JVvkPLCKJT5jr9/4FGeWtQmMMZufH6PzTxpHCc9HQ==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.14.tgz", + "integrity": "sha512-k1vKXmOQ9+Rdj6dkgPIo0MWKmEf9+CmjyD2GZkRM6dxufiytNSuE5yT8FQMtb2Yg1I8OFH/+kUiNxn2eIKurRw==", "cpu": [ "x64" ], @@ -528,9 +504,9 @@ ] }, "node_modules/@oven/bun-linux-aarch64": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.13.tgz", - "integrity": "sha512-5F9EKOjQauRXr+D3VjeMebKyq93xhdgrBOfpPnAn/C+NLFs1Wa2ZjwGAKjW2akmqht6milHft3sbsnCIR+MWIQ==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.14.tgz", + "integrity": "sha512-uHI7jk47C6wwG/y90W35NttyDrKLWum1pa5PfpuMi8+LpxnRGi0doGXN73RwdJy+qnYp2OjJTo60X++GMn9GmA==", "cpu": [ "arm64" ], @@ -542,9 +518,9 @@ ] }, "node_modules/@oven/bun-linux-x64": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.13.tgz", - "integrity": "sha512-3mq50HhwJbAwu0Dw6OCB5PS6uD1bpFGb8XrEgxnOB3ZydCBOVRRjoY1Jb8HjYHVKzFJZoPrUqulToA8od3IzeQ==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.14.tgz", + "integrity": "sha512-t2b6pDSlV2Uke6ON5eSx1hk/o+f4s8Nr+E1djx9fNqrvz58UF4zmilQoEKDhciuRUKvhMkroddiORpxIMiKIjA==", "cpu": [ "x64" ], @@ -556,9 +532,9 @@ ] }, "node_modules/@oven/bun-linux-x64-baseline": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.13.tgz", - "integrity": "sha512-0zhCVLsFcIyfqqsum7XUejuF3QhRkhI1DxgHQrLs16EKS4gt4X4A49jgTIHOvyedHcKb3FZOLsyjpOejB8kIpg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.14.tgz", + "integrity": "sha512-7otawHLy8ec0iN0wr7sznkOpMhofZCfJeA4vWp+5D/yhXg8ZxVaK7xJ1aWBlBLHAMX8tWTkrUjB6X2iQFtvZvQ==", "cpu": [ "x64" ], @@ -570,9 +546,9 @@ ] }, "node_modules/@oven/bun-windows-x64": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.13.tgz", - "integrity": "sha512-PwFKQVFzhpUMAF86PwIEctfFT8ZQe1Gueqn1dKk07lwJOBve+Ou2NUEoQsq0eac0Cbw2C20fScjyVzDBwIMIPQ==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.14.tgz", + "integrity": "sha512-hZ+Z0zgO6FM63U99wkF0YvTLm/Tcfa4ue5U9JOGc8K05DLBS4gHp6f0bngzd3EvIEz+mfc+zcYPR954dYHT9AA==", "cpu": [ "x64" ], @@ -584,9 +560,9 @@ ] }, "node_modules/@oven/bun-windows-x64-baseline": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.13.tgz", - "integrity": "sha512-7CVWrc/6LSRrdkxwBjAt4ehqQrLxC9k8+LI7VZKAYt1yNHM3JaOhcPyt3AJB10cmzc5HA/q/uSi6xcNUnlCWiA==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.14.tgz", + "integrity": "sha512-oK7y0q5sICni6771q+xvJ40dqzg0l+x2IdkN8V2I5QMzQCqFIVPhwPmOX5+2JsMp9ILQtYeioyL60kCDgIguDw==", "cpu": [ "x64" ], @@ -988,6 +964,12 @@ "integrity": "sha512-zCcqCJoNLvdeF41asAK71XPlwSPieeRDsE09albBunJEksuYPYNillKNQjf8p5BqSoTKTuKrW3lUm3MNodUC4g==", "license": "MIT" }, + "node_modules/@webreflection/idb-map": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@webreflection/idb-map/-/idb-map-0.3.1.tgz", + "integrity": "sha512-lRCanqwR7tHHFohJHAMSMEZnoNPvgjcKr0f5e4y+lTJA+fctT61EZ+f5pT5/+8+wlSsMAvXjzfKRLT6o9aqxbA==", + "license": "MIT" + }, "node_modules/@webreflection/toml-j0.4": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@webreflection/toml-j0.4/-/toml-j0.4-1.1.3.tgz", @@ -1023,9 +1005,9 @@ "peer": true }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", "dev": true, "license": "MIT", "bin": { @@ -1167,9 +1149,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", + "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", "dev": true, "funding": [ { @@ -1187,10 +1169,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", + "caniuse-lite": "^1.0.30001629", + "electron-to-chromium": "^1.4.796", "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "update-browserslist-db": "^1.0.16" }, "bin": { "browserslist": "cli.js" @@ -1220,9 +1202,9 @@ } }, "node_modules/bun": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.13.tgz", - "integrity": "sha512-yrujTLEspzQJfh7hd2xkYM5skQsjBwVm/wq0cyYBkR5x4FRveOUqeAqtFOPH4aHvsDgwVN+dO0uIrlvE7dDsDQ==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.14.tgz", + "integrity": "sha512-LqbB6Xr8bU6D9K18UOrzmLLPYOS9CQ3SGW+JvTUli/eYW4y70yzdCr6JZiw3pk0V8ZqHn9Kmg3c8/7rF2XIM8g==", "cpu": [ "arm64", "x64" @@ -1240,14 +1222,14 @@ "bunx": "bin/bun.exe" }, "optionalDependencies": { - "@oven/bun-darwin-aarch64": "1.1.13", - "@oven/bun-darwin-x64": "1.1.13", - "@oven/bun-darwin-x64-baseline": "1.1.13", - "@oven/bun-linux-aarch64": "1.1.13", - "@oven/bun-linux-x64": "1.1.13", - "@oven/bun-linux-x64-baseline": "1.1.13", - "@oven/bun-windows-x64": "1.1.13", - "@oven/bun-windows-x64-baseline": "1.1.13" + "@oven/bun-darwin-aarch64": "1.1.14", + "@oven/bun-darwin-x64": "1.1.14", + "@oven/bun-darwin-x64-baseline": "1.1.14", + "@oven/bun-linux-aarch64": "1.1.14", + "@oven/bun-linux-x64": "1.1.14", + "@oven/bun-linux-x64-baseline": "1.1.14", + "@oven/bun-windows-x64": "1.1.14", + "@oven/bun-windows-x64-baseline": "1.1.14" } }, "node_modules/callsites": { @@ -1274,9 +1256,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001624", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001624.tgz", - "integrity": "sha512-0dWnQG87UevOCPYaOR49CBcLBwoZLpws+k6W37nLjWUhumP1Isusj0p2u+3KhjNloRWK9OKMgjBBzPujQHw4nA==", + "version": "1.0.30001636", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz", + "integrity": "sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==", "dev": true, "funding": [ { @@ -1622,9 +1604,9 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, "license": "MIT", "dependencies": { @@ -1723,16 +1705,16 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.4.783", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.783.tgz", - "integrity": "sha512-bT0jEz/Xz1fahQpbZ1D7LgmPYZ3iHVY39NcWWro1+hA2IvjiPeaXtfSqrQ+nXjApMvQRE2ASt1itSLRrebHMRQ==", + "version": "1.4.805", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.805.tgz", + "integrity": "sha512-8W4UJwX/w9T0QSzINJckTKG6CYpAUTqsaWcWIsdud3I1FYJcMgW9QqT1/4CBff/pP/TihWh13OmiyY8neto6vw==", "dev": true, "license": "ISC" }, "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, "license": "MIT" }, @@ -1770,17 +1752,17 @@ } }, "node_modules/eslint": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.4.0.tgz", - "integrity": "sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.5.0.tgz", + "integrity": "sha512-+NAOZFrW/jFTS3dASCGBxX1pkFD0/fsO+hfAkJ4TyYKwgsXZbqzrw+seCYFCcPCYXvnD67tAnglU7GQTz6kcVw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/config-array": "^0.15.1", + "@eslint/config-array": "^0.16.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.4.0", + "@eslint/js": "9.5.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -1792,7 +1774,7 @@ "eslint-scope": "^8.0.1", "eslint-visitor-keys": "^4.0.0", "espree": "^10.0.1", - "esquery": "^1.4.2", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", @@ -1818,7 +1800,7 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" } }, "node_modules/eslint-scope": { @@ -1865,13 +1847,13 @@ } }, "node_modules/espree": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", - "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.11.3", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.0.0" }, @@ -2038,9 +2020,9 @@ "license": "ISC" }, "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", "dev": true, "license": "ISC", "dependencies": { @@ -2499,9 +2481,9 @@ } }, "node_modules/loader-utils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", - "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", "dev": true, "license": "MIT", "engines": { @@ -2936,14 +2918,15 @@ } }, "node_modules/polyscript": { - "version": "0.12.14", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.12.14.tgz", - "integrity": "sha512-inflltAxoMmZZ1qGYIPPBe8KZFPtcatqUCbJjvTzR/gRHpa6PfcZQi2p4HobqDVZLc3LXdODi/GtRxZuRK8a3w==", + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.13.4.tgz", + "integrity": "sha512-kpr2GDq4FLswasiX9QETez3hXTHglzKyNC7gzmH1+dTHEh/GYsa7rbbv0pLr8JWlTm6Rs13fHB8qnaQ0DweCVg==", "license": "APACHE-2.0", "dependencies": { "@ungap/structured-clone": "^1.2.0", "@ungap/with-resolvers": "^0.1.0", "@webreflection/fetch": "^0.1.5", + "@webreflection/idb-map": "^0.3.1", "basic-devtools": "^0.1.6", "codedent": "^0.1.2", "coincident": "^1.2.3", @@ -3935,18 +3918,21 @@ "license": "CC0-1.0" }, "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/string-width-cjs": { @@ -3965,6 +3951,42 @@ "node": ">=8" } }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -4085,9 +4107,9 @@ } }, "node_modules/terser": { - "version": "5.31.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz", - "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==", + "version": "5.31.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.1.tgz", + "integrity": "sha512-37upzU1+viGvuFtBo9NPufCb9dwM0+l9hMxYyWfBA+fbwrPqNJAhbZ6W47bBFnZHKHTUBnMvi87434qq+qnxOg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -4287,6 +4309,28 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", @@ -4313,31 +4357,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/wrap-ansi/node_modules/strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", @@ -4355,9 +4374,9 @@ } }, "node_modules/ws": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", - "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "license": "MIT", "optional": true, "engines": { @@ -4397,6 +4416,28 @@ "xterm": "^5.0.0" } }, + "node_modules/xterm-readline/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/xterm-readline/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 93056f2df6c..a3ea53fa874 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.46", + "version": "0.4.47", "type": "module", "description": "PyScript", "module": "./index.js", @@ -22,6 +22,7 @@ "server": "npx static-handler --coi .", "build": "export ESLINT_USE_FLAT_CONFIG=true;npm run build:3rd-party && npm run build:stdlib && npm run build:plugins && npm run build:core && if [ -z \"$NO_MIN\" ]; then eslint src/ && npm run ts && npm run test:mpy; fi", "build:core": "rm -rf dist && rollup --config rollup/core.config.js && cp src/3rd-party/*.css dist/", + "build:flatted": "node rollup/flatted.cjs", "build:plugins": "node rollup/plugins.cjs", "build:stdlib": "node rollup/stdlib.cjs", "build:3rd-party": "node rollup/3rd-party.cjs", @@ -43,7 +44,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.12.14", + "polyscript": "^0.13.4", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -61,10 +62,11 @@ "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", - "bun": "^1.1.13", + "bun": "^1.1.14", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^9.4.0", + "eslint": "^9.5.0", + "flatted": "^3.3.1", "rollup": "^4.18.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", diff --git a/pyscript.core/rollup/flatted.cjs b/pyscript.core/rollup/flatted.cjs new file mode 100644 index 00000000000..22ae1d299a4 --- /dev/null +++ b/pyscript.core/rollup/flatted.cjs @@ -0,0 +1,17 @@ +const { writeFileSync, readFileSync } = require("node:fs"); +const { join } = require("node:path"); + +const flatted = "# https://www.npmjs.com/package/flatted\n\n"; +const source = join( + __dirname, + "..", + "node_modules", + "flatted", + "python", + "flatted.py", +); +const dest = join(__dirname, "..", "src", "stdlib", "pyscript", "flatted.py"); + +const clear = (str) => String(str).replace(/^#.*/gm, "").trimStart(); + +writeFileSync(dest, flatted + clear(readFileSync(source))); diff --git a/pyscript.core/src/stdlib/pyscript/__init__.py b/pyscript.core/src/stdlib/pyscript/__init__.py index f291e491607..518ede3bf9c 100644 --- a/pyscript.core/src/stdlib/pyscript/__init__.py +++ b/pyscript.core/src/stdlib/pyscript/__init__.py @@ -43,6 +43,7 @@ sync, window, ) +from pyscript.storage import Storage, storage from pyscript.websocket import WebSocket try: diff --git a/pyscript.core/src/stdlib/pyscript/flatted.py b/pyscript.core/src/stdlib/pyscript/flatted.py new file mode 100644 index 00000000000..1b72cdb506b --- /dev/null +++ b/pyscript.core/src/stdlib/pyscript/flatted.py @@ -0,0 +1,148 @@ +# https://www.npmjs.com/package/flatted + +import json as _json + + +class _Known: + def __init__(self): + self.key = [] + self.value = [] + + +class _String: + def __init__(self, value): + self.value = value + + +def _array_keys(value): + keys = [] + i = 0 + for _ in value: + keys.append(i) + i += 1 + return keys + + +def _object_keys(value): + keys = [] + for key in value: + keys.append(key) + return keys + + +def _is_array(value): + return isinstance(value, list) or isinstance(value, tuple) + + +def _is_object(value): + return isinstance(value, dict) + + +def _is_string(value): + return isinstance(value, str) + + +def _index(known, input, value): + input.append(value) + index = str(len(input) - 1) + known.key.append(value) + known.value.append(index) + return index + + +def _loop(keys, input, known, output): + for key in keys: + value = output[key] + if isinstance(value, _String): + _ref(key, input[int(value.value)], input, known, output) + + return output + + +def _ref(key, value, input, known, output): + if _is_array(value) and not value in known: + known.append(value) + value = _loop(_array_keys(value), input, known, value) + elif _is_object(value) and not value in known: + known.append(value) + value = _loop(_object_keys(value), input, known, value) + + output[key] = value + + +def _relate(known, input, value): + if _is_string(value) or _is_array(value) or _is_object(value): + try: + return known.value[known.key.index(value)] + except: + return _index(known, input, value) + + return value + + +def _transform(known, input, value): + if _is_array(value): + output = [] + for val in value: + output.append(_relate(known, input, val)) + return output + + if _is_object(value): + obj = {} + for key in value: + obj[key] = _relate(known, input, value[key]) + return obj + + return value + + +def _wrap(value): + if _is_string(value): + return _String(value) + + if _is_array(value): + i = 0 + for val in value: + value[i] = _wrap(val) + i += 1 + + elif _is_object(value): + for key in value: + value[key] = _wrap(value[key]) + + return value + + +def parse(value, *args, **kwargs): + json = _json.loads(value, *args, **kwargs) + wrapped = [] + for value in json: + wrapped.append(_wrap(value)) + + input = [] + for value in wrapped: + if isinstance(value, _String): + input.append(value.value) + else: + input.append(value) + + value = input[0] + + if _is_array(value): + return _loop(_array_keys(value), input, [value], value) + + if _is_object(value): + return _loop(_object_keys(value), input, [value], value) + + return value + + +def stringify(value, *args, **kwargs): + known = _Known() + input = [] + output = [] + i = int(_index(known, input, value)) + while i < len(input): + output.append(_transform(known, input, input[i])) + i += 1 + return _json.dumps(output, *args, **kwargs) diff --git a/pyscript.core/src/stdlib/pyscript/storage.py b/pyscript.core/src/stdlib/pyscript/storage.py new file mode 100644 index 00000000000..943aee183b9 --- /dev/null +++ b/pyscript.core/src/stdlib/pyscript/storage.py @@ -0,0 +1,60 @@ +from polyscript import storage as _storage +from pyscript.flatted import parse as _parse +from pyscript.flatted import stringify as _stringify + + +# convert a Python value into an IndexedDB compatible entry +def _to_idb(value): + if value is None: + return _stringify(["null", 0]) + if isinstance(value, (bool, float, int, str, list, dict, tuple)): + return _stringify(["generic", value]) + if isinstance(value, bytearray): + return _stringify(["bytearray", [v for v in value]]) + if isinstance(value, memoryview): + return _stringify(["memoryview", [v for v in value]]) + raise TypeError(f"Unexpected value: {value}") + + +# convert an IndexedDB compatible entry into a Python value +def _from_idb(value): + ( + kind, + result, + ) = _parse(value) + if kind == "null": + return None + if kind == "generic": + return result + if kind == "bytearray": + return bytearray(result) + if kind == "memoryview": + return memoryview(bytearray(result)) + return value + + +class Storage(dict): + def __init__(self, store): + super().__init__({k: _from_idb(v) for k, v in store.entries()}) + self.__store__ = store + + def __delitem__(self, attr): + self.__store__.delete(attr) + super().__delitem__(attr) + + def __setitem__(self, attr, value): + self.__store__.set(attr, _to_idb(value)) + super().__setitem__(attr, value) + + def clear(self): + self.__store__.clear() + super().clear() + + async def sync(self): + await self.__store__.sync() + + +async def storage(name="", storage_class=Storage): + if not name: + raise ValueError("The storage name must be defined") + return storage_class(await _storage(f"@pyscript/{name}")) diff --git a/pyscript.core/test/mpy.spec.js b/pyscript.core/test/mpy.spec.js index fe94019c4f5..7805eb456fb 100644 --- a/pyscript.core/test/mpy.spec.js +++ b/pyscript.core/test/mpy.spec.js @@ -88,3 +88,8 @@ test('MicroPython + Pyodide ffi', async ({ page }) => { await page.goto('http://localhost:8080/test/ffi.html'); await page.waitForSelector('html.mpy.py'); }); + +test('MicroPython + Storage', async ({ page }) => { + await page.goto('http://localhost:8080/test/storage.html'); + await page.waitForSelector('html.ok'); +}); diff --git a/pyscript.core/test/storage.html b/pyscript.core/test/storage.html new file mode 100644 index 00000000000..de602e3fb39 --- /dev/null +++ b/pyscript.core/test/storage.html @@ -0,0 +1,46 @@ + + + + + + @pyscript/core storage + + + + + + + diff --git a/pyscript.core/types/stdlib/pyscript.d.ts b/pyscript.core/types/stdlib/pyscript.d.ts index 613e822c26c..fb69b323649 100644 --- a/pyscript.core/types/stdlib/pyscript.d.ts +++ b/pyscript.core/types/stdlib/pyscript.d.ts @@ -5,7 +5,9 @@ declare namespace _default { "event_handling.py": string; "fetch.py": string; "ffi.py": string; + "flatted.py": string; "magic_js.py": string; + "storage.py": string; "util.py": string; web: { "__init__.py": string; From 15c19aa7082d53218e6ee5af67b500af79ce6537 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Wed, 19 Jun 2024 17:56:22 +0200 Subject: [PATCH 067/179] Updated Polyscript with latest MicroPython (#2103) --- pyscript.core/package-lock.json | 12 ++++++------ pyscript.core/package.json | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 048475c54c8..c6663652657 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.4.47", + "version": "0.4.48", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.47", + "version": "0.4.48", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.13.4", + "polyscript": "^0.13.5", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -2918,9 +2918,9 @@ } }, "node_modules/polyscript": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.13.4.tgz", - "integrity": "sha512-kpr2GDq4FLswasiX9QETez3hXTHglzKyNC7gzmH1+dTHEh/GYsa7rbbv0pLr8JWlTm6Rs13fHB8qnaQ0DweCVg==", + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.13.5.tgz", + "integrity": "sha512-PwXWnhLbOMtvZWFIN271JhaN7KnxESaMtv9Rcdrq1TKTCMnkz9idvYb3Od1iumBJlr49lLlwyUKeGb423rFR4w==", "license": "APACHE-2.0", "dependencies": { "@ungap/structured-clone": "^1.2.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index a3ea53fa874..4889f05f72c 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.47", + "version": "0.4.48", "type": "module", "description": "PyScript", "module": "./index.js", @@ -44,7 +44,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.13.4", + "polyscript": "^0.13.5", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" From 4b90ebdef557452f27a7b7c3f9fb0a9f868db7e1 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Fri, 21 Jun 2024 14:49:20 +0200 Subject: [PATCH 068/179] Bring back pyweb as it was (#2105) --- pyscript.core/package-lock.json | 4 +- pyscript.core/package.json | 2 +- .../src/stdlib/pyscript/event_handling.py | 9 +- pyscript.core/src/stdlib/pyweb/__init__.py | 2 + pyscript.core/src/stdlib/pyweb/media.py | 95 ++ pyscript.core/src/stdlib/pyweb/pydom.py | 569 +++++++++++ pyscript.core/src/stdlib/pyweb/ui/__init__.py | 1 + pyscript.core/src/stdlib/pyweb/ui/elements.py | 947 ++++++++++++++++++ pyscript.core/test/pydom.py | 11 +- .../test/pyscript_dom/tests/test_dom.py | 119 ++- pyscript.core/tests/integration/test_pyweb.py | 7 +- pyscript.core/types/stdlib/pyscript.d.ts | 9 + 12 files changed, 1704 insertions(+), 71 deletions(-) create mode 100644 pyscript.core/src/stdlib/pyweb/__init__.py create mode 100644 pyscript.core/src/stdlib/pyweb/media.py create mode 100644 pyscript.core/src/stdlib/pyweb/pydom.py create mode 100644 pyscript.core/src/stdlib/pyweb/ui/__init__.py create mode 100644 pyscript.core/src/stdlib/pyweb/ui/elements.py diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index c6663652657..472a23558b5 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.48", + "version": "0.4.50", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.48", + "version": "0.4.50", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 4889f05f72c..402f277194d 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.48", + "version": "0.4.50", "type": "module", "description": "PyScript", "module": "./index.js", diff --git a/pyscript.core/src/stdlib/pyscript/event_handling.py b/pyscript.core/src/stdlib/pyscript/event_handling.py index 5e4438c671e..6c2339402eb 100644 --- a/pyscript.core/src/stdlib/pyscript/event_handling.py +++ b/pyscript.core/src/stdlib/pyscript/event_handling.py @@ -19,17 +19,16 @@ def when(event_type=None, selector=None): """ def decorator(func): - - from pyscript.web.elements import Element, ElementCollection - if isinstance(selector, str): elements = document.querySelectorAll(selector) else: # TODO: This is a hack that will be removed when pyscript becomes a package # and we can better manage the imports without circular dependencies - if isinstance(selector, Element): + from pyweb import pydom + + if isinstance(selector, pydom.Element): elements = [selector._js] - elif isinstance(selector, ElementCollection): + elif isinstance(selector, pydom.ElementCollection): elements = [el._js for el in selector] else: raise ValueError( diff --git a/pyscript.core/src/stdlib/pyweb/__init__.py b/pyscript.core/src/stdlib/pyweb/__init__.py new file mode 100644 index 00000000000..80843cf2da0 --- /dev/null +++ b/pyscript.core/src/stdlib/pyweb/__init__.py @@ -0,0 +1,2 @@ +from .pydom import JSProperty +from .pydom import dom as pydom diff --git a/pyscript.core/src/stdlib/pyweb/media.py b/pyscript.core/src/stdlib/pyweb/media.py new file mode 100644 index 00000000000..9f0ffcda559 --- /dev/null +++ b/pyscript.core/src/stdlib/pyweb/media.py @@ -0,0 +1,95 @@ +from pyodide.ffi import to_js +from pyscript import window + + +class Device: + """Device represents a media input or output device, such as a microphone, + camera, or headset. + """ + + def __init__(self, device): + self._js = device + + @property + def id(self): + return self._js.deviceId + + @property + def group(self): + return self._js.groupId + + @property + def kind(self): + return self._js.kind + + @property + def label(self): + return self._js.label + + def __getitem__(self, key): + return getattr(self, key) + + @classmethod + async def load(cls, audio=False, video=True): + """Load the device stream.""" + options = window.Object.new() + options.audio = audio + if isinstance(video, bool): + options.video = video + else: + # TODO: Think this can be simplified but need to check it on the pyodide side + + # TODO: this is pyodide specific. shouldn't be! + options.video = window.Object.new() + for k in video: + setattr( + options.video, + k, + to_js(video[k], dict_converter=window.Object.fromEntries), + ) + + stream = await window.navigator.mediaDevices.getUserMedia(options) + return stream + + async def get_stream(self): + key = self.kind.replace("input", "").replace("output", "") + options = {key: {"deviceId": {"exact": self.id}}} + + return await self.load(**options) + + +async def list_devices() -> list[dict]: + """ + Return the list of the currently available media input and output devices, + such as microphones, cameras, headsets, and so forth. + + Output: + + list(dict) - list of dictionaries representing the available media devices. + Each dictionary has the following keys: + * deviceId: a string that is an identifier for the represented device + that is persisted across sessions. It is un-guessable by other + applications and unique to the origin of the calling application. + It is reset when the user clears cookies (for Private Browsing, a + different identifier is used that is not persisted across sessions). + + * groupId: a string that is a group identifier. Two devices have the same + group identifier if they belong to the same physical device — for + example a monitor with both a built-in camera and a microphone. + + * kind: an enumerated value that is either "videoinput", "audioinput" + or "audiooutput". + + * label: a string describing this device (for example "External USB + Webcam"). + + Note: the returned list will omit any devices that are blocked by the document + Permission Policy: microphone, camera, speaker-selection (for output devices), + and so on. Access to particular non-default devices is also gated by the + Permissions API, and the list will omit devices for which the user has not + granted explicit permission. + """ + # https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices + return [ + Device(obj) for obj in await window.navigator.mediaDevices.enumerateDevices() + ] diff --git a/pyscript.core/src/stdlib/pyweb/pydom.py b/pyscript.core/src/stdlib/pyweb/pydom.py new file mode 100644 index 00000000000..0ba41b25260 --- /dev/null +++ b/pyscript.core/src/stdlib/pyweb/pydom.py @@ -0,0 +1,569 @@ +import inspect + +try: + from typing import Any +except ImportError: + Any = "Any" + +try: + import warnings +except ImportError: + # TODO: For now it probably means we are in MicroPython. We should figure + # out the "right" way to handle this. For now we just ignore the warning + # and logging to console + class warnings: + @staticmethod + def warn(*args, **kwargs): + print("WARNING: ", *args, **kwargs) + + +try: + from functools import cached_property +except ImportError: + # TODO: same comment about micropython as above + cached_property = property + +try: + from pyodide.ffi import JsProxy +except ImportError: + # TODO: same comment about micropython as above + def JsProxy(obj): + return obj + + +from pyscript import display, document, window + +alert = window.alert + + +class JSProperty: + """JS property descriptor that directly maps to the property with the same + name in the underlying JS component.""" + + def __init__(self, name: str, allow_nones: bool = False): + self.name = name + self.allow_nones = allow_nones + + def __get__(self, obj, objtype=None): + return getattr(obj._js, self.name) + + def __set__(self, obj, value): + if not self.allow_nones and value is None: + return + setattr(obj._js, self.name, value) + + +class BaseElement: + def __init__(self, js_element): + self._js = js_element + self._parent = None + self.style = StyleProxy(self) + self._proxies = {} + + def __eq__(self, obj): + """Check if the element is the same as the other element by comparing + the underlying JS element""" + return isinstance(obj, BaseElement) and obj._js == self._js + + @property + def parent(self): + if self._parent: + return self._parent + + if self._js.parentElement: + self._parent = self.__class__(self._js.parentElement) + + return self._parent + + @property + def __class(self): + return self.__class__ if self.__class__ != PyDom else Element + + def create(self, type_, is_child=True, classes=None, html=None, label=None): + js_el = document.createElement(type_) + element = self.__class(js_el) + + if classes: + for class_ in classes: + element.add_class(class_) + + if html is not None: + element.html = html + + if label is not None: + element.label = label + + if is_child: + self.append(element) + + return element + + def find(self, selector): + """Return an ElementCollection representing all the child elements that + match the specified selector. + + Args: + selector (str): A string containing a selector expression + + Returns: + ElementCollection: A collection of elements matching the selector + """ + elements = self._js.querySelectorAll(selector) + if not elements: + return None + return ElementCollection([Element(el) for el in elements]) + + +class Element(BaseElement): + @property + def children(self): + return [self.__class__(el) for el in self._js.children] + + def append(self, child): + # TODO: this is Pyodide specific for now!!!!!! + # if we get passed a JSProxy Element directly we just map it to the + # higher level Python element + if inspect.isclass(JsProxy) and isinstance(child, JsProxy): + return self.append(Element(child)) + + elif isinstance(child, Element): + self._js.appendChild(child._js) + + return child + + elif isinstance(child, ElementCollection): + for el in child: + self.append(el) + + # -------- Pythonic Interface to Element -------- # + @property + def html(self): + return self._js.innerHTML + + @html.setter + def html(self, value): + self._js.innerHTML = value + + @property + def text(self): + return self._js.textContent + + @text.setter + def text(self, value): + self._js.textContent = value + + @property + def content(self): + # TODO: This breaks with with standard template elements. Define how to best + # handle this specifica use case. Just not support for now? + if self._js.tagName == "TEMPLATE": + warnings.warn( + "Content attribute not supported for template elements.", stacklevel=2 + ) + return None + return self._js.innerHTML + + @content.setter + def content(self, value): + # TODO: (same comment as above) + if self._js.tagName == "TEMPLATE": + warnings.warn( + "Content attribute not supported for template elements.", stacklevel=2 + ) + return + + display(value, target=self.id) + + @property + def id(self): + return self._js.id + + @id.setter + def id(self, value): + self._js.id = value + + @property + def options(self): + if "options" in self._proxies: + return self._proxies["options"] + + if not self._js.tagName.lower() in {"select", "datalist", "optgroup"}: + raise AttributeError( + f"Element {self._js.tagName} has no options attribute." + ) + self._proxies["options"] = OptionsProxy(self) + return self._proxies["options"] + + @property + def value(self): + return self._js.value + + @value.setter + def value(self, value): + # in order to avoid confusion to the user, we don't allow setting the + # value of elements that don't have a value attribute + if not hasattr(self._js, "value"): + raise AttributeError( + f"Element {self._js.tagName} has no value attribute. If you want to " + "force a value attribute, set it directly using the `_js.value = ` " + "javascript API attribute instead." + ) + self._js.value = value + + @property + def selected(self): + return self._js.selected + + @selected.setter + def selected(self, value): + # in order to avoid confusion to the user, we don't allow setting the + # value of elements that don't have a value attribute + if not hasattr(self._js, "selected"): + raise AttributeError( + f"Element {self._js.tagName} has no value attribute. If you want to " + "force a value attribute, set it directly using the `_js.value = ` " + "javascript API attribute instead." + ) + self._js.selected = value + + def clone(self, new_id=None): + clone = Element(self._js.cloneNode(True)) + clone.id = new_id + + return clone + + def remove_class(self, classname): + classList = self._js.classList + if isinstance(classname, list): + classList.remove(*classname) + else: + classList.remove(classname) + return self + + def add_class(self, classname): + classList = self._js.classList + if isinstance(classname, list): + classList.add(*classname) + else: + self._js.classList.add(classname) + return self + + @property + def classes(self): + classes = self._js.classList.values() + return [x for x in classes] + + def show_me(self): + self._js.scrollIntoView() + + def snap( + self, + to: BaseElement | str = None, + width: int | None = None, + height: int | None = None, + ): + """ + Captures a snapshot of a video element. (Only available for video elements) + + Inputs: + + * to: element where to save the snapshot of the video frame to + * width: width of the image + * height: height of the image + + Output: + (Element) canvas element where the video frame snapshot was drawn into + """ + if self._js.tagName != "VIDEO": + raise AttributeError("Snap method is only available for video Elements") + + if to is None: + canvas = self.create("canvas") + if width is None: + width = self._js.width + if height is None: + height = self._js.height + canvas._js.width = width + canvas._js.height = height + + elif isinstance(to, Element): + if to._js.tagName != "CANVAS": + raise TypeError("Element to snap to must a canvas.") + canvas = to + elif getattr(to, "tagName", "") == "CANVAS": + canvas = Element(to) + elif isinstance(to, str): + canvas = pydom[to][0] + if canvas._js.tagName != "CANVAS": + raise TypeError("Element to snap to must a be canvas.") + + canvas.draw(self, width, height) + + return canvas + + def download(self, filename: str = "snapped.png") -> None: + """Download the current element (only available for canvas elements) with the filename + provided in input. + + Inputs: + * filename (str): name of the file being downloaded + + Output: + None + """ + if self._js.tagName != "CANVAS": + raise AttributeError( + "The download method is only available for canvas Elements" + ) + + link = self.create("a") + link._js.download = filename + link._js.href = self._js.toDataURL() + link._js.click() + + def draw(self, what, width, height): + """Draw `what` on the current element (only available for canvas elements). + + Inputs: + + * what (canvas image source): An element to draw into the context. The specification permits any canvas + image source, specifically, an HTMLImageElement, an SVGImageElement, an HTMLVideoElement, + an HTMLCanvasElement, an ImageBitmap, an OffscreenCanvas, or a VideoFrame. + """ + if self._js.tagName != "CANVAS": + raise AttributeError( + "The draw method is only available for canvas Elements" + ) + + if isinstance(what, Element): + what = what._js + + # https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage + self._js.getContext("2d").drawImage(what, 0, 0, width, height) + + +class OptionsProxy: + """This class represents the options of a select element. It + allows to access to add and remove options by using the `add` and `remove` methods. + """ + + def __init__(self, element: Element) -> None: + self._element = element + if self._element._js.tagName.lower() != "select": + raise AttributeError( + f"Element {self._element._js.tagName} has no options attribute." + ) + + def add( + self, + value: Any = None, + html: str = None, + text: str = None, + before: Element | int = None, + **kws, + ) -> None: + """Add a new option to the select element""" + # create the option element and set the attributes + option = document.createElement("option") + if value is not None: + kws["value"] = value + if html is not None: + option.innerHTML = html + if text is not None: + kws["text"] = text + + for key, value in kws.items(): + option.setAttribute(key, value) + + if before: + if isinstance(before, Element): + before = before._js + + self._element._js.add(option, before) + + def remove(self, item: int) -> None: + """Remove the option at the specified index""" + self._element._js.remove(item) + + def clear(self) -> None: + """Remove all the options""" + for i in range(len(self)): + self.remove(0) + + @property + def options(self): + """Return the list of options""" + return [Element(opt) for opt in self._element._js.options] + + @property + def selected(self): + """Return the selected option""" + return self.options[self._element._js.selectedIndex] + + def __iter__(self): + yield from self.options + + def __len__(self): + return len(self.options) + + def __repr__(self): + return f"{self.__class__.__name__} (length: {len(self)}) {self.options}" + + def __getitem__(self, key): + return self.options[key] + + +class StyleProxy: # (dict): + def __init__(self, element: Element) -> None: + self._element = element + + @cached_property + def _style(self): + return self._element._js.style + + def __getitem__(self, key): + return self._style.getPropertyValue(key) + + def __setitem__(self, key, value): + self._style.setProperty(key, value) + + def remove(self, key): + self._style.removeProperty(key) + + def set(self, **kws): + for k, v in kws.items(): + self._element._js.style.setProperty(k, v) + + # CSS Properties + # Reference: https://github.com/microsoft/TypeScript/blob/main/src/lib/dom.generated.d.ts#L3799C1-L5005C2 + # Following prperties automatically generated from the above reference using + # tools/codegen_css_proxy.py + @property + def visible(self): + return self._element._js.style.visibility + + @visible.setter + def visible(self, value): + self._element._js.style.visibility = value + + +class StyleCollection: + def __init__(self, collection: "ElementCollection") -> None: + self._collection = collection + + def __get__(self, obj, objtype=None): + return obj._get_attribute("style") + + def __getitem__(self, key): + return self._collection._get_attribute("style")[key] + + def __setitem__(self, key, value): + for element in self._collection._elements: + element.style[key] = value + + def remove(self, key): + for element in self._collection._elements: + element.style.remove(key) + + +class ElementCollection: + def __init__(self, elements: [Element]) -> None: + self._elements = elements + self.style = StyleCollection(self) + + def __getitem__(self, key): + # If it's an integer we use it to access the elements in the collection + if isinstance(key, int): + return self._elements[key] + # If it's a slice we use it to support slice operations over the elements + # in the collection + elif isinstance(key, slice): + return ElementCollection(self._elements[key]) + + # If it's anything else (basically a string) we use it as a selector + # TODO: Write tests! + elements = self._element.querySelectorAll(key) + return ElementCollection([Element(el) for el in elements]) + + def __len__(self): + return len(self._elements) + + def __eq__(self, obj): + """Check if the element is the same as the other element by comparing + the underlying JS element""" + return isinstance(obj, ElementCollection) and obj._elements == self._elements + + def _get_attribute(self, attr, index=None): + if index is None: + return [getattr(el, attr) for el in self._elements] + + # As JQuery, when getting an attr, only return it for the first element + return getattr(self._elements[index], attr) + + def _set_attribute(self, attr, value): + for el in self._elements: + setattr(el, attr, value) + + @property + def html(self): + return self._get_attribute("html") + + @html.setter + def html(self, value): + self._set_attribute("html", value) + + @property + def value(self): + return self._get_attribute("value") + + @value.setter + def value(self, value): + self._set_attribute("value", value) + + @property + def children(self): + return self._elements + + def __iter__(self): + yield from self._elements + + def __repr__(self): + return f"{self.__class__.__name__} (length: {len(self._elements)}) {self._elements}" + + +class DomScope: + def __getattr__(self, __name: str): + element = document[f"#{__name}"] + if element: + return element[0] + + +class PyDom(BaseElement): + # Add objects we want to expose to the DOM namespace since this class instance is being + # remapped as "the module" itself + BaseElement = BaseElement + Element = Element + ElementCollection = ElementCollection + + def __init__(self): + # PyDom is a special case of BaseElement where we don't want to create a new JS element + # and it really doesn't have a need for styleproxy or parent to to call to __init__ + # (which actually fails in MP for some reason) + self._js = document + self._parent = None + self._proxies = {} + self.ids = DomScope() + self.body = Element(document.body) + self.head = Element(document.head) + + def create(self, type_, classes=None, html=None): + return super().create(type_, is_child=False, classes=classes, html=html) + + def __getitem__(self, key): + elements = self._js.querySelectorAll(key) + if not elements: + return None + return ElementCollection([Element(el) for el in elements]) + + +dom = PyDom() diff --git a/pyscript.core/src/stdlib/pyweb/ui/__init__.py b/pyscript.core/src/stdlib/pyweb/ui/__init__.py new file mode 100644 index 00000000000..a50ec40cefb --- /dev/null +++ b/pyscript.core/src/stdlib/pyweb/ui/__init__.py @@ -0,0 +1 @@ +from . import elements diff --git a/pyscript.core/src/stdlib/pyweb/ui/elements.py b/pyscript.core/src/stdlib/pyweb/ui/elements.py new file mode 100644 index 00000000000..540e8f59f33 --- /dev/null +++ b/pyscript.core/src/stdlib/pyweb/ui/elements.py @@ -0,0 +1,947 @@ +import inspect +import sys + +from pyscript import document, when, window +from pyweb import JSProperty, pydom + +#: A flag to show if MicroPython is the current Python interpreter. +is_micropython = "MicroPython" in sys.version + + +def getmembers_static(cls): + """Cross-interpreter implementation of inspect.getmembers_static.""" + + if is_micropython: # pragma: no cover + return [(name, getattr(cls, name)) for name, _ in inspect.getmembers(cls)] + + return inspect.getmembers_static(cls) + + +class ElementBase(pydom.Element): + tag = "div" + + # GLOBAL ATTRIBUTES + # These are attribute that all elements have (this list is a subset of the official one) + # We are trying to capture the most used ones + accesskey = JSProperty("accesskey") + autofocus = JSProperty("autofocus") + autocapitalize = JSProperty("autocapitalize") + className = JSProperty("className") + contenteditable = JSProperty("contenteditable") + draggable = JSProperty("draggable") + enterkeyhint = JSProperty("enterkeyhint") + hidden = JSProperty("hidden") + id = JSProperty("id") + lang = JSProperty("lang") + nonce = JSProperty("nonce") + part = JSProperty("part") + popover = JSProperty("popover") + slot = JSProperty("slot") + spellcheck = JSProperty("spellcheck") + tabindex = JSProperty("tabindex") + title = JSProperty("title") + translate = JSProperty("translate") + virtualkeyboardpolicy = JSProperty("virtualkeyboardpolicy") + + def __init__(self, style=None, **kwargs): + super().__init__(document.createElement(self.tag)) + + # set all the style properties provided in input + if isinstance(style, dict): + for key, value in style.items(): + self.style[key] = value + elif style is None: + pass + else: + raise ValueError( + f"Style should be a dictionary, received {style} (type {type(style)}) instead." + ) + + # IMPORTANT!!! This is used to auto-harvest all input arguments and set them as properties + self._init_properties(**kwargs) + + def _init_properties(self, **kwargs): + """Set all the properties (of type JSProperties) provided in input as properties + of the class instance. + + Args: + **kwargs: The properties to set + """ + # Look at all the properties of the class and see if they were provided in kwargs + for attr_name, attr in getmembers_static(self.__class__): + # For each one, actually check if it is a property of the class and set it + if isinstance(attr, JSProperty) and attr_name in kwargs: + try: + setattr(self, attr_name, kwargs[attr_name]) + except Exception as e: + print(f"Error setting {attr_name} to {kwargs[attr_name]}: {e}") + raise + + +class TextElementBase(ElementBase): + def __init__(self, content=None, style=None, **kwargs): + super().__init__(style=style, **kwargs) + + # If it's an element, append the element + if isinstance(content, pydom.Element): + self.append(content) + # If it's a list of elements + elif isinstance(content, list): + for item in content: + self.append(item) + # If the content wasn't set just ignore + elif content is None: + pass + else: + # Otherwise, set content as the html of the element + self.html = content + + +# IMPORTANT: For all HTML components defined below, we are not mapping all +# available attributes, just the global and the most common ones. +# If you need to access a specific attribute, you can always use the `_js.` +class a(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a""" + + tag = "a" + + download = JSProperty("download") + href = JSProperty("href") + referrerpolicy = JSProperty("referrerpolicy") + rel = JSProperty("rel") + target = JSProperty("target") + type = JSProperty("type") + + +class abbr(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/abbr""" + + tag = "abbr" + + +class address(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/address""" + + tag = "address" + + +class area(ElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area""" + + tag = "area" + + alt = JSProperty("alt") + coords = JSProperty("coords") + download = JSProperty("download") + href = JSProperty("href") + ping = JSProperty("ping") + referrerpolicy = JSProperty("referrerpolicy") + rel = JSProperty("rel") + shape = JSProperty("shape") + target = JSProperty("target") + + +class article(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article""" + + tag = "article" + + +class aside(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside""" + + tag = "aside" + + +class audio(ElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio""" + + tag = "audio" + + autoplay = JSProperty("autoplay") + controls = JSProperty("controls") + controlslist = JSProperty("controlslist") + crossorigin = JSProperty("crossorigin") + disableremoteplayback = JSProperty("disableremoteplayback") + loop = JSProperty("loop") + muted = JSProperty("muted") + preload = JSProperty("preload") + src = JSProperty("src") + + +class b(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/b""" + + tag = "b" + + +class blockquote(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote""" + + tag = "blockquote" + + cite = JSProperty("cite") + + +class br(ElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br""" + + tag = "br" + + +class button(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button""" + + tag = "button" + + autofocus = JSProperty("autofocus") + disabled = JSProperty("disabled") + form = JSProperty("form") + formaction = JSProperty("formaction") + formenctype = JSProperty("formenctype") + formmethod = JSProperty("formmethod") + formnovalidate = JSProperty("formnovalidate") + formtarget = JSProperty("formtarget") + name = JSProperty("name") + type = JSProperty("type") + value = JSProperty("value") + + +class canvas(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas""" + + tag = "canvas" + + height = JSProperty("height") + width = JSProperty("width") + + +class caption(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption""" + + tag = "caption" + + +class cite(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite""" + + tag = "cite" + + +class code(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code""" + + tag = "code" + + +class data(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/data""" + + tag = "data" + + value = JSProperty("value") + + +class datalist(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist""" + + tag = "datalist" + + +class dd(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dd""" + + tag = "dd" + + +class del_(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del""" + + tag = "del" + + cite = JSProperty("cite") + datetime = JSProperty("datetime") + + +class details(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details""" + + tag = "details" + + open = JSProperty("open") + + +class dialog(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog""" + + tag = "dialog" + + open = JSProperty("open") + + +class div(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div""" + + tag = "div" + + +class dl(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl""" + + tag = "dl" + + value = JSProperty("value") + + +class dt(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dt""" + + tag = "dt" + + +class em(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em""" + + tag = "em" + + +class embed(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/embed""" + + tag = "embed" + + height = JSProperty("height") + src = JSProperty("src") + type = JSProperty("type") + width = JSProperty("width") + + +class fieldset(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset""" + + tag = "fieldset" + + disabled = JSProperty("disabled") + form = JSProperty("form") + name = JSProperty("name") + + +class figcaption(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figcaption""" + + tag = "figcaption" + + +class figure(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure""" + + tag = "figure" + + +class footer(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer""" + + tag = "footer" + + +class form(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form""" + + tag = "form" + + accept_charset = JSProperty("accept-charset") + action = JSProperty("action") + autocapitalize = JSProperty("autocapitalize") + autocomplete = JSProperty("autocomplete") + enctype = JSProperty("enctype") + name = JSProperty("name") + method = JSProperty("method") + nonvalidate = JSProperty("nonvalidate") + rel = JSProperty("rel") + target = JSProperty("target") + + +class h1(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h1""" + + tag = "h1" + + +class h2(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h2""" + + tag = "h2" + + +class h3(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h3""" + + tag = "h3" + + +class h4(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h4""" + + tag = "h4" + + +class h5(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h5""" + + tag = "h5" + + +class h6(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/h6""" + + tag = "h6" + + +class header(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header""" + + tag = "header" + + +class hgroup(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hgroup""" + + tag = "hgroup" + + +class hr(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hr""" + + tag = "hr" + + +class i(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/i""" + + tag = "i" + + +class iframe(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe""" + + tag = "iframe" + + allow = JSProperty("allow") + allowfullscreen = JSProperty("allowfullscreen") + height = JSProperty("height") + loading = JSProperty("loading") + name = JSProperty("name") + referrerpolicy = JSProperty("referrerpolicy") + sandbox = JSProperty("sandbox") + src = JSProperty("src") + srcdoc = JSProperty("srcdoc") + width = JSProperty("width") + + +class img(ElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img""" + + tag = "img" + + alt = JSProperty("alt") + crossorigin = JSProperty("crossorigin") + decoding = JSProperty("decoding") + fetchpriority = JSProperty("fetchpriority") + height = JSProperty("height") + ismap = JSProperty("ismap") + loading = JSProperty("loading") + referrerpolicy = JSProperty("referrerpolicy") + sizes = JSProperty("sizes") + src = JSProperty("src") + width = JSProperty("width") + + +# NOTE: Input is a reserved keyword in Python, so we use input_ instead +class input_(ElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input""" + + tag = "input" + + accept = JSProperty("accept") + alt = JSProperty("alt") + autofocus = JSProperty("autofocus") + capture = JSProperty("capture") + checked = JSProperty("checked") + dirname = JSProperty("dirname") + disabled = JSProperty("disabled") + form = JSProperty("form") + formaction = JSProperty("formaction") + formenctype = JSProperty("formenctype") + formmethod = JSProperty("formmethod") + formnovalidate = JSProperty("formnovalidate") + formtarget = JSProperty("formtarget") + height = JSProperty("height") + list = JSProperty("list") + max = JSProperty("max") + maxlength = JSProperty("maxlength") + min = JSProperty("min") + minlength = JSProperty("minlength") + multiple = JSProperty("multiple") + name = JSProperty("name") + pattern = JSProperty("pattern") + placeholder = JSProperty("placeholder") + popovertarget = JSProperty("popovertarget") + popovertargetaction = JSProperty("popovertargetaction") + readonly = JSProperty("readonly") + required = JSProperty("required") + size = JSProperty("size") + src = JSProperty("src") + step = JSProperty("step") + type = JSProperty("type") + value = JSProperty("value") + width = JSProperty("width") + + +class ins(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins""" + + tag = "ins" + + cite = JSProperty("cite") + datetime = JSProperty("datetime") + + +class kbd(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/kbd""" + + tag = "kbd" + + +class label(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label""" + + tag = "label" + + for_ = JSProperty("for") + + +class legend(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend""" + + tag = "legend" + + +class li(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li""" + + tag = "li" + + value = JSProperty("value") + + +class link(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link""" + + tag = "link" + + as_ = JSProperty("as") + crossorigin = JSProperty("crossorigin") + disabled = JSProperty("disabled") + fetchpriority = JSProperty("fetchpriority") + href = JSProperty("href") + imagesizes = JSProperty("imagesizes") + imagesrcset = JSProperty("imagesrcset") + integrity = JSProperty("integrity") + media = JSProperty("media") + rel = JSProperty("rel") + referrerpolicy = JSProperty("referrerpolicy") + sizes = JSProperty("sizes") + title = JSProperty("title") + type = JSProperty("type") + + +class main(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main""" + + tag = "main" + + +class map_(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/map""" + + tag = "map" + + name = JSProperty("name") + + +class mark(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark""" + + tag = "mark" + + +class menu(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menu""" + + tag = "menu" + + +class meter(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter""" + + tag = "meter" + + form = JSProperty("form") + high = JSProperty("high") + low = JSProperty("low") + max = JSProperty("max") + min = JSProperty("min") + optimum = JSProperty("optimum") + value = JSProperty("value") + + +class nav(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav""" + + tag = "nav" + + +class object_(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object""" + + tag = "object" + + data = JSProperty("data") + form = JSProperty("form") + height = JSProperty("height") + name = JSProperty("name") + type = JSProperty("type") + usemap = JSProperty("usemap") + width = JSProperty("width") + + +class ol(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol""" + + tag = "ol" + + reversed = JSProperty("reversed") + start = JSProperty("start") + type = JSProperty("type") + + +class optgroup(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup""" + + tag = "optgroup" + + disabled = JSProperty("disabled") + label = JSProperty("label") + + +class option(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option""" + + tag = "option" + + disabled = JSProperty("value") + label = JSProperty("label") + selected = JSProperty("selected") + value = JSProperty("value") + + +class output(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output""" + + tag = "output" + + for_ = JSProperty("for") + form = JSProperty("form") + name = JSProperty("name") + + +class p(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/p""" + + tag = "p" + + +class picture(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture""" + + tag = "picture" + + +class pre(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre""" + + tag = "pre" + + +class progress(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress""" + + tag = "progress" + + max = JSProperty("max") + value = JSProperty("value") + + +class q(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q""" + + tag = "q" + + cite = JSProperty("cite") + + +class s(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s""" + + tag = "s" + + +class script(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script""" + + tag = "script" + + # Let's add async manually since it's a reserved keyword in Python + async_ = JSProperty("async") + blocking = JSProperty("blocking") + crossorigin = JSProperty("crossorigin") + defer = JSProperty("defer") + fetchpriority = JSProperty("fetchpriority") + integrity = JSProperty("integrity") + nomodule = JSProperty("nomodule") + nonce = JSProperty("nonce") + referrerpolicy = JSProperty("referrerpolicy") + src = JSProperty("src") + type = JSProperty("type") + + +class section(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section""" + + tag = "section" + + +class select(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select""" + + tag = "select" + + +class small(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small""" + + tag = "small" + + +class source(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/source""" + + tag = "source" + + media = JSProperty("media") + sizes = JSProperty("sizes") + src = JSProperty("src") + srcset = JSProperty("srcset") + type = JSProperty("type") + + +class span(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span""" + + tag = "span" + + +class strong(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong""" + + tag = "strong" + + +class style(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style""" + + tag = "style" + + blocking = JSProperty("blocking") + media = JSProperty("media") + nonce = JSProperty("nonce") + title = JSProperty("title") + + +class sub(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub""" + + tag = "sub" + + +class summary(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary""" + + tag = "summary" + + +class sup(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup""" + + tag = "sup" + + +class table(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table""" + + tag = "table" + + +class tbody(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tbody""" + + tag = "tbody" + + +class td(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td""" + + tag = "td" + + colspan = JSProperty("colspan") + headers = JSProperty("headers") + rowspan = JSProperty("rowspan") + + +class template(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template""" + + tag = "template" + + shadowrootmode = JSProperty("shadowrootmode") + + +class textarea(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea""" + + tag = "textarea" + + autocapitalize = JSProperty("autocapitalize") + autocomplete = JSProperty("autocomplete") + autofocus = JSProperty("autofocus") + cols = JSProperty("cols") + dirname = JSProperty("dirname") + disabled = JSProperty("disabled") + form = JSProperty("form") + maxlength = JSProperty("maxlength") + minlength = JSProperty("minlength") + name = JSProperty("name") + placeholder = JSProperty("placeholder") + readonly = JSProperty("readonly") + required = JSProperty("required") + rows = JSProperty("rows") + spellcheck = JSProperty("spellcheck") + wrap = JSProperty("wrap") + + +class tfoot(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tfoot""" + + tag = "tfoot" + + +class th(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/th""" + + tag = "th" + + +class thead(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/thead""" + + tag = "thead" + + +class time(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time""" + + tag = "time" + + datetime = JSProperty("datetime") + + +class title(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title""" + + tag = "title" + + +class tr(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/tr""" + + tag = "tr" + + abbr = JSProperty("abbr") + colspan = JSProperty("colspan") + headers = JSProperty("headers") + rowspan = JSProperty("rowspan") + scope = JSProperty("scope") + + +class track(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track""" + + tag = "track" + + default = JSProperty("default") + kind = JSProperty("kind") + label = JSProperty("label") + src = JSProperty("src") + srclang = JSProperty("srclang") + + +class u(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/u""" + + tag = "u" + + +class ul(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul""" + + tag = "ul" + + +class var(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/var""" + + tag = "var" + + +class video(TextElementBase): + """Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video""" + + tag = "video" + + autoplay = JSProperty("autoplay") + controls = JSProperty("controls") + crossorigin = JSProperty("crossorigin") + disablepictureinpicture = JSProperty("disablepictureinpicture") + disableremoteplayback = JSProperty("disableremoteplayback") + height = JSProperty("height") + loop = JSProperty("loop") + muted = JSProperty("muted") + playsinline = JSProperty("playsinline") + poster = JSProperty("poster") + preload = JSProperty("preload") + src = JSProperty("src") + width = JSProperty("width") + + +# Custom Elements +class grid(TextElementBase): + tag = "div" + + def __init__(self, layout, content=None, gap=None, **kwargs): + super().__init__(content, **kwargs) + self.style["display"] = "grid" + self.style["grid-template-columns"] = layout + + # TODO: This should be a property + if not gap is None: + self.style["gap"] = gap diff --git a/pyscript.core/test/pydom.py b/pyscript.core/test/pydom.py index 3f579e8edb7..2f134688c19 100644 --- a/pyscript.core/test/pydom.py +++ b/pyscript.core/test/pydom.py @@ -4,7 +4,7 @@ from datetime import datetime as dt from pyscript import display, when -from pyscript.web import dom +from pyweb import pydom display(sys.version, target="system-info") @@ -19,15 +19,18 @@ def on_click(): tstr = "{:02d}/{:02d}/{:04d} {:02d}:{:02d}:{:02d}" timenow = tstr.format(tnow[2], tnow[1], tnow[0], *tnow[2:]) - display(f"Hello from PyScript, time is: {timenow}", append=False, target="#result") + display(f"Hello from PyScript, time is: {timenow}", append=False, target="result") @when("click", "#color-button") def on_color_click(event): - btn = dom["#result"] + btn = pydom["#result"] btn.style["background-color"] = f"#{random.randrange(0x1000000):06x}" @when("click", "#color-reset-button") def reset_color(*args, **kwargs): - dom["#result"].style["background-color"] = "white" + pydom["#result"].style["background-color"] = "white" + + +# btn_reset = pydom["#color-reset-button"][0].when('click', reset_color) diff --git a/pyscript.core/test/pyscript_dom/tests/test_dom.py b/pyscript.core/test/pyscript_dom/tests/test_dom.py index 7f4af822855..d3a23c805b2 100644 --- a/pyscript.core/test/pyscript_dom/tests/test_dom.py +++ b/pyscript.core/test/pyscript_dom/tests/test_dom.py @@ -2,13 +2,22 @@ import pytest from pyscript import document, when -from pyscript.web import dom -from pyscript.web import elements as el +from pyweb import pydom class TestDocument: def test__element(self): - assert dom._js == document + assert pydom._js == document + + def test_no_parent(self): + assert pydom.parent is None + + def test_create_element(self): + new_el = pydom.create("div") + assert isinstance(new_el, pydom.BaseElement) + assert new_el._js.tagName == "DIV" + # EXPECT the new element to be associated with the document + assert new_el.parent == None def test_getitem_by_id(): @@ -17,14 +26,14 @@ def test_getitem_by_id(): txt = "You found test_id_selector" selector = f"#{id_}" # EXPECT the element to be found by id - result = dom[selector] + result = pydom[selector] div = result[0] # EXPECT the element text value to match what we expect and what # the JS document.querySelector API would return assert document.querySelector(selector).innerHTML == div.html == txt # EXPECT the results to be of the right types - assert isinstance(div, el.BaseElement) - assert isinstance(result, dom.ElementCollection) + assert isinstance(div, pydom.BaseElement) + assert isinstance(result, pydom.ElementCollection) def test_getitem_by_class(): @@ -34,7 +43,7 @@ def test_getitem_by_class(): "test_selector_w_children_child_1", ] expected_class = "a-test-class" - result = dom[f".{expected_class}"] + result = pydom[f".{expected_class}"] div = result[0] # EXPECT to find exact number of elements with the class in the page (== 3) @@ -45,7 +54,7 @@ def test_getitem_by_class(): def test_read_n_write_collection_elements(): - elements = dom[".multi-elems"] + elements = pydom[".multi-elems"] for element in elements: assert element.html == f"Content {element.id.replace('#', '')}" @@ -60,15 +69,15 @@ class TestElement: def test_query(self): # GIVEN an existing element on the page, with at least 1 child element id_ = "test_selector_w_children" - parent_div = dom[f"#{id_}"][0] + parent_div = pydom[f"#{id_}"][0] # EXPECT it to be able to query for the first child element div = parent_div.find("div")[0] # EXPECT the new element to be associated with the parent assert div.parent == parent_div - # EXPECT the new element to be a el.BaseElement - assert isinstance(div, el.BaseElement) + # EXPECT the new element to be a BaseElement + assert isinstance(div, pydom.BaseElement) # EXPECT the div attributes to be == to how they are configured in the page assert div.html == "Child 1" assert div.id == "test_selector_w_children_child_1" @@ -77,8 +86,8 @@ def test_equality(self): # GIVEN 2 different Elements pointing to the same underlying element id_ = "test_id_selector" selector = f"#{id_}" - div = dom[selector][0] - div2 = dom[selector][0] + div = pydom[selector][0] + div2 = pydom[selector][0] # EXPECT them to be equal assert div == div2 @@ -93,27 +102,27 @@ def test_equality(self): def test_append_element(self): id_ = "element-append-tests" - div = dom[f"#{id_}"][0] + div = pydom[f"#{id_}"][0] len_children_before = len(div.children) - new_el = el.p("new element") + new_el = div.create("p") div.append(new_el) assert len(div.children) == len_children_before + 1 assert div.children[-1] == new_el def test_append_js_element(self): id_ = "element-append-tests" - div = dom[f"#{id_}"][0] + div = pydom[f"#{id_}"][0] len_children_before = len(div.children) - new_el = el.p("new element") + new_el = div.create("p") div.append(new_el._js) assert len(div.children) == len_children_before + 1 assert div.children[-1] == new_el def test_append_collection(self): id_ = "element-append-tests" - div = dom[f"#{id_}"][0] + div = pydom[f"#{id_}"][0] len_children_before = len(div.children) - collection = dom[".collection"] + collection = pydom[".collection"] div.append(collection) assert len(div.children) == len_children_before + len(collection) @@ -123,16 +132,16 @@ def test_append_collection(self): def test_read_classes(self): id_ = "test_class_selector" expected_class = "a-test-class" - div = dom[f"#{id_}"][0] + div = pydom[f"#{id_}"][0] assert div.classes == [expected_class] def test_add_remove_class(self): id_ = "div-no-classes" classname = "tester-class" - div = dom[f"#{id_}"][0] + div = pydom[f"#{id_}"][0] assert not div.classes div.add_class(classname) - same_div = dom[f"#{id_}"][0] + same_div = pydom[f"#{id_}"][0] assert div.classes == [classname] == same_div.classes div.remove_class(classname) assert div.classes == [] == same_div.classes @@ -140,7 +149,7 @@ def test_add_remove_class(self): def test_when_decorator(self): called = False - just_a_button = dom["#a-test-button"][0] + just_a_button = pydom["#a-test-button"][0] @when("click", just_a_button) def on_click(event): @@ -148,7 +157,7 @@ def on_click(event): called = True # Now let's simulate a click on the button (using the low level JS API) - # so we don't risk dom getting in the way + # so we don't risk pydom getting in the way assert not called just_a_button._js.click() @@ -156,7 +165,7 @@ def on_click(event): def test_html_attribute(self): # GIVEN an existing element on the page with a known empty text content - div = dom["#element_attribute_tests"][0] + div = pydom["#element_attribute_tests"][0] # WHEN we set the html attribute div.html = "New Content" @@ -168,7 +177,7 @@ def test_html_attribute(self): def test_text_attribute(self): # GIVEN an existing element on the page with a known empty text content - div = dom["#element_attribute_tests"][0] + div = pydom["#element_attribute_tests"][0] # WHEN we set the html attribute div.text = "New Content" @@ -181,12 +190,12 @@ def test_text_attribute(self): class TestCollection: def test_iter_eq_children(self): - elements = dom[".multi-elems"] + elements = pydom[".multi-elems"] assert [el for el in elements] == [el for el in elements.children] assert len(elements) == 3 def test_slices(self): - elements = dom[".multi-elems"] + elements = pydom[".multi-elems"] assert elements[0] _slice = elements[:2] assert len(_slice) == 2 @@ -196,26 +205,26 @@ def test_slices(self): def test_style_rule(self): selector = ".multi-elems" - elements = dom[selector] + elements = pydom[selector] for el in elements: assert el.style["background-color"] != "red" elements.style["background-color"] = "red" - for i, el in enumerate(dom[selector]): + for i, el in enumerate(pydom[selector]): assert elements[i].style["background-color"] == "red" assert el.style["background-color"] == "red" elements.style.remove("background-color") - for i, el in enumerate(dom[selector]): + for i, el in enumerate(pydom[selector]): assert el.style["background-color"] != "red" assert elements[i].style["background-color"] != "red" def test_when_decorator(self): called = False - buttons_collection = dom["button"] + buttons_collection = pydom["button"] @when("click", buttons_collection) def on_click(event): @@ -223,7 +232,7 @@ def on_click(event): called = True # Now let's simulate a click on the button (using the low level JS API) - # so we don't risk dom getting in the way + # so we don't risk pydom getting in the way assert not called for button in buttons_collection: button._js.click() @@ -233,32 +242,32 @@ def on_click(event): class TestCreation: def test_create_document_element(self): - # TODO: This test should probably be removed since it's testing the elements module - new_el = el.div("new element") + new_el = pydom.create("div") new_el.id = "new_el_id" - assert isinstance(new_el, el.BaseElement) + assert isinstance(new_el, pydom.BaseElement) assert new_el._js.tagName == "DIV" # EXPECT the new element to be associated with the document assert new_el.parent == None - dom.body.append(new_el) + pydom.body.append(new_el) - assert dom["#new_el_id"][0].parent == dom.body + assert pydom["#new_el_id"][0].parent == pydom.body def test_create_element_child(self): selector = "#element-creation-test" - parent_div = dom[selector][0] + parent_div = pydom[selector][0] # Creating an element from another element automatically creates that element # as a child of the original element - new_el = el.p("a div", classes=["code-description"], html="Ciao PyScripters!") - parent_div.append(new_el) + new_el = parent_div.create( + "p", classes=["code-description"], html="Ciao PyScripters!" + ) - assert isinstance(new_el, el.BaseElement) + assert isinstance(new_el, pydom.BaseElement) assert new_el._js.tagName == "P" - # EXPECT the new element to be associated with the document assert new_el.parent == parent_div - assert dom[selector][0].children[0] == new_el + + assert pydom[selector][0].children[0] == new_el class TestInput: @@ -272,7 +281,7 @@ class TestInput: def test_value(self): for id_ in self.input_ids: expected_type = id_.split("_")[-1] - result = dom[f"#{id_}"] + result = pydom[f"#{id_}"] input_el = result[0] assert input_el._js.type == expected_type assert input_el.value == f"Content {id_}" == input_el._js.value @@ -290,7 +299,7 @@ def test_value(self): def test_set_value_collection(self): for id_ in self.input_ids: - input_el = dom[f"#{id_}"] + input_el = pydom[f"#{id_}"] assert input_el.value[0] == f"Content {id_}" == input_el[0].value @@ -299,35 +308,35 @@ def test_set_value_collection(self): assert input_el.value[0] == new_value == input_el[0].value def test_element_without_value(self): - result = dom[f"#tests-terminal"][0] + result = pydom[f"#tests-terminal"][0] with pytest.raises(AttributeError): result.value = "some value" def test_element_without_collection(self): - result = dom[f"#tests-terminal"] + result = pydom[f"#tests-terminal"] with pytest.raises(AttributeError): result.value = "some value" def test_element_without_collection(self): - result = dom[f"#tests-terminal"] + result = pydom[f"#tests-terminal"] with pytest.raises(AttributeError): result.value = "some value" class TestSelect: def test_select_options_iter(self): - select = dom[f"#test_select_element_w_options"][0] + select = pydom[f"#test_select_element_w_options"][0] for i, option in enumerate(select.options, 1): assert option.value == f"{i}" assert option.html == f"Option {i}" def test_select_options_len(self): - select = dom[f"#test_select_element_w_options"][0] + select = pydom[f"#test_select_element_w_options"][0] assert len(select.options) == 2 def test_select_options_clear(self): - select = dom[f"#test_select_element_to_clear"][0] + select = pydom[f"#test_select_element_to_clear"][0] assert len(select.options) == 3 select.options.clear() @@ -336,7 +345,7 @@ def test_select_options_clear(self): def test_select_element_add(self): # GIVEN the existing select element with no options - select = dom[f"#test_select_element"][0] + select = pydom[f"#test_select_element"][0] # EXPECT the select element to have no options assert len(select.options) == 0 @@ -417,7 +426,7 @@ def test_select_element_add(self): def test_select_options_remove(self): # GIVEN the existing select element with 3 options - select = dom[f"#test_select_element_to_remove"][0] + select = pydom[f"#test_select_element_to_remove"][0] # EXPECT the select element to have 3 options assert len(select.options) == 4 @@ -439,7 +448,7 @@ def test_select_options_remove(self): def test_select_get_selected_option(self): # GIVEN the existing select element with one selected option - select = dom[f"#test_select_element_w_options"][0] + select = pydom[f"#test_select_element_w_options"][0] # WHEN we get the selected option selected_option = select.options.selected diff --git a/pyscript.core/tests/integration/test_pyweb.py b/pyscript.core/tests/integration/test_pyweb.py index 80b2567d6ed..d83424c8c00 100644 --- a/pyscript.core/tests/integration/test_pyweb.py +++ b/pyscript.core/tests/integration/test_pyweb.py @@ -101,11 +101,10 @@ def parse_value(v): code_ = f""" from pyscript import when """ self.pyscript_run(code_) diff --git a/pyscript.core/types/stdlib/pyscript.d.ts b/pyscript.core/types/stdlib/pyscript.d.ts index fb69b323649..8dd1c7c3d24 100644 --- a/pyscript.core/types/stdlib/pyscript.d.ts +++ b/pyscript.core/types/stdlib/pyscript.d.ts @@ -17,5 +17,14 @@ declare namespace _default { }; "websocket.py": string; }; + let pyweb: { + "__init__.py": string; + "media.py": string; + "pydom.py": string; + ui: { + "__init__.py": string; + "elements.py": string; + }; + }; } export default _default; From 461ae38763ef2a24ceeee4bd1a2348cbe8260735 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Fri, 21 Jun 2024 16:06:18 +0200 Subject: [PATCH 069/179] Updated reference code to grab latest (#2107) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 869c25b952c..c70151f7219 100644 --- a/README.md +++ b/README.md @@ -38,11 +38,11 @@ To try PyScript, import the appropriate pyscript files into the `` tag of From 7b8ef7ebe2791be6aea2b108ce3bcff945a12a9b Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Mon, 24 Jun 2024 17:04:28 +0200 Subject: [PATCH 070/179] Fix #2109 - Allow inline JSON config attribute in PyEditor (#2110) Fix #2109 - Allow inline JSON config attribute in PyEditor --- pyscript.core/package-lock.json | 100 +++++++++++------------ pyscript.core/package.json | 10 +-- pyscript.core/src/config.js | 6 +- pyscript.core/src/core.js | 5 +- pyscript.core/src/plugins/py-editor.js | 24 ++++-- pyscript.core/src/plugins/py-terminal.js | 4 +- pyscript.core/test/py-editor/index.html | 2 +- pyscript.core/types/config.d.ts | 4 +- pyscript.core/types/core.d.ts | 3 +- pyscript.core/types/exceptions.d.ts | 17 +--- 10 files changed, 85 insertions(+), 90 deletions(-) diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index 472a23558b5..457c1ccd2b8 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,17 +1,17 @@ { "name": "@pyscript/core", - "version": "0.4.50", + "version": "0.4.52", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.50", + "version": "0.4.52", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.13.5", + "polyscript": "^0.13.7", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -21,7 +21,7 @@ "@codemirror/lang-python": "^6.1.6", "@codemirror/language": "^6.10.2", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.28.1", + "@codemirror/view": "^6.28.2", "@playwright/test": "^1.44.1", "@rollup/plugin-commonjs": "^26.0.1", "@rollup/plugin-node-resolve": "^15.2.3", @@ -29,7 +29,7 @@ "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", - "bun": "^1.1.14", + "bun": "^1.1.16", "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^9.5.0", @@ -38,7 +38,7 @@ "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", - "typescript": "^5.4.5", + "typescript": "^5.5.2", "xterm": "^5.3.0", "xterm-readline": "^1.1.1" } @@ -136,9 +136,9 @@ "license": "MIT" }, "node_modules/@codemirror/view": { - "version": "6.28.1", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.28.1.tgz", - "integrity": "sha512-BUWr+zCJpMkA/u69HlJmR+YkV4yPpM81HeMkOMZuwFa8iM5uJdEPKAs1icIRZKkKmy0Ub1x9/G3PQLTXdpBxrQ==", + "version": "6.28.2", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.28.2.tgz", + "integrity": "sha512-A3DmyVfjgPsGIjiJqM/zvODUAPQdQl3ci0ghehYNnbt5x+o76xq+dL5+mMBuysDXnI3kapgOkoeJ0sbtL/3qPw==", "dev": true, "license": "MIT", "dependencies": { @@ -462,9 +462,9 @@ } }, "node_modules/@oven/bun-darwin-aarch64": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.14.tgz", - "integrity": "sha512-zdgLlQ9+SUOgJzTMQyb0lnX2MRtFgVApXPR9c0lSVUqPbfcGogVDRuNFWdYK96wjUkrCJIvYeu5rbMGcnJD1Qg==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-aarch64/-/bun-darwin-aarch64-1.1.16.tgz", + "integrity": "sha512-a5lnLoyyw24n0uvVSSJVT8kZjA7m3xO2FRBenpr+01A+SIkA8q255ybEBEz+7X30M5ZhYJwb11KgkScd0MB8Mg==", "cpu": [ "arm64" ], @@ -476,9 +476,9 @@ ] }, "node_modules/@oven/bun-darwin-x64": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.14.tgz", - "integrity": "sha512-CEoFw0udQRann0Vj3Et1/nW6MV3EY/kZ+lNkSCCmFEvq1HDLB+Wbicgnt9GbEElw6XXXKm4FdxMYnOJzfeanYQ==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64/-/bun-darwin-x64-1.1.16.tgz", + "integrity": "sha512-LYm6KnALYdDJEaxV1HYWIttgQMECMV5akvlnKULDYXp2anxjQDYGoZ4VpVwdDiKel3m/pnG0RSPLDHiX5NCYWg==", "cpu": [ "x64" ], @@ -490,9 +490,9 @@ ] }, "node_modules/@oven/bun-darwin-x64-baseline": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.14.tgz", - "integrity": "sha512-k1vKXmOQ9+Rdj6dkgPIo0MWKmEf9+CmjyD2GZkRM6dxufiytNSuE5yT8FQMtb2Yg1I8OFH/+kUiNxn2eIKurRw==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@oven/bun-darwin-x64-baseline/-/bun-darwin-x64-baseline-1.1.16.tgz", + "integrity": "sha512-NwnowvNIwT9JsLVQ8YgjzobvVYxC3F3bHN7jGTSX6b5ogLQ+LGzRlzFfnRJNV9JbyLLYeA7jQAS0CPvQoon6gQ==", "cpu": [ "x64" ], @@ -504,9 +504,9 @@ ] }, "node_modules/@oven/bun-linux-aarch64": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.14.tgz", - "integrity": "sha512-uHI7jk47C6wwG/y90W35NttyDrKLWum1pa5PfpuMi8+LpxnRGi0doGXN73RwdJy+qnYp2OjJTo60X++GMn9GmA==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-aarch64/-/bun-linux-aarch64-1.1.16.tgz", + "integrity": "sha512-RiUVrMLuROwezg8iTnTgbkvPz3k7G6o07WGVEXVFr6umxlaRc8jB2uVlc2BCrPtJtm27iJJpu7SnwpHg+Rr8Qw==", "cpu": [ "arm64" ], @@ -518,9 +518,9 @@ ] }, "node_modules/@oven/bun-linux-x64": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.14.tgz", - "integrity": "sha512-t2b6pDSlV2Uke6ON5eSx1hk/o+f4s8Nr+E1djx9fNqrvz58UF4zmilQoEKDhciuRUKvhMkroddiORpxIMiKIjA==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64/-/bun-linux-x64-1.1.16.tgz", + "integrity": "sha512-T6YDz/KnbH/FZH+2QI3C3CZcGqlGe2Nmk5haMvWPlW7y6B/ejQ84/Y88FNxD7V9rSLlnY+PZX5IQjN0rZ/CaHw==", "cpu": [ "x64" ], @@ -532,9 +532,9 @@ ] }, "node_modules/@oven/bun-linux-x64-baseline": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.14.tgz", - "integrity": "sha512-7otawHLy8ec0iN0wr7sznkOpMhofZCfJeA4vWp+5D/yhXg8ZxVaK7xJ1aWBlBLHAMX8tWTkrUjB6X2iQFtvZvQ==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@oven/bun-linux-x64-baseline/-/bun-linux-x64-baseline-1.1.16.tgz", + "integrity": "sha512-AWD3Kmb7gvlVqyW8qk/2MbHPS/HzsoNYz0SVjKiJMMzDbRE7cILk5OSYafi+iSnJKy1Qw7p25LP6LpkGzrBnyA==", "cpu": [ "x64" ], @@ -546,9 +546,9 @@ ] }, "node_modules/@oven/bun-windows-x64": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.14.tgz", - "integrity": "sha512-hZ+Z0zgO6FM63U99wkF0YvTLm/Tcfa4ue5U9JOGc8K05DLBS4gHp6f0bngzd3EvIEz+mfc+zcYPR954dYHT9AA==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64/-/bun-windows-x64-1.1.16.tgz", + "integrity": "sha512-HMcwQq0lvqSbbXMqrUhLIwhOAMdt5IUCTPDkcMEPKQpWk7FUTfLkeH/8928kqpVmN7LHHH7I9PqMY7Q/Q3gZBA==", "cpu": [ "x64" ], @@ -560,9 +560,9 @@ ] }, "node_modules/@oven/bun-windows-x64-baseline": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.14.tgz", - "integrity": "sha512-oK7y0q5sICni6771q+xvJ40dqzg0l+x2IdkN8V2I5QMzQCqFIVPhwPmOX5+2JsMp9ILQtYeioyL60kCDgIguDw==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@oven/bun-windows-x64-baseline/-/bun-windows-x64-baseline-1.1.16.tgz", + "integrity": "sha512-SspbjEgeXh7NkB61rhHcQDGqWl/nPQcn7NKb5wkxZyDmrwITciq2J8iaYsw/WEyYUFubjkjvpJala+cGS7voLA==", "cpu": [ "x64" ], @@ -1202,9 +1202,9 @@ } }, "node_modules/bun": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.14.tgz", - "integrity": "sha512-LqbB6Xr8bU6D9K18UOrzmLLPYOS9CQ3SGW+JvTUli/eYW4y70yzdCr6JZiw3pk0V8ZqHn9Kmg3c8/7rF2XIM8g==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/bun/-/bun-1.1.16.tgz", + "integrity": "sha512-t2AwDuJsLA3cBAxNQv/hJ66SLGtVkKFjrxdpcztkUwjVst6G9ynWiVwQOlg6VSN7niF2EZptTvDg6Jb+MKEGMQ==", "cpu": [ "arm64", "x64" @@ -1222,14 +1222,14 @@ "bunx": "bin/bun.exe" }, "optionalDependencies": { - "@oven/bun-darwin-aarch64": "1.1.14", - "@oven/bun-darwin-x64": "1.1.14", - "@oven/bun-darwin-x64-baseline": "1.1.14", - "@oven/bun-linux-aarch64": "1.1.14", - "@oven/bun-linux-x64": "1.1.14", - "@oven/bun-linux-x64-baseline": "1.1.14", - "@oven/bun-windows-x64": "1.1.14", - "@oven/bun-windows-x64-baseline": "1.1.14" + "@oven/bun-darwin-aarch64": "1.1.16", + "@oven/bun-darwin-x64": "1.1.16", + "@oven/bun-darwin-x64-baseline": "1.1.16", + "@oven/bun-linux-aarch64": "1.1.16", + "@oven/bun-linux-x64": "1.1.16", + "@oven/bun-linux-x64-baseline": "1.1.16", + "@oven/bun-windows-x64": "1.1.16", + "@oven/bun-windows-x64-baseline": "1.1.16" } }, "node_modules/callsites": { @@ -2918,9 +2918,9 @@ } }, "node_modules/polyscript": { - "version": "0.13.5", - "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.13.5.tgz", - "integrity": "sha512-PwXWnhLbOMtvZWFIN271JhaN7KnxESaMtv9Rcdrq1TKTCMnkz9idvYb3Od1iumBJlr49lLlwyUKeGb423rFR4w==", + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.13.7.tgz", + "integrity": "sha512-GVJHVw3EjNgWyZIN1yKVd2AtzF+ARwYGYvzN5VHO0WqWXL3w+8CifQIbEDgBgvalOWfF/YxyK4C+0LKVx9lnGA==", "license": "APACHE-2.0", "dependencies": { "@ungap/structured-clone": "^1.2.0", @@ -4178,9 +4178,9 @@ "license": "ISC" }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", + "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/pyscript.core/package.json b/pyscript.core/package.json index 402f277194d..03c53082eac 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.50", + "version": "0.4.52", "type": "module", "description": "PyScript", "module": "./index.js", @@ -44,7 +44,7 @@ "dependencies": { "@ungap/with-resolvers": "^0.1.0", "basic-devtools": "^0.1.6", - "polyscript": "^0.13.5", + "polyscript": "^0.13.7", "sticky-module": "^0.1.1", "to-json-callback": "^0.1.1", "type-checked-collections": "^0.1.7" @@ -54,7 +54,7 @@ "@codemirror/lang-python": "^6.1.6", "@codemirror/language": "^6.10.2", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.28.1", + "@codemirror/view": "^6.28.2", "@playwright/test": "^1.44.1", "@rollup/plugin-commonjs": "^26.0.1", "@rollup/plugin-node-resolve": "^15.2.3", @@ -62,7 +62,7 @@ "@webreflection/toml-j0.4": "^1.1.3", "@xterm/addon-fit": "^0.10.0", "@xterm/addon-web-links": "^0.11.0", - "bun": "^1.1.14", + "bun": "^1.1.16", "chokidar": "^3.6.0", "codemirror": "^6.0.1", "eslint": "^9.5.0", @@ -71,7 +71,7 @@ "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", - "typescript": "^5.4.5", + "typescript": "^5.5.2", "xterm": "^5.3.0", "xterm-readline": "^1.1.1" }, diff --git a/pyscript.core/src/config.js b/pyscript.core/src/config.js index ca8d3a46099..040bbbe58c9 100644 --- a/pyscript.core/src/config.js +++ b/pyscript.core/src/config.js @@ -45,6 +45,8 @@ const configDetails = async (config, type) => { const conflictError = (reason) => new Error(`(${CONFLICTING_CODE}): ${reason}`); +const relative_url = (url, base = location.href) => new URL(url, base).href; + const syntaxError = (type, url, { message }) => { let str = `(${BAD_CONFIG}): Invalid ${type}`; if (url) str += ` @ ${url}`; @@ -108,7 +110,7 @@ for (const [TYPE] of TYPES) { if (!error && config) { try { const { json, toml, text, url } = await configDetails(config, type); - if (url) configURL = new URL(url, location.href).href; + if (url) configURL = relative_url(url); config = text; if (json || type === "json") { try { @@ -153,4 +155,4 @@ for (const [TYPE] of TYPES) { configs.set(TYPE, { config: parsed, configURL, plugins, error }); } -export default configs; +export { configs, relative_url }; diff --git a/pyscript.core/src/core.js b/pyscript.core/src/core.js index 56f7117a954..5a1e3bc70cf 100644 --- a/pyscript.core/src/core.js +++ b/pyscript.core/src/core.js @@ -19,7 +19,7 @@ import { import "./all-done.js"; import TYPES from "./types.js"; -import configs from "./config.js"; +import { configs, relative_url } from "./config.js"; import sync from "./sync.js"; import bootstrapNodeAndPlugins from "./plugins-helper.js"; import { ErrorCode } from "./exceptions.js"; @@ -84,6 +84,7 @@ const [ export { TYPES, + relative_url, exportedPyWorker as PyWorker, exportedMPWorker as MPWorker, exportedHooks as hooks, @@ -92,7 +93,7 @@ export { }; export const offline_interpreter = (config) => - config?.interpreter && new URL(config.interpreter, location.href).href; + config?.interpreter && relative_url(config.interpreter); const hooked = new Map(); diff --git a/pyscript.core/src/plugins/py-editor.js b/pyscript.core/src/plugins/py-editor.js index 0a0f69a942e..0218162be4e 100644 --- a/pyscript.core/src/plugins/py-editor.js +++ b/pyscript.core/src/plugins/py-editor.js @@ -1,6 +1,6 @@ // PyScript py-editor plugin import { Hook, XWorker, dedent, defineProperties } from "polyscript/exports"; -import { TYPES, offline_interpreter, stdlib } from "../core.js"; +import { TYPES, offline_interpreter, relative_url, stdlib } from "../core.js"; const RUN_BUTTON = ``; @@ -37,11 +37,19 @@ async function execute({ currentTarget }) { const details = { type: this.interpreter }; const { config } = this; if (config) { - details.configURL = config; - const { parse } = config.endsWith(".toml") - ? await import(/* webpackIgnore: true */ "../3rd-party/toml.js") - : JSON; - details.config = parse(await fetch(config).then((r) => r.text())); + details.configURL = relative_url(config); + if (config.endsWith(".toml")) { + const [{ parse }, toml] = await Promise.all([ + import(/* webpackIgnore: true */ "../3rd-party/toml.js"), + fetch(config).then((r) => r.text()), + ]); + details.config = parse(toml); + } else if (config.endsWith(".json")) { + details.config = await fetch(config).then((r) => r.json()); + } else { + details.configURL = relative_url("./config.txt"); + details.config = JSON.parse(config); + } details.version = offline_interpreter(details.config); } else { details.config = {}; @@ -175,9 +183,7 @@ const init = async (script, type, interpreter) => { handleEvent: execute, interpreter, env, - config: - hasConfig && - new URL(script.getAttribute("config"), location.href).href, + config: hasConfig && script.getAttribute("config"), get pySrc() { return isSetup ? source : editor.state.doc.toString(); }, diff --git a/pyscript.core/src/plugins/py-terminal.js b/pyscript.core/src/plugins/py-terminal.js index 4dfc4eb293d..cd61483a488 100644 --- a/pyscript.core/src/plugins/py-terminal.js +++ b/pyscript.core/src/plugins/py-terminal.js @@ -1,5 +1,5 @@ // PyScript py-terminal plugin -import { TYPES } from "../core.js"; +import { TYPES, relative_url } from "../core.js"; import { notify } from "./error.js"; import { customObserver } from "polyscript/exports"; @@ -35,7 +35,7 @@ for (const type of TYPES.keys()) { document.head.append( Object.assign(document.createElement("link"), { rel: "stylesheet", - href: new URL("./xterm.css", import.meta.url), + href: relative_url("./xterm.css", import.meta.url), }), ); } diff --git a/pyscript.core/test/py-editor/index.html b/pyscript.core/test/py-editor/index.html index c1b4f57adb4..a0d32b680fe 100644 --- a/pyscript.core/test/py-editor/index.html +++ b/pyscript.core/test/py-editor/index.html @@ -29,7 +29,7 @@ a = 1 - + + + + + + + + diff --git a/pyscript.core/test/workers/test.py b/pyscript.core/test/workers/test.py new file mode 100644 index 00000000000..55a99a42650 --- /dev/null +++ b/pyscript.core/test/workers/test.py @@ -0,0 +1,19 @@ +from pyscript import document, workers + + +async def test(interpreter): + # accessed as item + named = await workers.micropython_version + + version = await named.micropython_version() + document.body.append(version) + document.body.append(document.createElement("hr")) + + # accessed as attribute + named = await workers["pyodide_version"] + + version = await named.pyodide_version() + document.body.append(version) + document.body.append(document.createElement("hr")) + + document.documentElement.classList.add(interpreter) diff --git a/pyscript.core/test/workers/worker.py b/pyscript.core/test/workers/worker.py new file mode 100644 index 00000000000..59b78330970 --- /dev/null +++ b/pyscript.core/test/workers/worker.py @@ -0,0 +1,7 @@ +def micropython_version(): + import sys + + return sys.version + + +__export__ = ["micropython_version"] diff --git a/pyscript.core/types/stdlib/pyscript.d.ts b/pyscript.core/types/stdlib/pyscript.d.ts index 8dd1c7c3d24..88a4f2b875b 100644 --- a/pyscript.core/types/stdlib/pyscript.d.ts +++ b/pyscript.core/types/stdlib/pyscript.d.ts @@ -16,6 +16,7 @@ declare namespace _default { "media.py": string; }; "websocket.py": string; + "workers.py": string; }; let pyweb: { "__init__.py": string; From 67d47511d5c0968a55a5b95e34f34817ba8faff7 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Wed, 3 Jul 2024 13:03:31 +0200 Subject: [PATCH 072/179] Fix MicroPython terminal input when no REPL is used/needed (#2113) * Fix terminal input when no REPL is used/needed * Fix input backspace too --- pyscript.core/package-lock.json | 72 ++++++++++---------- pyscript.core/package.json | 10 +-- pyscript.core/src/plugins/py-terminal/mpy.js | 29 +++++--- pyscript.core/test/py-terminals.html | 2 +- pyscript.core/test/py-terminals/index.html | 18 +++++ pyscript.core/test/py-terminals/no-repl.html | 20 ++++++ pyscript.core/test/py-terminals/repl.html | 28 ++++++++ 7 files changed, 129 insertions(+), 50 deletions(-) create mode 100644 pyscript.core/test/py-terminals/index.html create mode 100644 pyscript.core/test/py-terminals/no-repl.html create mode 100644 pyscript.core/test/py-terminals/repl.html diff --git a/pyscript.core/package-lock.json b/pyscript.core/package-lock.json index e3af45819c3..50d58194dc9 100644 --- a/pyscript.core/package-lock.json +++ b/pyscript.core/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pyscript/core", - "version": "0.4.53", + "version": "0.4.55", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@pyscript/core", - "version": "0.4.53", + "version": "0.4.55", "license": "APACHE-2.0", "dependencies": { "@ungap/with-resolvers": "^0.1.0", @@ -21,8 +21,8 @@ "@codemirror/lang-python": "^6.1.6", "@codemirror/language": "^6.10.2", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.28.2", - "@playwright/test": "^1.45.0", + "@codemirror/view": "^6.28.3", + "@playwright/test": "^1.45.1", "@rollup/plugin-commonjs": "^26.0.1", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", @@ -32,13 +32,13 @@ "bun": "^1.1.17", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^9.5.0", + "eslint": "^9.6.0", "flatted": "^3.3.1", "rollup": "^4.18.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", - "typescript": "^5.5.2", + "typescript": "^5.5.3", "xterm": "^5.3.0", "xterm-readline": "^1.1.1" } @@ -136,9 +136,9 @@ "license": "MIT" }, "node_modules/@codemirror/view": { - "version": "6.28.2", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.28.2.tgz", - "integrity": "sha512-A3DmyVfjgPsGIjiJqM/zvODUAPQdQl3ci0ghehYNnbt5x+o76xq+dL5+mMBuysDXnI3kapgOkoeJ0sbtL/3qPw==", + "version": "6.28.3", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.28.3.tgz", + "integrity": "sha512-QVqP+ko078/h9yrW+u5grX3rQhC+BkGKADRrlDaJznfPngJOv5zObiVf0+SgAWhL/Yt0nvZ+10rO3L+gU5IbFw==", "dev": true, "license": "MIT", "dependencies": { @@ -187,15 +187,15 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.16.0.tgz", - "integrity": "sha512-/jmuSd74i4Czf1XXn7wGRWZCuyaUZ330NH1Bek0Pplatt4Sy1S5haN21SCLLdbeKslQ+S0wEJ+++v5YibSi+Lg==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.0.tgz", + "integrity": "sha512-A68TBu6/1mHHuc5YJL0U0VVeGNiklLAL6rRmhTCP2B5XjWLMnrX+HkO+IAXyHvks5cyyY1jjK5ITPQ1HGS2EVA==", "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.4", "debug": "^4.3.1", - "minimatch": "^3.0.5" + "minimatch": "^3.1.2" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -226,9 +226,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.5.0.tgz", - "integrity": "sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.6.0.tgz", + "integrity": "sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A==", "dev": true, "license": "MIT", "engines": { @@ -585,13 +585,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.0.tgz", - "integrity": "sha512-TVYsfMlGAaxeUllNkywbwek67Ncf8FRGn8ZlRdO291OL3NjG9oMbfVhyP82HQF0CZLMrYsvesqoUekxdWuF9Qw==", + "version": "1.45.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.1.tgz", + "integrity": "sha512-Wo1bWTzQvGA7LyKGIZc8nFSTFf2TkthGIFBR+QVNilvwouGzFd4PYukZe3rvf5PSqjHi1+1NyKSDZKcQWETzaA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.45.0" + "playwright": "1.45.1" }, "bin": { "playwright": "cli.js" @@ -1752,17 +1752,17 @@ } }, "node_modules/eslint": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.5.0.tgz", - "integrity": "sha512-+NAOZFrW/jFTS3dASCGBxX1pkFD0/fsO+hfAkJ4TyYKwgsXZbqzrw+seCYFCcPCYXvnD67tAnglU7GQTz6kcVw==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-ElQkdLMEEqQNM9Njff+2Y4q2afHk7JpkPvrd7Xh7xefwgQynqPxwf55J7di9+MEibWUGdNjFF9ITG9Pck5M84w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/config-array": "^0.16.0", + "@eslint/config-array": "^0.17.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.5.0", + "@eslint/js": "9.6.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -1773,7 +1773,7 @@ "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.0.1", "eslint-visitor-keys": "^4.0.0", - "espree": "^10.0.1", + "espree": "^10.1.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2882,13 +2882,13 @@ "license": "ISC" }, "node_modules/playwright": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.0.tgz", - "integrity": "sha512-4z3ac3plDfYzGB6r0Q3LF8POPR20Z8D0aXcxbJvmfMgSSq1hkcgvFRXJk9rUq5H/MJ0Ktal869hhOdI/zUTeLA==", + "version": "1.45.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.1.tgz", + "integrity": "sha512-Hjrgae4kpSQBr98nhCj3IScxVeVUixqj+5oyif8TdIn2opTCPEzqAqNMeK42i3cWDCVu9MI+ZsGWw+gVR4ISBg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.45.0" + "playwright-core": "1.45.1" }, "bin": { "playwright": "cli.js" @@ -2901,9 +2901,9 @@ } }, "node_modules/playwright-core": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.0.tgz", - "integrity": "sha512-lZmHlFQ0VYSpAs43dRq1/nJ9G/6SiTI7VPqidld9TDefL9tX87bTKExWZZUF5PeRyqtXqd8fQi2qmfIedkwsNQ==", + "version": "1.45.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.1.tgz", + "integrity": "sha512-LF4CUUtrUu2TCpDw4mcrAIuYrEjVDfT1cHbJMfwnE2+1b8PZcFzPNgvZCvq2JfQ4aTjRCCHw5EJ2tmr2NSzdPg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4189,9 +4189,9 @@ "license": "ISC" }, "node_modules/typescript": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", - "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/pyscript.core/package.json b/pyscript.core/package.json index d84a354d81b..fae499830c7 100644 --- a/pyscript.core/package.json +++ b/pyscript.core/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/core", - "version": "0.4.53", + "version": "0.4.55", "type": "module", "description": "PyScript", "module": "./index.js", @@ -54,8 +54,8 @@ "@codemirror/lang-python": "^6.1.6", "@codemirror/language": "^6.10.2", "@codemirror/state": "^6.4.1", - "@codemirror/view": "^6.28.2", - "@playwright/test": "^1.45.0", + "@codemirror/view": "^6.28.3", + "@playwright/test": "^1.45.1", "@rollup/plugin-commonjs": "^26.0.1", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", @@ -65,13 +65,13 @@ "bun": "^1.1.17", "chokidar": "^3.6.0", "codemirror": "^6.0.1", - "eslint": "^9.5.0", + "eslint": "^9.6.0", "flatted": "^3.3.1", "rollup": "^4.18.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-string": "^3.0.0", "static-handler": "^0.4.3", - "typescript": "^5.5.2", + "typescript": "^5.5.3", "xterm": "^5.3.0", "xterm-readline": "^1.1.1" }, diff --git a/pyscript.core/src/plugins/py-terminal/mpy.js b/pyscript.core/src/plugins/py-terminal/mpy.js index 6e4a163eed1..deb1cfeb34e 100644 --- a/pyscript.core/src/plugins/py-terminal/mpy.js +++ b/pyscript.core/src/plugins/py-terminal/mpy.js @@ -49,11 +49,12 @@ const workerReady = ({ interpreter, io, run, type }, { sync }) => { const writer = encoder.writable.getWriter(); sync.pyterminal_stream_write = (buffer) => writer.write(buffer); - pyterminal_ready(); interpreter.replInit(); }, }); + + pyterminal_ready(); }; export default async (element) => { @@ -163,13 +164,25 @@ export default async (element) => { }; terminal.onData((buffer) => { if (promisedChunks) { - readChunks += buffer; - terminal.write(buffer); - if (readChunks.endsWith("\r")) { - terminal.write("\n"); - promisedChunks.resolve(readChunks.slice(0, -1)); - promisedChunks = null; - readChunks = ""; + // handle backspace on input + if (buffer === "\x7f") { + // avoid over-greedy backspace + if (readChunks.length) { + readChunks = readChunks.slice(0, -1); + // override previous char position + // put an empty space to clear the char + // move back position again + buffer = "\b \b"; + } else buffer = ""; + } else readChunks += buffer; + if (buffer) { + terminal.write(buffer); + if (readChunks.endsWith("\r")) { + terminal.write("\n"); + promisedChunks.resolve(readChunks.slice(0, -1)); + promisedChunks = null; + readChunks = ""; + } } } else { stream.write(buffer); diff --git a/pyscript.core/test/py-terminals.html b/pyscript.core/test/py-terminals.html index ff72c5516a1..a846ea7c8ca 100644 --- a/pyscript.core/test/py-terminals.html +++ b/pyscript.core/test/py-terminals.html @@ -9,7 +9,7 @@ - + + + + + + + diff --git a/pyscript.core/test/py-terminals/repl.html b/pyscript.core/test/py-terminals/repl.html new file mode 100644 index 00000000000..ee64bfe8aad --- /dev/null +++ b/pyscript.core/test/py-terminals/repl.html @@ -0,0 +1,28 @@ + + + + + + PyTerminal Prompt: REPL + + + + + + + + From f8f7ba89c1a7d267f0ae742d4752c8d01c23a545 Mon Sep 17 00:00:00 2001 From: Fabio Pliger Date: Wed, 3 Jul 2024 17:21:23 -0400 Subject: [PATCH 073/179] Cleanup pyscript web elements (#2094) * change pydom example to use new pyscript.web namespace * change tests to use new pyscript.web namespace * create new pyscript.web package and move pydom to pyscript.web.dom * add __init__ to pyscript.web and expose the dom instance instead of the pyscript.web.dom module * move elements from pyweb.ui to pyscript.web and temp fix pydom import * moved of elements file completed * moved media from pyweb to pyscript.web * RIP pyweb * move JSProperty from pyscript.web.dom to pyscript.web.elements * move element classes from pyscript.web.dom to pyscript.web.elements * first round of fixes while running tests * fix test typo * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * restore right type type returned for Element.parent. ALL TESTS PASS LOCALLY NOW * lint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * clean up dom.py from dead commented code and osbolete comments * bugfix: dom shouldn't return None when it can't find any element for a specific selector so it now returns an empty collection * additional cleanup in tests * lint * initial cleaning up of unused modules * change element.append to not consider types anymore and add tests for appending elements.Element or a JsProxy object * add Element.append tests for append JS elements directly and appending nodeList as well * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Tag and create the correct subclass of Element. * Move: Element.snap -> video.snap * Move: Element.download and draw to canvas.download and draw. * Minor cleanups. * Commenting. * Allow css classes to be passed to Element constructor. * Commenting. * Typo fix. * Make html, id and text JSProperties. * Commenting. * Remove unnecessary selected attribute on BaseElement. * Extract: BaseElement.from_js -> element_from_js * Pass *args and **kwargs to element_from_js and remove BaseElement.create * Move value attribute to specific Element subclasses. * fix: wrapping of existing js elements. * Add body and head elements so parent and children work everywhere. * Revert order of HasOptions mixin for the select element. * Comment out tests that are no longer relevant (see comment). * Use correct super args in mixin. * Have to use element_from_js when returning options from OptionsProxy. * rename: StyleProxy -> Style, OptionsProxy -> Options and added Classes. * Remove cached_property. * Remove list-y methods from Classes collection. * Allow explicit children or *args for containers. * controversial: fix tests to use find rather than dom * Add html element so (say) body.parent does what is expected. * Collapse Element class hierarchy. * rename: js_element -> dom_element * rename: element_from_js -> element_from_dom * replace: JS with DOM * rename: _js -> _dom_element * fix dom tests. * Complete element list with void elements derived from Element. * Added attributes to the newly added Element subclasses. * remove dom module, replace with instance. Also, remove media :) * fix: typo in test for 'b' element. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Remove dom and media modules. * fix up ts definitions. * Added missing import (used in content property). * Added TODO :) * wip: Add ClassesCollection * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Attempt to ask black to leave class list alone. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add classes attribute to ElementCollection * wip: work on classes collection * Extract code to get set of all class names in ClassesCollection. * Update elements.py * Polishing. * Make children return an ElementCollection * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * wip: Add the ability to set multiple properties. * Add __getitem__ back to the dom object. * Put validation when setting DOM properties back in. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * All tests green. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Remove unnecessary comment. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Martin --- .../src/stdlib/pyscript/event_handling.py | 25 +- .../src/stdlib/pyscript/web/__init__.py | 22 +- pyscript.core/src/stdlib/pyscript/web/dom.py | 21 - .../src/stdlib/pyscript/web/elements.py | 1621 +++++++++-------- .../src/stdlib/pyscript/web/media.py | 95 - pyscript.core/src/stdlib/pyweb/__init__.py | 2 - pyscript.core/src/stdlib/pyweb/media.py | 95 - pyscript.core/src/stdlib/pyweb/pydom.py | 569 ------ pyscript.core/src/stdlib/pyweb/ui/__init__.py | 1 - pyscript.core/src/stdlib/pyweb/ui/elements.py | 947 ---------- pyscript.core/test/pydom.py | 11 +- .../test/pyscript_dom/tests/test_dom.py | 245 +-- pyscript.core/tests/integration/test_pyweb.py | 213 ++- pyscript.core/types/stdlib/pyscript.d.ts | 11 - 14 files changed, 1267 insertions(+), 2611 deletions(-) delete mode 100644 pyscript.core/src/stdlib/pyscript/web/dom.py delete mode 100644 pyscript.core/src/stdlib/pyscript/web/media.py delete mode 100644 pyscript.core/src/stdlib/pyweb/__init__.py delete mode 100644 pyscript.core/src/stdlib/pyweb/media.py delete mode 100644 pyscript.core/src/stdlib/pyweb/pydom.py delete mode 100644 pyscript.core/src/stdlib/pyweb/ui/__init__.py delete mode 100644 pyscript.core/src/stdlib/pyweb/ui/elements.py diff --git a/pyscript.core/src/stdlib/pyscript/event_handling.py b/pyscript.core/src/stdlib/pyscript/event_handling.py index 6c2339402eb..e3d388d9076 100644 --- a/pyscript.core/src/stdlib/pyscript/event_handling.py +++ b/pyscript.core/src/stdlib/pyscript/event_handling.py @@ -19,22 +19,23 @@ def when(event_type=None, selector=None): """ def decorator(func): + + from pyscript.web.elements import Element, ElementCollection + if isinstance(selector, str): elements = document.querySelectorAll(selector) + # TODO: This is a hack that will be removed when pyscript becomes a package + # and we can better manage the imports without circular dependencies + elif isinstance(selector, Element): + elements = [selector._dom_element] + elif isinstance(selector, ElementCollection): + elements = [el._dom_element for el in selector] else: - # TODO: This is a hack that will be removed when pyscript becomes a package - # and we can better manage the imports without circular dependencies - from pyweb import pydom - - if isinstance(selector, pydom.Element): - elements = [selector._js] - elif isinstance(selector, pydom.ElementCollection): - elements = [el._js for el in selector] + if isinstance(selector, list): + elements = selector else: - raise ValueError( - f"Invalid selector: {selector}. Selector must" - " be a string, a pydom.Element or a pydom.ElementCollection." - ) + elements = [selector] + try: sig = inspect.signature(func) # Function doesn't receive events diff --git a/pyscript.core/src/stdlib/pyscript/web/__init__.py b/pyscript.core/src/stdlib/pyscript/web/__init__.py index 2aa24957172..996ecc6496e 100644 --- a/pyscript.core/src/stdlib/pyscript/web/__init__.py +++ b/pyscript.core/src/stdlib/pyscript/web/__init__.py @@ -1,5 +1,19 @@ -from . import elements +from pyscript import document +from pyscript.web.elements import ElementCollection, element_from_dom -# Ugly trick to hide the dom module in the web package since we want the module -# to allow querying right away. -from .dom import dom + +class DOM: + def __init__(self): + self.body = element_from_dom(document.body) + self.head = element_from_dom(document.head) + + def __getitem__(self, selector): + return self.find(selector) + + def find(self, selector): + return ElementCollection( + [element_from_dom(el) for el in document.querySelectorAll(selector)] + ) + + +dom = DOM() diff --git a/pyscript.core/src/stdlib/pyscript/web/dom.py b/pyscript.core/src/stdlib/pyscript/web/dom.py deleted file mode 100644 index 95d3398ad93..00000000000 --- a/pyscript.core/src/stdlib/pyscript/web/dom.py +++ /dev/null @@ -1,21 +0,0 @@ -from pyscript import document -from pyscript.web.elements import Element, ElementCollection - - -class PyDom: - # Add objects we want to expose to the DOM namespace since this class instance is being - # remapped as "the module" itself - ElementCollection = ElementCollection - - def __init__(self): - self._js = document - - self.body = Element(document.body) - self.head = Element(document.head) - - def __getitem__(self, key): - elements = self._js.querySelectorAll(key) - return ElementCollection([Element(el) for el in elements]) - - -dom = PyDom() diff --git a/pyscript.core/src/stdlib/pyscript/web/elements.py b/pyscript.core/src/stdlib/pyscript/web/elements.py index cc4b2bbf995..6565464f0d3 100644 --- a/pyscript.core/src/stdlib/pyscript/web/elements.py +++ b/pyscript.core/src/stdlib/pyscript/web/elements.py @@ -18,23 +18,7 @@ def warn(*args, **kwargs): print("WARNING: ", *args, **kwargs) -try: - from functools import cached_property -except ImportError: - # TODO: same comment about micropython as above - cached_property = property - -try: - from pyodide.ffi import JsProxy -except ImportError: - # TODO: same comment about micropython as above - def JsProxy(obj): - return obj - - -from pyscript import document, window - -# from pyscript.web import dom as pydom +from pyscript import document #: A flag to show if MicroPython is the current Python interpreter. is_micropython = "MicroPython" in sys.version @@ -49,330 +33,328 @@ def getmembers_static(cls): return inspect.getmembers_static(cls) -class JSProperty: - """JS property descriptor that directly maps to the property with the same - name in the underlying JS component.""" +class DOMProperty: + """A descriptor representing a DOM property on an Element`. + + This maps a property on an `Element` instance, to the property with the specified + name on the element's underlying DOM element. + """ def __init__(self, name: str, allow_nones: bool = False): self.name = name self.allow_nones = allow_nones def __get__(self, obj, objtype=None): - return getattr(obj._js, self.name) + return getattr(obj._dom_element, self.name) def __set__(self, obj, value): if not self.allow_nones and value is None: return - setattr(obj._js, self.name, value) + setattr(obj._dom_element, self.name, value) -# ------ TODO: REMOVE!!!! pydom elements +def element_from_dom(dom_element): + """Create an instance of the appropriate subclass of `Element` for a DOM element. + If the DOM element was created via an `Element` (i.e. by us) it will have a data + attribute named `data-pyscript-type` that contains the name of the subclass + that created it. If the `data-pyscript-type` attribute *is* present we look up the + subclass by name and create an instance of that. Otherwise, we make a 'best-guess' + and look up the `Element` subclass by the DOM element's tag name (this is NOT + fool-proof as many subclasses might use a `
`, but close enough for jazz). + """ -class BaseElement: - def __init__(self, js_element): - self._js = js_element - self._parent = None - self.style = StyleProxy(self) - self._proxies = {} + # We use "getAttribute" here instead of `js_element.dataset.pyscriptType` as the + # latter throws an `AttributeError` if the value isn't set. This way we just get + # `None` which seems cleaner. + cls_name = dom_element.getAttribute("data-pyscript-type") + if cls_name: + cls = ELEMENT_CLASSES_BY_NAME.get(cls_name.lower()) - def __eq__(self, obj): - """Check if the element is the same as the other element by comparing - the underlying JS element""" - return isinstance(obj, BaseElement) and obj._js == self._js + else: + cls = ELEMENT_CLASSES_BY_TAG.get(dom_element.tagName.lower()) - @property - def parent(self): - if self._parent: - return self._parent + # For any unknown elements (custom tags etc.) create an instance of the 'Element' + # class. + if not cls: + cls = Element - if self._js.parentElement: - # TODO: This should actually return the correct class (== to tagName) - self._parent = Element(self._js.parentElement) + return cls(dom_element=dom_element) - return self._parent - # @property - # def __class(self): - # return self.__class__ if self.__class__ != PyDom else Element +class Element: + tag = "div" + + # GLOBAL ATTRIBUTES. + # These are attribute that all elements have (this list is a subset of the official + # one). We are trying to capture the most used ones. + accesskey = DOMProperty("accesskey") + autofocus = DOMProperty("autofocus") + autocapitalize = DOMProperty("autocapitalize") + className = DOMProperty("className") + contenteditable = DOMProperty("contenteditable") + draggable = DOMProperty("draggable") + enterkeyhint = DOMProperty("enterkeyhint") + hidden = DOMProperty("hidden") + innerHTML = DOMProperty("innerHTML") + id = DOMProperty("id") + lang = DOMProperty("lang") + nonce = DOMProperty("nonce") + part = DOMProperty("part") + popover = DOMProperty("popover") + slot = DOMProperty("slot") + spellcheck = DOMProperty("spellcheck") + tabindex = DOMProperty("tabindex") + text = DOMProperty("textContent") + title = DOMProperty("title") + translate = DOMProperty("translate") + virtualkeyboardpolicy = DOMProperty("virtualkeyboardpolicy") + + def __init__(self, dom_element=None, classes=None, style=None, **kwargs): + """Create a new, or wrap an existing DOM element. + + If `dom_element` is None we are being called to *create* a new element. + Otherwise, we are being called to *wrap* an existing DOM element. + """ + self._dom_element = dom_element or document.createElement(self.tag) - def create(self, type_, is_child=True, classes=None, html=None, label=None): - js_el = document.createElement(type_) - element = self.__class(js_el) + # Tag the DOM element with our class name. + # + # Using the `dataset` attribute is how you programmatically add `data-xxx` + # attributes to a DOM element. In this case it will set an attribute that + # appears in (say) the devtools as `data-pyscript-type`. + self._dom_element.dataset.pyscriptType = type(self).__name__ - if classes: - for class_ in classes: - element.add_class(class_) + self._parent = None + self._classes = Classes(self) + self._style = Style(self) - if html is not None: - element.html = html + # Set any specified classes, styles, and DOM properties. + self.update(classes=classes, style=style, **kwargs) - if label is not None: - element.label = label + def update(self, classes=None, style=None, **kwargs): + """Update the element with the specified classes, styles, and DOM properties.""" - if is_child: - self.append(element) + if classes: + self.classes.add(classes) - return element + # Set any specified styles. + if isinstance(style, dict): + self.style.set(**style) - def find(self, selector): - """Return an ElementCollection representing all the child elements that - match the specified selector. + elif style is not None: + raise ValueError( + f"Style should be a dictionary, received {style} (type {type(style)}) instead." + ) - Args: - selector (str): A string containing a selector expression + self._set_dom_properties(**kwargs) - Returns: - ElementCollection: A collection of elements matching the selector + def _set_dom_properties(self, **kwargs): + """Set all the properties (of type DOMProperty) provided in input as properties + of the class instance. + + Args: + **kwargs: The properties to set """ - elements = self._js.querySelectorAll(selector) - if not elements: - return None - return ElementCollection([Element(el) for el in elements]) + dom_properties = { + attribute_name: attribute_value + for attribute_name, attribute_value in getmembers_static(self.__class__) + if isinstance(attribute_value, DOMProperty) + } + + for name, value in kwargs.items(): + if name not in dom_properties: + raise ValueError(f"'{name}' is not a DOM property.") + + try: + setattr(self, name, value) + except Exception as e: + print(f"Error setting {name} to {value}: {e}") + raise + def __eq__(self, obj): + """Check for equality by comparing the underlying DOM element.""" + return isinstance(obj, Element) and obj._dom_element == self._dom_element -class Element(BaseElement): @property def children(self): - return [self.__class__(el) for el in self._js.children] - - def append(self, child): - # TODO: this is Pyodide specific for now!!!!!! - # if we get passed a JSProxy Element directly we just map it to the - # higher level Python element - if inspect.isclass(JsProxy) and isinstance(child, JsProxy): - return self.append(Element(child)) - - elif isinstance(child, Element): - self._js.appendChild(child._js) + return ElementCollection( + [element_from_dom(el) for el in self._dom_element.children] + ) - return child - - elif isinstance(child, ElementCollection): - for el in child: - self.append(el) - - # -------- Pythonic Interface to Element -------- # @property - def html(self): - return self._js.innerHTML - - @html.setter - def html(self, value): - self._js.innerHTML = value + def classes(self): + return self._classes @property - def text(self): - return self._js.textContent + def parent(self): + if self._parent: + return self._parent + + if self._dom_element.parentElement: + self._parent = element_from_dom(self._dom_element.parentElement) - @text.setter - def text(self, value): - self._js.textContent = value + return self._parent @property - def content(self): - # TODO: This breaks with with standard template elements. Define how to best - # handle this specifica use case. Just not support for now? - if self._js.tagName == "TEMPLATE": - warnings.warn( - "Content attribute not supported for template elements.", stacklevel=2 - ) - return None - return self._js.innerHTML - - @content.setter - def content(self, value): - # TODO: (same comment as above) - if self._js.tagName == "TEMPLATE": - warnings.warn( - "Content attribute not supported for template elements.", stacklevel=2 - ) - return + def style(self): + return self._style - display(value, target=self.id) + def append(self, child): + if isinstance(child, Element): + self._dom_element.appendChild(child._dom_element) - @property - def id(self): - return self._js.id + elif isinstance(child, ElementCollection): + for el in child: + self._dom_element.appendChild(el._dom_element) - @id.setter - def id(self, value): - self._js.id = value + else: + # In this case we know it's not an Element or an ElementCollection, so we + # guess that it's either a DOM element or NodeList returned via the ffi. + try: + # First, we try to see if it's an element by accessing the 'tagName' + # attribute. + child.tagName + self._dom_element.appendChild(child) + + except AttributeError: + try: + # Ok, it's not an element, so let's see if it's a NodeList by + # accessing the 'length' attribute. + child.length + for element_ in child: + self._dom_element.appendChild(element_) + + except AttributeError: + # Nope! This is not an element or a NodeList. + raise TypeError( + f'Element "{child}" is a proxy object, but not a valid element or a NodeList.' + ) + + def clone(self, clone_id=None): + """Make a clone of the element (clones the underlying DOM object too).""" + clone = element_from_dom(self._dom_element.cloneNode(True)) + clone.id = clone_id + return clone - @property - def options(self): - if "options" in self._proxies: - return self._proxies["options"] + def find(self, selector): + """Return an ElementCollection representing all the child elements that + match the specified selector. - if not self._js.tagName.lower() in {"select", "datalist", "optgroup"}: - raise AttributeError( - f"Element {self._js.tagName} has no options attribute." - ) - self._proxies["options"] = OptionsProxy(self) - return self._proxies["options"] + Args: + selector (str): A string containing a selector expression - @property - def value(self): - return self._js.value + Returns: + ElementCollection: A collection of elements matching the selector + """ + return ElementCollection( + [ + element_from_dom(el) + for el in self._dom_element.querySelectorAll(selector) + ] + ) - @value.setter - def value(self, value): - # in order to avoid confusion to the user, we don't allow setting the - # value of elements that don't have a value attribute - if not hasattr(self._js, "value"): - raise AttributeError( - f"Element {self._js.tagName} has no value attribute. If you want to " - "force a value attribute, set it directly using the `_js.value = ` " - "javascript API attribute instead." - ) - self._js.value = value + def show_me(self): + """Scroll the element into view.""" + self._dom_element.scrollIntoView() - @property - def selected(self): - return self._js.selected - - @selected.setter - def selected(self, value): - # in order to avoid confusion to the user, we don't allow setting the - # value of elements that don't have a value attribute - if not hasattr(self._js, "selected"): - raise AttributeError( - f"Element {self._js.tagName} has no value attribute. If you want to " - "force a value attribute, set it directly using the `_js.value = ` " - "javascript API attribute instead." - ) - self._js.selected = value - def clone(self, new_id=None): - clone = Element(self._js.cloneNode(True)) - clone.id = new_id +class Classes: + """A set-like interface to an element's `classList`.""" - return clone + def __init__(self, element: Element): + self._element = element + self._class_list = self._element._dom_element.classList - def remove_class(self, classname): - classList = self._js.classList - if isinstance(classname, list): - classList.remove(*classname) - else: - classList.remove(classname) - return self + def __contains__(self, item): + return item in self._class_list - def add_class(self, classname): - classList = self._js.classList - if isinstance(classname, list): - classList.add(*classname) + def __eq__(self, other): + # We allow comparison with either another `Classes` instance... + if isinstance(other, Classes): + compare_with = list(other._class_list) + + # ...or iterables of strings. else: - self._js.classList.add(classname) - return self + # TODO: Check MP for existence of better iterable test. + try: + compare_with = iter(other) - @property - def classes(self): - classes = self._js.classList.values() - return [x for x in classes] + except TypeError: + return False - def show_me(self): - self._js.scrollIntoView() + return set(self._class_list) == set(compare_with) - def snap( - self, - to: BaseElement | str = None, - width: int | None = None, - height: int | None = None, - ): - """ - Captures a snapshot of a video element. (Only available for video elements) + def __iter__(self): + return iter(self._class_list) - Inputs: + def __len__(self): + return self._class_list.length - * to: element where to save the snapshot of the video frame to - * width: width of the image - * height: height of the image + def __repr__(self): + return f"Classes({', '.join(self._class_list)})" - Output: - (Element) canvas element where the video frame snapshot was drawn into - """ - if self._js.tagName != "VIDEO": - raise AttributeError("Snap method is only available for video Elements") + def __str__(self): + return " ".join(self._class_list) - if to is None: - canvas = self.create("canvas") - if width is None: - width = self._js.width - if height is None: - height = self._js.height - canvas._js.width = width - canvas._js.height = height + def add(self, *class_names): + for class_name in class_names: + if isinstance(class_name, list): + for item in class_name: + self.add(item) - elif isinstance(to, Element): - if to._js.tagName != "CANVAS": - raise TypeError("Element to snap to must a canvas.") - canvas = to - elif getattr(to, "tagName", "") == "CANVAS": - canvas = Element(to) - elif isinstance(to, str): - # TODO (fpliger): This needs a better fix but doing a local import here for a quick fix - from pyscript.web import dom + else: + self._class_list.add(class_name) - canvas = dom[to][0] - if canvas._js.tagName != "CANVAS": - raise TypeError("Element to snap to must a be canvas.") + def contains(self, class_name): + return class_name in self - canvas.draw(self, width, height) + def remove(self, *class_names): + for class_name in class_names: + if isinstance(class_name, list): + for item in class_name: + self.remove(item) - return canvas + else: + self._class_list.remove(class_name) - def download(self, filename: str = "snapped.png") -> None: - """Download the current element (only available for canvas elements) with the filename - provided in input. + def replace(self, old_class, new_class): + self.remove(old_class) + self.add(new_class) - Inputs: - * filename (str): name of the file being downloaded + def toggle(self, class_name): + if class_name in self: + self.remove(class_name) + return False - Output: - None - """ - if self._js.tagName != "CANVAS": - raise AttributeError( - "The download method is only available for canvas Elements" - ) + self.add(class_name) + return True - link = self.create("a") - link._js.download = filename - link._js.href = self._js.toDataURL() - link._js.click() - def draw(self, what, width, height): - """Draw `what` on the current element (only available for canvas elements). +class HasOptions: + """Mix-in for elements that have an options attribute. - Inputs: + The elements that support options are: , , and + element. -class OptionsProxy: - """This class represents the options of a select element. It - allows to access to add and remove options by using the `add` and `remove` methods. + It allows to access to add and remove