mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-19 18:27:29 -05:00
[RC] Ensure dedicated configs per interpreter (#1743)
This commit is contained in:
committed by
GitHub
parent
287d0fa1af
commit
b4c686f411
@@ -1,3 +1,4 @@
|
||||
.pytest_cache/
|
||||
node_modules/
|
||||
rollup/
|
||||
test/
|
||||
|
||||
4
pyscript.core/package-lock.json
generated
4
pyscript.core/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@pyscript/core",
|
||||
"version": "0.2.0",
|
||||
"version": "0.2.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@pyscript/core",
|
||||
"version": "0.2.0",
|
||||
"version": "0.2.2",
|
||||
"license": "APACHE-2.0",
|
||||
"dependencies": {
|
||||
"@ungap/with-resolvers": "^0.1.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@pyscript/core",
|
||||
"version": "0.2.0",
|
||||
"version": "0.2.2",
|
||||
"type": "module",
|
||||
"description": "PyScript",
|
||||
"module": "./index.js",
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
import { $ } from "basic-devtools";
|
||||
|
||||
import TYPES from "./types.js";
|
||||
import allPlugins from "./plugins.js";
|
||||
import { robustFetch as fetch, getText } from "./fetch.js";
|
||||
import { ErrorCode } from "./exceptions.js";
|
||||
@@ -45,66 +46,72 @@ const syntaxError = (type, url, { message }) => {
|
||||
return new SyntaxError(`${str}\n${message}`);
|
||||
};
|
||||
|
||||
// find the shared config for all py-script elements
|
||||
let config, plugins, parsed, error, type;
|
||||
let pyConfig = $("py-config");
|
||||
if (pyConfig) {
|
||||
config = pyConfig.getAttribute("src") || pyConfig.textContent;
|
||||
type = pyConfig.getAttribute("type");
|
||||
} else {
|
||||
pyConfig = $(
|
||||
[
|
||||
'script[type="py"][config]:not([worker])',
|
||||
"py-script[config]:not([worker])",
|
||||
].join(","),
|
||||
);
|
||||
if (pyConfig) config = pyConfig.getAttribute("config");
|
||||
}
|
||||
const configs = new Map();
|
||||
|
||||
// catch possible fetch errors
|
||||
if (config) {
|
||||
try {
|
||||
const { json, toml, text, url } = await configDetails(config);
|
||||
config = text;
|
||||
if (json || type === "json") {
|
||||
try {
|
||||
parsed = JSON.parse(text);
|
||||
} catch (e) {
|
||||
error = syntaxError("JSON", url, e);
|
||||
}
|
||||
} else if (toml || type === "toml") {
|
||||
try {
|
||||
const { parse } = await import(
|
||||
/* webpackIgnore: true */
|
||||
"https://cdn.jsdelivr.net/npm/@webreflection/toml-j0.4/toml.js"
|
||||
);
|
||||
parsed = parse(text);
|
||||
} catch (e) {
|
||||
error = syntaxError("TOML", url, e);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
error = e;
|
||||
for (const [TYPE] of TYPES) {
|
||||
// find the shared config for all py-script elements
|
||||
let config, plugins, parsed, error, type;
|
||||
let pyConfig = $(`${TYPE}-config`);
|
||||
if (pyConfig) {
|
||||
config = pyConfig.getAttribute("src") || pyConfig.textContent;
|
||||
type = pyConfig.getAttribute("type");
|
||||
} else {
|
||||
pyConfig = $(
|
||||
[
|
||||
`script[type="${TYPE}"][config]:not([worker])`,
|
||||
`${TYPE}-script[config]:not([worker])`,
|
||||
].join(","),
|
||||
);
|
||||
if (pyConfig) config = pyConfig.getAttribute("config");
|
||||
}
|
||||
}
|
||||
|
||||
// parse all plugins and optionally ignore only
|
||||
// those flagged as "undesired" via `!` prefix
|
||||
const toBeAwaited = [];
|
||||
for (const [key, value] of Object.entries(allPlugins)) {
|
||||
if (error) {
|
||||
if (key === "error") {
|
||||
// show on page the config is broken, meaning that
|
||||
// it was not possible to disable error plugin neither
|
||||
// as that part wasn't correctly parsed anyway
|
||||
value().then(({ notify }) => notify(error.message));
|
||||
// catch possible fetch errors
|
||||
if (config) {
|
||||
try {
|
||||
const { json, toml, text, url } = await configDetails(config);
|
||||
config = text;
|
||||
if (json || type === "json") {
|
||||
try {
|
||||
parsed = JSON.parse(text);
|
||||
} catch (e) {
|
||||
error = syntaxError("JSON", url, e);
|
||||
}
|
||||
} else if (toml || type === "toml") {
|
||||
try {
|
||||
const { parse } = await import(
|
||||
/* webpackIgnore: true */
|
||||
"https://cdn.jsdelivr.net/npm/@webreflection/toml-j0.4/toml.js"
|
||||
);
|
||||
parsed = parse(text);
|
||||
} catch (e) {
|
||||
error = syntaxError("TOML", url, e);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
} else if (!parsed?.plugins?.includes(`!${key}`)) {
|
||||
toBeAwaited.push(value());
|
||||
}
|
||||
|
||||
// parse all plugins and optionally ignore only
|
||||
// those flagged as "undesired" via `!` prefix
|
||||
const toBeAwaited = [];
|
||||
for (const [key, value] of Object.entries(allPlugins)) {
|
||||
if (error) {
|
||||
if (key === "error") {
|
||||
// show on page the config is broken, meaning that
|
||||
// it was not possible to disable error plugin neither
|
||||
// as that part wasn't correctly parsed anyway
|
||||
value().then(({ notify }) => notify(error.message));
|
||||
}
|
||||
} else if (!parsed?.plugins?.includes(`!${key}`)) {
|
||||
toBeAwaited.push(value());
|
||||
}
|
||||
}
|
||||
|
||||
// assign plugins as Promise.all only if needed
|
||||
if (toBeAwaited.length) plugins = Promise.all(toBeAwaited);
|
||||
|
||||
configs.set(TYPE, { config: parsed, plugins, error });
|
||||
}
|
||||
|
||||
// assign plugins as Promise.all only if needed
|
||||
if (toBeAwaited.length) plugins = Promise.all(toBeAwaited);
|
||||
|
||||
export { parsed as config, plugins, error };
|
||||
export default configs;
|
||||
|
||||
@@ -9,10 +9,11 @@ import { queryTarget } from "../node_modules/polyscript/esm/script-handler.js";
|
||||
import { dedent, dispatch } from "../node_modules/polyscript/esm/utils.js";
|
||||
import { Hook } from "../node_modules/polyscript/esm/worker/hooks.js";
|
||||
|
||||
import { ErrorCode } from "./exceptions.js";
|
||||
import TYPES from "./types.js";
|
||||
import configs from "./config.js";
|
||||
import sync from "./sync.js";
|
||||
import stdlib from "./stdlib.js";
|
||||
import { config, plugins, error } from "./config.js";
|
||||
import { ErrorCode } from "./exceptions.js";
|
||||
import { robustFetch as fetch, getText } from "./fetch.js";
|
||||
|
||||
const { assign, defineProperty } = Object;
|
||||
@@ -20,11 +21,6 @@ const { assign, defineProperty } = Object;
|
||||
// allows lazy element features on code evaluation
|
||||
let currentElement;
|
||||
|
||||
const TYPES = new Map([
|
||||
["py", "pyodide"],
|
||||
["mpy", "micropython"],
|
||||
]);
|
||||
|
||||
// generic helper to disambiguate between custom element and script
|
||||
const isScript = ({ tagName }) => tagName === "SCRIPT";
|
||||
|
||||
@@ -103,7 +99,12 @@ const workerHooks = {
|
||||
[...hooks.codeAfterRunWorkerAsync].map(dedent).join("\n"),
|
||||
};
|
||||
|
||||
const exportedConfig = {};
|
||||
export { exportedConfig as config };
|
||||
|
||||
for (const [TYPE, interpreter] of TYPES) {
|
||||
const { config, plugins, error } = configs.get(TYPE);
|
||||
|
||||
// create a unique identifier when/if needed
|
||||
let id = 0;
|
||||
const getID = (prefix = TYPE) => `${prefix}-${id++}`;
|
||||
@@ -273,6 +274,9 @@ for (const [TYPE, interpreter] of TYPES) {
|
||||
|
||||
// define py-script only if the config didn't throw an error
|
||||
if (!error) customElements.define(`${TYPE}-script`, PyScriptElement);
|
||||
|
||||
// export the used config without allowing leaks through it
|
||||
exportedConfig[TYPE] = structuredClone(config);
|
||||
}
|
||||
|
||||
// TBD: I think manual worker cases are interesting in pyodide only
|
||||
|
||||
4
pyscript.core/src/types.js
Normal file
4
pyscript.core/src/types.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export default new Map([
|
||||
["py", "pyodide"],
|
||||
["mpy", "micropython"],
|
||||
]);
|
||||
20
pyscript.core/test/split-config.html
Normal file
20
pyscript.core/test/split-config.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>PyScript Config</title>
|
||||
<script type="module">
|
||||
import { config } from "../dist/core.js";
|
||||
console.log(config.mpy);
|
||||
</script>
|
||||
<link rel="stylesheet" href="../dist/core.css">
|
||||
<mpy-config>
|
||||
[[fetch]]
|
||||
files = ["a.py"]
|
||||
</mpy-config>
|
||||
<script type="mpy">
|
||||
import a
|
||||
</script>
|
||||
</head>
|
||||
</html>
|
||||
@@ -15,7 +15,7 @@
|
||||
</script>
|
||||
|
||||
<!-- the worker attribute -->
|
||||
<script type="py" worker="./worker.py" config="./config.json"></script>
|
||||
<script type="py" src="./worker.py" config="./config.json" worker></script>
|
||||
|
||||
<!-- this is only to test the non-blocking behavior -->
|
||||
<script>
|
||||
|
||||
6
pyscript.core/types/config.d.ts
vendored
6
pyscript.core/types/config.d.ts
vendored
@@ -1,4 +1,2 @@
|
||||
declare let parsed: any;
|
||||
export let plugins: any;
|
||||
export let error: any;
|
||||
export { parsed as config };
|
||||
export default configs;
|
||||
declare const configs: Map<any, any>;
|
||||
|
||||
3
pyscript.core/types/core.d.ts
vendored
3
pyscript.core/types/core.d.ts
vendored
@@ -21,5 +21,6 @@ export namespace hooks {
|
||||
let codeAfterRunWorker: Set<string>;
|
||||
let codeAfterRunWorkerAsync: Set<string>;
|
||||
}
|
||||
import { config } from "./config.js";
|
||||
export { exportedConfig as config };
|
||||
import sync from "./sync.js";
|
||||
declare const exportedConfig: {};
|
||||
|
||||
2
pyscript.core/types/types.d.ts
vendored
Normal file
2
pyscript.core/types/types.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: Map<string, string>;
|
||||
export default _default;
|
||||
Reference in New Issue
Block a user