|
importScripts("https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide.js"); |
|
|
|
function sendPatch(patch, buffers, msg_id) { |
|
self.postMessage({ |
|
type: 'patch', |
|
patch: patch, |
|
buffers: buffers |
|
}) |
|
} |
|
|
|
async function startApplication() { |
|
console.log("Loading pyodide!"); |
|
self.postMessage({type: 'status', msg: 'Loading pyodide'}) |
|
self.pyodide = await loadPyodide(); |
|
self.pyodide.globals.set("sendPatch", sendPatch); |
|
console.log("Loaded!"); |
|
await self.pyodide.loadPackage("micropip"); |
|
const env_spec = ['https://cdn.holoviz.org/panel/wheels/bokeh-3.3.2-py3-none-any.whl', 'https://cdn.holoviz.org/panel/1.3.6/dist/wheels/panel-1.3.6-py3-none-any.whl', 'pyodide-http==0.2.1', 'pandas'] |
|
for (const pkg of env_spec) { |
|
let pkg_name; |
|
if (pkg.endsWith('.whl')) { |
|
pkg_name = pkg.split('/').slice(-1)[0].split('-')[0] |
|
} else { |
|
pkg_name = pkg |
|
} |
|
self.postMessage({type: 'status', msg: `Installing ${pkg_name}`}) |
|
try { |
|
await self.pyodide.runPythonAsync(` |
|
import micropip |
|
await micropip.install('${pkg}'); |
|
`); |
|
} catch(e) { |
|
console.log(e) |
|
self.postMessage({ |
|
type: 'status', |
|
msg: `Error while installing ${pkg_name}` |
|
}); |
|
} |
|
} |
|
console.log("Packages loaded!"); |
|
self.postMessage({type: 'status', msg: 'Executing code'}) |
|
const code = ` |
|
|
|
import asyncio |
|
|
|
from panel.io.pyodide import init_doc, write_doc |
|
|
|
init_doc() |
|
|
|
""" |
|
Source: https://awesome-panel.org/resources/table_of_elements_with_wikipedia_row_content/ |
|
""" |
|
|
|
import panel as pn |
|
from bokeh.sampledata.periodic_table import elements |
|
|
|
pn.extension("tabulator") |
|
|
|
@pn.cache |
|
def get_elements(): |
|
return elements[ |
|
["atomic number", "name", "atomic mass", "metal", "year discovered"] |
|
].set_index("atomic number") |
|
|
|
periodic_df = get_elements() |
|
|
|
@pn.cache # Caching is a hack to avoid flickering. It seems like row content is loaded twice otherwise |
|
def content_fn(row): |
|
return pn.pane.HTML( |
|
f'<iframe src="https://en.wikipedia.org/wiki/{row["name"]}" width="100%" height="500px"></iframe>', |
|
sizing_mode="stretch_width" |
|
) |
|
|
|
periodic_table = pn.widgets.Tabulator( |
|
periodic_df, |
|
layout="fit_columns", |
|
sizing_mode="stretch_both", |
|
row_content=content_fn, |
|
embed_content=True, |
|
) |
|
|
|
pn.template.FastListTemplate( |
|
site="Awesome Panel", |
|
site_url="https://awesome-panel.org", |
|
title="Table of Elements with Wikipedia row content", |
|
main=[periodic_table], |
|
accent="#F08080", |
|
main_layout=None, |
|
main_max_width="1024px", |
|
).servable() |
|
|
|
|
|
await write_doc() |
|
` |
|
|
|
try { |
|
const [docs_json, render_items, root_ids] = await self.pyodide.runPythonAsync(code) |
|
self.postMessage({ |
|
type: 'render', |
|
docs_json: docs_json, |
|
render_items: render_items, |
|
root_ids: root_ids |
|
}) |
|
} catch(e) { |
|
const traceback = `${e}` |
|
const tblines = traceback.split('\n') |
|
self.postMessage({ |
|
type: 'status', |
|
msg: tblines[tblines.length-2] |
|
}); |
|
throw e |
|
} |
|
} |
|
|
|
self.onmessage = async (event) => { |
|
const msg = event.data |
|
if (msg.type === 'rendered') { |
|
self.pyodide.runPythonAsync(` |
|
from panel.io.state import state |
|
from panel.io.pyodide import _link_docs_worker |
|
|
|
_link_docs_worker(state.curdoc, sendPatch, setter='js') |
|
`) |
|
} else if (msg.type === 'patch') { |
|
self.pyodide.globals.set('patch', msg.patch) |
|
self.pyodide.runPythonAsync(` |
|
state.curdoc.apply_json_patch(patch.to_py(), setter='js') |
|
`) |
|
self.postMessage({type: 'idle'}) |
|
} else if (msg.type === 'location') { |
|
self.pyodide.globals.set('location', msg.location) |
|
self.pyodide.runPythonAsync(` |
|
import json |
|
from panel.io.state import state |
|
from panel.util import edit_readonly |
|
if state.location: |
|
loc_data = json.loads(location) |
|
with edit_readonly(state.location): |
|
state.location.param.update({ |
|
k: v for k, v in loc_data.items() if k in state.location.param |
|
}) |
|
`) |
|
} |
|
} |
|
|
|
startApplication() |