Skip to content

Commit 2ed691b

Browse files
committed
0 parents  commit 2ed691b

File tree

276 files changed

+67028
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

276 files changed

+67028
-0
lines changed

.buildinfo

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Sphinx build info version 1
2+
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
3+
config: 5f57cc29c17d37268a2dcbb08c348645
4+
tags: 645f666f9bcd5a90fca523b33c5a78b7

.nojekyll

Whitespace-only changes.

PyodideServiceWorker.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
const appName = 'Lumen'
2+
const appCacheName = 'Lumen-0.7.0a1';
3+
4+
const preCacheFiles = [];
5+
6+
const cachePatterns = ['https://cdn.holoviz.org/panel/1.5.0-a.3/dist/', 'https://cdn.bokeh.org/bokeh/', 'https://cdn.jsdelivr.net/pyodide/', 'https://files.pythonhosted.org/packages/', 'https://pypi.org/pypi/'];
7+
8+
self.addEventListener('install', (e) => {
9+
console.log('[Service Worker] Install');
10+
self.skipWaiting();
11+
e.waitUntil((async () => {
12+
const cacheNames = await caches.keys();
13+
for (const cacheName of cacheNames) {
14+
if (cacheName.startsWith(appName) && cacheName !== appCacheName) {
15+
console.log(`[Service Worker] Delete old cache ${cacheName}`);
16+
caches.delete(cacheName);
17+
}
18+
}
19+
const cache = await caches.open(appCacheName);
20+
if (preCacheFiles.length) {
21+
console.log('[Service Worker] Precaching ');
22+
}
23+
preCacheFiles.forEach(async (cacheFile) => {
24+
const request = new Request(cacheFile);
25+
const response = await fetch(request);
26+
if (response.ok || response.type == 'opaque') {
27+
cache.put(request, response);
28+
}
29+
})
30+
})());
31+
});
32+
33+
self.addEventListener('activate', (event) => {
34+
console.log('[Service Worker] Activating');
35+
return self.clients.claim();
36+
});
37+
38+
self.addEventListener('fetch', (e) => {
39+
if (e.request.method !== 'GET') {
40+
return
41+
}
42+
e.respondWith((async () => {
43+
const cache = await caches.open(appCacheName);
44+
let response = await cache.match(e.request);
45+
console.log(`[Service Worker] Fetching resource: ${e.request.url}`);
46+
if (response) {
47+
return response;
48+
}
49+
response = await fetch(e.request);
50+
if (!response.ok && !(response.type == 'opaque')) {
51+
throw Error(`[Service Worker] Fetching resource ${e.request.url} failed with response: ${response.status}`);
52+
}
53+
console.log(`[Service Worker] Caching new resource: ${e.request.url}`);
54+
cache.put(e.request, response.clone());
55+
return response;
56+
})());
57+
});

_images/1.png

119 KB

_images/2.png

121 KB

_images/3.png

117 KB

_images/bikes.png

439 KB

_images/branch_yaml_00_firstTable.png

280 KB
357 KB

_images/build_app_00.png

57.9 KB

_images/build_app_01.png

209 KB

_images/build_app_02.png

111 KB

_images/build_app_03.png

118 KB

_images/build_app_04.png

128 KB

_images/build_app_05.png

199 KB

_images/build_app_06.png

205 KB

_images/build_app_07.png

223 KB

_images/builder_dashboard.png

54.6 KB

_images/cli_bad.png

49.7 KB

_images/cli_good.png

48.9 KB

_images/config_editor.png

25.7 KB

_images/dashboard_gallery.png

71.7 KB

_images/earthquakes.png

401 KB

_images/launcher.png

38.1 KB

_images/layout_example.png

96.6 KB

_images/local_components_app.png

354 KB

_images/lumen_dashboard.png

850 KB

_images/nyc_taxi.png

574 KB

_images/penguins.png

120 KB

_images/pipeline_diagram.png

158 KB

_images/precip.png

238 KB

_images/seattle.png

232 KB

_images/shell.png

48.9 KB

_images/source_editor.png

103 KB

_images/source_example.png

95.2 KB

_images/source_variable.png

30.8 KB

_images/variable_all.png

65.8 KB

_images/variable_editor.png

59.6 KB

_images/variable_selected.png

80.2 KB

_images/view_editor.png

44.1 KB

_images/view_example.png

102 KB

_images/windturbines.png

430 KB

_images/yaml_launcher.png

96.6 KB

_sphinx_design_static/design-tabs.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// @ts-check
2+
3+
// Extra JS capability for selected tabs to be synced
4+
// The selection is stored in local storage so that it persists across page loads.
5+
6+
/**
7+
* @type {Record<string, HTMLElement[]>}
8+
*/
9+
let sd_id_to_elements = {};
10+
const storageKeyPrefix = "sphinx-design-tab-id-";
11+
12+
/**
13+
* Create a key for a tab element.
14+
* @param {HTMLElement} el - The tab element.
15+
* @returns {[string, string, string] | null} - The key.
16+
*
17+
*/
18+
function create_key(el) {
19+
let syncId = el.getAttribute("data-sync-id");
20+
let syncGroup = el.getAttribute("data-sync-group");
21+
if (!syncId || !syncGroup) return null;
22+
return [syncGroup, syncId, syncGroup + "--" + syncId];
23+
}
24+
25+
/**
26+
* Initialize the tab selection.
27+
*
28+
*/
29+
function ready() {
30+
// Find all tabs with sync data
31+
32+
/** @type {string[]} */
33+
let groups = [];
34+
35+
document.querySelectorAll(".sd-tab-label").forEach((label) => {
36+
if (label instanceof HTMLElement) {
37+
let data = create_key(label);
38+
if (data) {
39+
let [group, id, key] = data;
40+
41+
// add click event listener
42+
// @ts-ignore
43+
label.onclick = onSDLabelClick;
44+
45+
// store map of key to elements
46+
if (!sd_id_to_elements[key]) {
47+
sd_id_to_elements[key] = [];
48+
}
49+
sd_id_to_elements[key].push(label);
50+
51+
if (groups.indexOf(group) === -1) {
52+
groups.push(group);
53+
// Check if a specific tab has been selected via URL parameter
54+
const tabParam = new URLSearchParams(window.location.search).get(
55+
group
56+
);
57+
if (tabParam) {
58+
console.log(
59+
"sphinx-design: Selecting tab id for group '" +
60+
group +
61+
"' from URL parameter: " +
62+
tabParam
63+
);
64+
window.sessionStorage.setItem(storageKeyPrefix + group, tabParam);
65+
}
66+
}
67+
68+
// Check is a specific tab has been selected previously
69+
let previousId = window.sessionStorage.getItem(
70+
storageKeyPrefix + group
71+
);
72+
if (previousId === id) {
73+
// console.log(
74+
// "sphinx-design: Selecting tab from session storage: " + id
75+
// );
76+
// @ts-ignore
77+
label.previousElementSibling.checked = true;
78+
}
79+
}
80+
}
81+
});
82+
}
83+
84+
/**
85+
* Activate other tabs with the same sync id.
86+
*
87+
* @this {HTMLElement} - The element that was clicked.
88+
*/
89+
function onSDLabelClick() {
90+
let data = create_key(this);
91+
if (!data) return;
92+
let [group, id, key] = data;
93+
for (const label of sd_id_to_elements[key]) {
94+
if (label === this) continue;
95+
// @ts-ignore
96+
label.previousElementSibling.checked = true;
97+
}
98+
window.sessionStorage.setItem(storageKeyPrefix + group, id);
99+
}
100+
101+
document.addEventListener("DOMContentLoaded", ready, false);

_sphinx_design_static/sphinx-design.min.css

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

_static/PyodideWebWorker.js

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
importScripts("https://cdn.jsdelivr.net/pyodide/v0.25.0/full/pyodide.js");
2+
3+
const QUEUE = [];
4+
5+
const REQUIRES = {}
6+
7+
function sendPatch(patch, buffers, cell_id) {
8+
self.postMessage({
9+
type: 'patch',
10+
patch: patch,
11+
buffers: buffers,
12+
id: cell_id
13+
})
14+
}
15+
16+
function sendStdout(cell_id, stdout) {
17+
self.postMessage({
18+
type: 'stdout',
19+
content: stdout,
20+
id: cell_id
21+
})
22+
}
23+
function sendStderr(cell_id, stderr) {
24+
self.postMessage({
25+
type: 'stderr',
26+
content: stderr,
27+
id: cell_id
28+
})
29+
}
30+
31+
async function loadApplication(cell_id, path) {
32+
console.log("Loading pyodide!");
33+
self.pyodide = await loadPyodide();
34+
self.pyodide.globals.set("sendPatch", sendPatch);
35+
self.pyodide.globals.set("sendStdout", sendStdout);
36+
self.pyodide.globals.set("sendStderr", sendStderr);
37+
console.log("Loaded!");
38+
await self.pyodide.loadPackage("micropip");
39+
const packages = ['https://cdn.holoviz.org/panel/1.5.0-a.3/dist/wheels/bokeh-3.4.2-py3-none-any.whl', 'https://cdn.holoviz.org/panel/1.5.0-a.3/dist/wheels/panel-1.5.0a3-py3-none-any.whl', 'lumen==0.7.0a1', 'requests', 'pandas', 'pyodide-http', 'holoviews>=1.15.1'];
40+
if (path != null) {
41+
for (const key of Object.keys(REQUIRES)) {
42+
if (path.replace('.html', '').endsWith(key.replace('.md', ''))) {
43+
for (const req of REQUIRES[key]) {
44+
packages.push(req)
45+
}
46+
}
47+
}
48+
}
49+
50+
await self.pyodide.runPythonAsync("")
51+
self.pyodide.runPython("import micropip")
52+
for (const pkg of packages) {
53+
self.postMessage({
54+
type: 'loading',
55+
msg: `Loading ${pkg}`,
56+
id: cell_id
57+
});
58+
await self.pyodide.runPythonAsync(`
59+
await micropip.install('${pkg}', keep_going=True);
60+
`);
61+
}
62+
console.log("Packages loaded!");
63+
}
64+
65+
const autodetect_deps_code = `
66+
import json
67+
try:
68+
from panel.io.mime_render import find_requirements
69+
except Exception:
70+
from panel.io.mime_render import find_imports as find_requirements
71+
json.dumps(find_requirements(msg.to_py()['code']))`
72+
73+
const exec_code = `
74+
from functools import partial
75+
from panel.io.pyodide import pyrender
76+
from js import console
77+
78+
msg = msg.to_py()
79+
code = msg['code']
80+
stdout_cb = partial(sendStdout, msg['id'])
81+
stderr_cb = partial(sendStderr, msg['id'])
82+
target = f"output-{msg['id']}"
83+
pyrender(code, stdout_cb, stderr_cb, target)`
84+
85+
const onload_code = `
86+
msg = msg.to_py()
87+
if msg['mime'] == 'application/bokeh':
88+
from panel.io.pyodide import _link_docs_worker
89+
from panel.io.state import state
90+
doc = state.cache[f"output-{msg['id']}"]
91+
_link_docs_worker(doc, sendPatch, msg['id'], 'js')`
92+
93+
const patch_code = `
94+
from panel import state
95+
96+
try:
97+
from pane.io.pyodide import _convert_json_patch
98+
patch = _convert_json_patch(msg.patch)
99+
except:
100+
patch = msg.patch.to_py()
101+
doc = state.cache[f"output-{msg.id}"]
102+
doc.apply_json_patch(patch, setter='js')`
103+
104+
const MESSAGES = {
105+
patch: patch_code,
106+
execute: exec_code,
107+
rendered: onload_code
108+
}
109+
110+
self.onmessage = async (event) => {
111+
let resolveExecution, rejectExecution;
112+
const executing = new Promise(function(resolve, reject){
113+
resolveExecution = resolve;
114+
rejectExecution = reject;
115+
});
116+
117+
const prev_msg = QUEUE[0]
118+
const msg = {...event.data, executing}
119+
QUEUE.unshift(msg)
120+
121+
if (prev_msg) {
122+
self.postMessage({
123+
type: 'loading',
124+
msg: 'Awaiting previous cells',
125+
id: msg.id
126+
});
127+
await prev_msg.executing
128+
}
129+
130+
// Init pyodide
131+
if (self.pyodide == null) {
132+
self.postMessage({
133+
type: 'loading',
134+
msg: 'Loading pyodide',
135+
id: msg.id
136+
});
137+
await loadApplication(msg.id, msg.path)
138+
self.postMessage({
139+
type: 'loaded',
140+
id: msg.id
141+
});
142+
}
143+
144+
// Handle message
145+
if (!MESSAGES.hasOwnProperty(msg.type)) {
146+
console.warn(`Service worker received unknown message type '${msg.type}'.`)
147+
resolveExecution()
148+
self.postMessage({
149+
type: 'idle',
150+
id: msg.id
151+
});
152+
return
153+
}
154+
155+
if (msg.type === 'execute') {
156+
let deps
157+
try {
158+
self.pyodide.globals.set('msg', msg)
159+
deps = self.pyodide.runPython(autodetect_deps_code)
160+
} catch(e) {
161+
deps = '[]'
162+
console.warn(`Auto-detection of dependencies failed with error: ${e}`)
163+
}
164+
for (const pkg of JSON.parse(deps)) {
165+
self.postMessage({
166+
type: 'loading',
167+
msg: `Loading ${pkg}`,
168+
id: msg.id
169+
});
170+
try {
171+
await self.pyodide.runPythonAsync(`await micropip.install('${pkg}', keep_going=True)`)
172+
} catch(e) {
173+
console.log(`Auto-detected dependency ${pkg} could not be installed.`)
174+
}
175+
}
176+
}
177+
178+
try {
179+
self.pyodide.globals.set('msg', msg)
180+
let out = await self.pyodide.runPythonAsync(MESSAGES[msg.type])
181+
resolveExecution()
182+
if (out == null) {
183+
out = new Map()
184+
}
185+
if (out.has('content')) {
186+
self.postMessage({
187+
type: 'render',
188+
id: msg.id,
189+
content: out.get('content'),
190+
mime: out.get('mime_type')
191+
});
192+
}
193+
if (out.has('stdout') && out.get('stdout').length) {
194+
self.postMessage({
195+
type: 'stdout',
196+
content: out.get('stdout'),
197+
id: msg.id
198+
});
199+
}
200+
if (out.has('stderr') && out.get('stderr').length) {
201+
self.postMessage({
202+
type: 'stderr',
203+
content: out.get('stderr'),
204+
id: msg.id
205+
});
206+
}
207+
self.postMessage({
208+
type: 'idle',
209+
id: msg.id,
210+
uuid: msg.uuid
211+
});
212+
} catch (e) {
213+
const traceback = `${e}`
214+
const tblines = traceback.split('\n')
215+
self.postMessage({
216+
type: 'error',
217+
traceback: traceback,
218+
msg: tblines[tblines.length-2],
219+
id: msg.id
220+
});
221+
resolveExecution()
222+
throw(e)
223+
}
224+
}

0 commit comments

Comments
 (0)