mirror of
https://github.com/pyscript/pyscript.git
synced 2026-02-13 07:01:00 -05:00
[next] Dispatch ready event for the custom py type (#1694)
This commit is contained in:
committed by
GitHub
parent
f376097a15
commit
7994207c78
46
pyscript.core/package-lock.json
generated
46
pyscript.core/package-lock.json
generated
@@ -1,22 +1,22 @@
|
||||
{
|
||||
"name": "@pyscript/core",
|
||||
"version": "0.1.17",
|
||||
"version": "0.1.18",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@pyscript/core",
|
||||
"version": "0.1.17",
|
||||
"version": "0.1.18",
|
||||
"license": "APACHE-2.0",
|
||||
"dependencies": {
|
||||
"@ungap/with-resolvers": "^0.1.0",
|
||||
"basic-devtools": "^0.1.6",
|
||||
"polyscript": "^0.3.1"
|
||||
"polyscript": "^0.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-node-resolve": "^15.2.1",
|
||||
"@rollup/plugin-terser": "^0.4.3",
|
||||
"rollup": "^3.29.0",
|
||||
"rollup": "^3.29.1",
|
||||
"rollup-plugin-postcss": "^4.0.2",
|
||||
"rollup-plugin-string": "^3.0.0",
|
||||
"static-handler": "^0.4.2",
|
||||
@@ -282,9 +282,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001528",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001528.tgz",
|
||||
"integrity": "sha512-0Db4yyjR9QMNlsxh+kKWzQtkyflkG/snYheSzkjmvdEtEXB1+jt7A2HmSEiO6XIJPIbo92lHNGNySvE5pZcs5Q==",
|
||||
"version": "1.0.30001534",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001534.tgz",
|
||||
"integrity": "sha512-vlPVrhsCS7XaSh2VvWluIQEzVhefrUQcEsQWSS5A5V+dM07uv1qHeQzAOTGIMy9i3e9bH15+muvI/UHojVgS/Q==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -326,9 +326,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/coincident": {
|
||||
"version": "0.11.5",
|
||||
"resolved": "https://registry.npmjs.org/coincident/-/coincident-0.11.5.tgz",
|
||||
"integrity": "sha512-aorzP9U2j4JzDj+2I9CM3HaU16J5rmaWptkzHMbgGDmR+c/r8PXJ/2Asq2FImoxIJVfZiMjFt8Vtglan/5i8/A==",
|
||||
"version": "0.11.6",
|
||||
"resolved": "https://registry.npmjs.org/coincident/-/coincident-0.11.6.tgz",
|
||||
"integrity": "sha512-Ld82kMrjDwNjpi+WE2C1v5ADPvOa+NANBWL8o1ohj+UhFTzDX3OMQOE9NSnjbUuMh+U/WBp39+uO2WFs8vJ3sw==",
|
||||
"dependencies": {
|
||||
"@ungap/structured-clone": "^1.2.0",
|
||||
"@ungap/with-resolvers": "^0.1.0"
|
||||
@@ -597,9 +597,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.510",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.510.tgz",
|
||||
"integrity": "sha512-xPfLIPFcN/WLXBpQ/K4UgE98oUBO5Tia6BD4rkSR0wE7ep/PwBVlgvPJQrIBpmJGVAmUzwPKuDbVt9XV6+uC2g==",
|
||||
"version": "1.4.519",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.519.tgz",
|
||||
"integrity": "sha512-kqs9oGYL4UFVkLKhqCTgBCYZv+wZ374yABDMqlDda9HvlkQxvSr7kgf4hfWVjMieDbX+1MwPHFBsOGCMIBaFKg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/entities": {
|
||||
@@ -948,15 +948,15 @@
|
||||
"integrity": "sha512-yyVAOFKTAElc7KdLt2+UKGExNYwYb/Y/WE9i+1ezCQsJE8gbKSjewfpRqK2nQgZ4d4hhAAGgDCOcIZVilqE5UA=="
|
||||
},
|
||||
"node_modules/polyscript": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.3.1.tgz",
|
||||
"integrity": "sha512-9cePhhLMgcUfnBbx8l7zv4N4ZRU18rtJ2QHM0hhoEBeu+Nist485rZ0/n/cLR04xi3yDqifvNWjl+g/Tkx4gnQ==",
|
||||
"version": "0.3.6",
|
||||
"resolved": "https://registry.npmjs.org/polyscript/-/polyscript-0.3.6.tgz",
|
||||
"integrity": "sha512-g5xUYASdftAIzfdr7jIK3zSI5GaePkTaaFjJfApoCpOYOGWkAdAEcb9IKHGlOrhLADkPoQ9YS6YLM9X7h9Z+AQ==",
|
||||
"dependencies": {
|
||||
"@ungap/structured-clone": "^1.2.0",
|
||||
"@ungap/with-resolvers": "^0.1.0",
|
||||
"basic-devtools": "^0.1.6",
|
||||
"codedent": "^0.1.2",
|
||||
"coincident": "^0.11.5"
|
||||
"coincident": "^0.11.6"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
@@ -1564,9 +1564,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "3.29.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.0.tgz",
|
||||
"integrity": "sha512-nszM8DINnx1vSS+TpbWKMkxem0CDWk3cSit/WWCBVs9/JZ1I/XLwOsiUglYuYReaeWWSsW9kge5zE5NZtf/a4w==",
|
||||
"version": "3.29.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.1.tgz",
|
||||
"integrity": "sha512-c+ebvQz0VIH4KhhCpDsI+Bik0eT8ZFEVZEYw0cGMVqIP8zc+gnwl7iXCamTw7vzv2MeuZFZfdx5JJIq+ehzDlg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
@@ -1869,9 +1869,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.14.0.tgz",
|
||||
"integrity": "sha512-WR0RJE9Ehsio6U4TuM+LmunEsjQ5ncHlw4sn9ihD6RoJKZrVyH9FWV3dmnwu8B2aNib1OvG2X6adUCyFpQyWcg==",
|
||||
"version": "8.14.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.14.1.tgz",
|
||||
"integrity": "sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@pyscript/core",
|
||||
"version": "0.1.17",
|
||||
"version": "0.1.18",
|
||||
"type": "module",
|
||||
"description": "PyScript",
|
||||
"module": "./index.js",
|
||||
@@ -32,12 +32,12 @@
|
||||
"dependencies": {
|
||||
"@ungap/with-resolvers": "^0.1.0",
|
||||
"basic-devtools": "^0.1.6",
|
||||
"polyscript": "^0.3.1"
|
||||
"polyscript": "^0.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-node-resolve": "^15.2.1",
|
||||
"@rollup/plugin-terser": "^0.4.3",
|
||||
"rollup": "^3.29.0",
|
||||
"rollup": "^3.29.1",
|
||||
"rollup-plugin-postcss": "^4.0.2",
|
||||
"rollup-plugin-string": "^3.0.0",
|
||||
"static-handler": "^0.4.2",
|
||||
|
||||
@@ -11,7 +11,7 @@ import plugins from "./plugins.js";
|
||||
// TODO: this is not strictly polyscript related but handy ... not sure
|
||||
// we should factor this utility out a part but this works anyway.
|
||||
import { queryTarget } from "../node_modules/polyscript/esm/script-handler.js";
|
||||
import { dedent } from "../node_modules/polyscript/esm/utils.js";
|
||||
import { dedent, dispatch } from "../node_modules/polyscript/esm/utils.js";
|
||||
import { Hook } from "../node_modules/polyscript/esm/worker/hooks.js";
|
||||
|
||||
import { robustFetch as fetch } from "./fetch.js";
|
||||
@@ -193,6 +193,7 @@ define("py", {
|
||||
// before regular stuff happens in here
|
||||
for (const callback of hooks.onInterpreterReady)
|
||||
callback(pyodide, element);
|
||||
|
||||
if (isScript(element)) {
|
||||
const {
|
||||
attributes: { async: isAsync, target },
|
||||
@@ -213,6 +214,8 @@ define("py", {
|
||||
// document.currentScript.target if needed
|
||||
defineProperty(element, "target", { value: show });
|
||||
|
||||
// notify before the code runs
|
||||
dispatch(element, "py");
|
||||
pyodide[`run${isAsync ? "Async" : ""}`](
|
||||
await fetchSource(element, pyodide.io, true),
|
||||
);
|
||||
@@ -245,6 +248,8 @@ class PyScriptElement extends HTMLElement {
|
||||
const runner = this.hasAttribute("async") ? runAsync : run;
|
||||
this.srcCode = await fetchSource(this, io, !this.childElementCount);
|
||||
this.replaceChildren();
|
||||
// notify before the code runs
|
||||
dispatch(this, "py");
|
||||
runner(this.srcCode);
|
||||
this.style.display = "block";
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ export default {
|
||||
"_pyscript": {
|
||||
"__init__.py": "import js as window\n\nIS_WORKER = not hasattr(window, \"document\")\n\nif IS_WORKER:\n from polyscript import xworker as _xworker\n\n window = _xworker.window\n document = window.document\n sync = _xworker.sync\nelse:\n document = window.document\n",
|
||||
"display.py": "import base64\nimport html\nimport io\nimport re\n\nfrom . import document, window\n\n_MIME_METHODS = {\n \"__repr__\": \"text/plain\",\n \"_repr_html_\": \"text/html\",\n \"_repr_markdown_\": \"text/markdown\",\n \"_repr_svg_\": \"image/svg+xml\",\n \"_repr_png_\": \"image/png\",\n \"_repr_pdf_\": \"application/pdf\",\n \"_repr_jpeg_\": \"image/jpeg\",\n \"_repr_latex\": \"text/latex\",\n \"_repr_json_\": \"application/json\",\n \"_repr_javascript_\": \"application/javascript\",\n \"savefig\": \"image/png\",\n}\n\n\ndef _render_image(mime, value, meta):\n # If the image value is using bytes we should convert it to base64\n # otherwise it will return raw bytes and the browser will not be able to\n # render it.\n if isinstance(value, bytes):\n value = base64.b64encode(value).decode(\"utf-8\")\n\n # This is the pattern of base64 strings\n base64_pattern = re.compile(\n r\"^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$\"\n )\n # If value doesn't match the base64 pattern we should encode it to base64\n if len(value) > 0 and not base64_pattern.match(value):\n value = base64.b64encode(value.encode(\"utf-8\")).decode(\"utf-8\")\n\n data = f\"data:{mime};charset=utf-8;base64,{value}\"\n attrs = \" \".join(['{k}=\"{v}\"' for k, v in meta.items()])\n return f'<img src=\"{data}\" {attrs}></img>'\n\n\ndef _identity(value, meta):\n return value\n\n\n_MIME_RENDERERS = {\n \"text/plain\": html.escape,\n \"text/html\": _identity,\n \"image/png\": lambda value, meta: _render_image(\"image/png\", value, meta),\n \"image/jpeg\": lambda value, meta: _render_image(\"image/jpeg\", value, meta),\n \"image/svg+xml\": _identity,\n \"application/json\": _identity,\n \"application/javascript\": lambda value, meta: f\"<script>{value}<\\\\/script>\",\n}\n\n\nclass HTML:\n \"\"\"\n Wrap a string so that display() can render it as plain HTML\n \"\"\"\n\n def __init__(self, html):\n self._html = html\n\n def _repr_html_(self):\n return self._html\n\n\ndef _eval_formatter(obj, print_method):\n \"\"\"\n Evaluates a formatter method.\n \"\"\"\n if print_method == \"__repr__\":\n return repr(obj)\n elif hasattr(obj, print_method):\n if print_method == \"savefig\":\n buf = io.BytesIO()\n obj.savefig(buf, format=\"png\")\n buf.seek(0)\n return base64.b64encode(buf.read()).decode(\"utf-8\")\n return getattr(obj, print_method)()\n elif print_method == \"_repr_mimebundle_\":\n return {}, {}\n return None\n\n\ndef _format_mime(obj):\n \"\"\"\n Formats object using _repr_x_ methods.\n \"\"\"\n if isinstance(obj, str):\n return html.escape(obj), \"text/plain\"\n\n mimebundle = _eval_formatter(obj, \"_repr_mimebundle_\")\n if isinstance(mimebundle, tuple):\n format_dict, _ = mimebundle\n else:\n format_dict = mimebundle\n\n output, not_available = None, []\n for method, mime_type in reversed(_MIME_METHODS.items()):\n if mime_type in format_dict:\n output = format_dict[mime_type]\n else:\n output = _eval_formatter(obj, method)\n\n if output is None:\n continue\n elif mime_type not in _MIME_RENDERERS:\n not_available.append(mime_type)\n continue\n break\n if output is None:\n if not_available:\n window.console.warn(\n f\"Rendered object requested unavailable MIME renderers: {not_available}\"\n )\n output = repr(output)\n mime_type = \"text/plain\"\n elif isinstance(output, tuple):\n output, meta = output\n else:\n meta = {}\n return _MIME_RENDERERS[mime_type](output, meta), mime_type\n\n\ndef _write(element, value, append=False):\n html, mime_type = _format_mime(value)\n if html == \"\\\\n\":\n return\n\n if append:\n out_element = document.createElement(\"div\")\n element.append(out_element)\n else:\n out_element = element.lastElementChild\n if out_element is None:\n out_element = element\n\n if mime_type in (\"application/javascript\", \"text/html\"):\n script_element = document.createRange().createContextualFragment(html)\n out_element.append(script_element)\n else:\n out_element.innerHTML = html\n\n\ndef display(*values, target=None, append=True):\n element = document.getElementById(target)\n for v in values:\n _write(element, v, append=append)\n",
|
||||
"event_handling.py": "import inspect\n\nfrom pyscript import document\nfrom pyodide.ffi.wrappers import add_event_listener\n\n\ndef when(event_type=None, selector=None):\n \"\"\"\n Decorates a function and passes py-* events to the decorated function\n The events might or not be an argument of the decorated function\n \"\"\"\n\n def decorator(func):\n elements = document.querySelectorAll(selector)\n sig = inspect.signature(func)\n # Function doesn't receive events\n if not sig.parameters:\n\n def wrapper(*args, **kwargs):\n func()\n\n for el in elements:\n add_event_listener(el, event_type, wrapper)\n else:\n for el in elements:\n add_event_listener(el, event_type, func)\n return func\n\n return decorator\n"
|
||||
"event_handling.py": "import inspect\n\nfrom pyodide.ffi.wrappers import add_event_listener\nfrom pyscript import document\n\n\ndef when(event_type=None, selector=None):\n \"\"\"\n Decorates a function and passes py-* events to the decorated function\n The events might or not be an argument of the decorated function\n \"\"\"\n\n def decorator(func):\n elements = document.querySelectorAll(selector)\n sig = inspect.signature(func)\n # Function doesn't receive events\n if not sig.parameters:\n\n def wrapper(*args, **kwargs):\n func()\n\n for el in elements:\n add_event_listener(el, event_type, wrapper)\n else:\n for el in elements:\n add_event_listener(el, event_type, func)\n return func\n\n return decorator\n"
|
||||
},
|
||||
"pyscript.py": "# export only what we want to expose as `pyscript` module\n# but not what is WORKER/MAIN dependent\nfrom _pyscript import window, document, IS_WORKER\nfrom _pyscript.display import HTML, display as _display\nfrom _pyscript.event_handling import when\n\n# this part is needed to disambiguate between MAIN and WORKER\nif IS_WORKER:\n # in workers the display does not have a default ID\n # but there is a sync utility from xworker\n import polyscript as _polyscript\n from _pyscript import sync\n\n def current_target():\n return _polyscript.target\n\nelse:\n # in MAIN both PyWorker and current element target exist\n # so these are both exposed and the display will use,\n # if not specified otherwise, such current element target\n import _pyscript_js\n\n PyWorker = _pyscript_js.PyWorker\n\n def current_target():\n return _pyscript_js.target\n\n\n# the display provides a handy default target either in MAIN or WORKER\ndef display(*values, target=None, append=True):\n if target is None:\n target = current_target()\n\n return _display(*values, target=target, append=append)\n"
|
||||
};
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>PyScript Next</title>
|
||||
<script>
|
||||
addEventListener("py:ready", console.log);
|
||||
</script>
|
||||
<link rel="stylesheet" href="../dist/core.css">
|
||||
<script type="module" src="../dist/core.js"></script>
|
||||
</head>
|
||||
|
||||
Reference in New Issue
Block a user