Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #1997 - Bring pyscript stdlib to the PyEditor #2010

Merged
merged 4 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
130 changes: 72 additions & 58 deletions pyscript.core/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pyscript.core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pyscript/core",
"version": "0.4.10",
"version": "0.4.11",
"type": "module",
"description": "PyScript",
"module": "./index.js",
Expand Down Expand Up @@ -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",
Expand Down
3 changes: 3 additions & 0 deletions pyscript.core/src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down
35 changes: 30 additions & 5 deletions pyscript.core/src/plugins/py-editor.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
// 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 = `<svg style="height:20px;width:20px;vertical-align:-.125em;transform-origin:center;overflow:visible;color:green" viewBox="0 0 384 512" aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg"><g transform="translate(192 256)" transform-origin="96 0"><g transform="translate(0,0) scale(1,1)"><path d="M361 215C375.3 223.8 384 239.3 384 256C384 272.7 375.3 288.2 361 296.1L73.03 472.1C58.21 482 39.66 482.4 24.52 473.9C9.377 465.4 0 449.4 0 432V80C0 62.64 9.377 46.63 24.52 38.13C39.66 29.64 58.21 29.99 73.03 39.04L361 215z" fill="currentColor" transform="translate(-192 -256)"></path></g></g></svg>`;

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);
Expand All @@ -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();
Expand Down Expand Up @@ -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();
},
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions pyscript.core/test/py-editor/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[js_modules.worker]
"https://cdn.jsdelivr.net/npm/html-escaper/+esm" = "html_escaper"