mirror of
https://github.com/pyscript/pyscript.git
synced 2022-05-01 19:47:48 +03:00
add array of initializers, to run after the python runtime has loaded
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
import { faPlusCircle } from '@fortawesome/free-solid-svg-icons'
|
import { faPlusCircle } from '@fortawesome/free-solid-svg-icons'
|
||||||
import Tailwind from "./Tailwind.svelte";
|
import Tailwind from "./Tailwind.svelte";
|
||||||
import { loadInterpreter } from './interpreter';
|
import { loadInterpreter } from './interpreter';
|
||||||
import { pyodideLoaded, loadedEnvironments, navBarOpen, componentsNavOpen, mode, scriptsQueue } from './stores';
|
import { pyodideLoaded, loadedEnvironments, navBarOpen, componentsNavOpen, mode, scriptsQueue, initializers } from './stores';
|
||||||
import Main from "./Main.svelte";
|
import Main from "./Main.svelte";
|
||||||
import Header from "./Header.svelte";
|
import Header from "./Header.svelte";
|
||||||
import SideNav from "./SideNav.svelte";
|
import SideNav from "./SideNav.svelte";
|
||||||
@@ -47,6 +47,12 @@
|
|||||||
for (let script of $scriptsQueue) {
|
for (let script of $scriptsQueue) {
|
||||||
script.evaluate();
|
script.evaluate();
|
||||||
}
|
}
|
||||||
|
scriptsQueue.set([])
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we call all initializers AFTER we actually executed all page scripts
|
||||||
|
for (let initializer of $initializers){
|
||||||
|
initializer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { keymap, ViewUpdate } from "@codemirror/view";
|
|||||||
import { defaultKeymap } from "@codemirror/commands";
|
import { defaultKeymap } from "@codemirror/commands";
|
||||||
import { oneDarkTheme } from "@codemirror/theme-one-dark";
|
import { oneDarkTheme } from "@codemirror/theme-one-dark";
|
||||||
|
|
||||||
import { pyodideLoaded, loadedEnvironments, componentDetailsNavOpen, currentComponentDetails, mode, addToScriptsQueue } from '../stores';
|
import { pyodideLoaded, loadedEnvironments, componentDetailsNavOpen, currentComponentDetails, mode } from '../stores';
|
||||||
import { addClasses } from '../utils';
|
import { addClasses } from '../utils';
|
||||||
|
|
||||||
// Premise used to connect to the first available pyodide interpreter
|
// Premise used to connect to the first available pyodide interpreter
|
||||||
@@ -208,7 +208,7 @@ export class PyRepl extends HTMLElement {
|
|||||||
let source = this.editor.state.doc.toString();
|
let source = this.editor.state.doc.toString();
|
||||||
let output;
|
let output;
|
||||||
if (source.includes("asyncio")){
|
if (source.includes("asyncio")){
|
||||||
output = pyodide.runPythonAsync(source);
|
output = await pyodide.runPythonAsync(source);
|
||||||
}else{
|
}else{
|
||||||
output = pyodide.runPython(source);
|
output = pyodide.runPython(source);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,14 @@ import { keymap, ViewUpdate } from "@codemirror/view";
|
|||||||
import { defaultKeymap } from "@codemirror/commands";
|
import { defaultKeymap } from "@codemirror/commands";
|
||||||
import { oneDarkTheme } from "@codemirror/theme-one-dark";
|
import { oneDarkTheme } from "@codemirror/theme-one-dark";
|
||||||
|
|
||||||
import { pyodideLoaded, loadedEnvironments, componentDetailsNavOpen, currentComponentDetails, mode, addToScriptsQueue } from '../stores';
|
import { pyodideLoaded, loadedEnvironments, componentDetailsNavOpen, currentComponentDetails, mode, addToScriptsQueue, addInitializer } from '../stores';
|
||||||
import { addClasses } from '../utils';
|
import { addClasses } from '../utils';
|
||||||
|
|
||||||
// Premise used to connect to the first available pyodide interpreter
|
// Premise used to connect to the first available pyodide interpreter
|
||||||
let pyodideReadyPromise;
|
let pyodideReadyPromise;
|
||||||
let environments;
|
let environments;
|
||||||
let currentMode;
|
let currentMode;
|
||||||
|
let handlersCollected = false;
|
||||||
|
|
||||||
pyodideLoaded.subscribe(value => {
|
pyodideLoaded.subscribe(value => {
|
||||||
pyodideReadyPromise = value;
|
pyodideReadyPromise = value;
|
||||||
@@ -40,6 +41,46 @@ function createCmdHandler(el){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Script {
|
||||||
|
source: string;
|
||||||
|
state: string;
|
||||||
|
target: string;
|
||||||
|
|
||||||
|
constructor(source: string, target: string) {
|
||||||
|
this.target = target;
|
||||||
|
this.source = source;
|
||||||
|
this.state = 'waiting';
|
||||||
|
}
|
||||||
|
|
||||||
|
async evaluate() {
|
||||||
|
console.log('evaluate');
|
||||||
|
let pyodide = await pyodideReadyPromise;
|
||||||
|
// debugger
|
||||||
|
try {
|
||||||
|
// @ts-ignore
|
||||||
|
// let source = this.editor.state.doc.toString();
|
||||||
|
let output;
|
||||||
|
if (this.source.includes("asyncio")){
|
||||||
|
output = await pyodide.runPythonAsync(this.source);
|
||||||
|
}else{
|
||||||
|
output = pyodide.runPython(this.source);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.target){
|
||||||
|
// this.editorOut.innerHTML = s;
|
||||||
|
}
|
||||||
|
// if (output !== undefined){
|
||||||
|
// this.addToOutput(output);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.log("OOOPS, this happened: " + err);
|
||||||
|
// this.addToOutput(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class PyScript extends HTMLElement {
|
export class PyScript extends HTMLElement {
|
||||||
shadow: ShadowRoot;
|
shadow: ShadowRoot;
|
||||||
wrapper: HTMLElement;
|
wrapper: HTMLElement;
|
||||||
@@ -176,11 +217,10 @@ export class PyScript extends HTMLElement {
|
|||||||
let source = this.editor.state.doc.toString();
|
let source = this.editor.state.doc.toString();
|
||||||
let output;
|
let output;
|
||||||
if (source.includes("asyncio")){
|
if (source.includes("asyncio")){
|
||||||
output = pyodide.runPythonAsync(source);
|
output = await pyodide.runPythonAsync(source);
|
||||||
}else{
|
}else{
|
||||||
output = pyodide.runPython(source);
|
output = pyodide.runPython(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output !== undefined){
|
if (output !== undefined){
|
||||||
this.addToOutput(output);
|
this.addToOutput(output);
|
||||||
}
|
}
|
||||||
@@ -200,3 +240,47 @@ export class PyScript extends HTMLElement {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function initHandlers() {
|
||||||
|
if( handlersCollected == true ) return;
|
||||||
|
|
||||||
|
console.log('Collecting nodes...');
|
||||||
|
let pyodide = await pyodideReadyPromise;
|
||||||
|
let matches : NodeListOf<HTMLElement> = document.querySelectorAll('[pys-onClick]');
|
||||||
|
let output;
|
||||||
|
let source;
|
||||||
|
for (var el of matches) {
|
||||||
|
let handlerCode = el.getAttribute('pys-onClick');
|
||||||
|
source = `Element("${ el.id }").element.onclick = ${ handlerCode }`;
|
||||||
|
output = await pyodide.runPythonAsync(source);
|
||||||
|
|
||||||
|
// el.onclick = (evt: any) => {
|
||||||
|
// console.log("click");
|
||||||
|
// new Promise((resolve, reject) => {
|
||||||
|
// setTimeout(() => {
|
||||||
|
// console.log('Inside')
|
||||||
|
// }, 300);
|
||||||
|
// }).then(() => {
|
||||||
|
// console.log("resolved")
|
||||||
|
// });
|
||||||
|
// // let handlerCode = el.getAttribute('pys-onClick');
|
||||||
|
// // pyodide.runPython(handlerCode);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
handlersCollected = true;
|
||||||
|
|
||||||
|
matches = document.querySelectorAll('[pys-onKeyDown]');
|
||||||
|
for (var el of matches) {
|
||||||
|
let handlerCode = el.getAttribute('pys-onKeyDown');
|
||||||
|
source = `Element("${ el.id }").element.addEventListener("keydown", ${ handlerCode })`;
|
||||||
|
output = await pyodide.runPythonAsync(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addInitializer(initHandlers)
|
||||||
|
|
||||||
|
// if( document.readyState === 'loading' ) {
|
||||||
|
// document.addEventListener( 'DOMContentLoaded', initHandlers );
|
||||||
|
// }
|
||||||
|
// else if( document.readyState === 'interactive' || document.readyState === 'complete' ) {
|
||||||
|
// initHandlers();
|
||||||
|
// }
|
||||||
|
|||||||
@@ -47,30 +47,54 @@ pyscript = PyScript()
|
|||||||
|
|
||||||
|
|
||||||
class Element:
|
class Element:
|
||||||
def __init__(self, element_id):
|
def __init__(self, element_id, element=None):
|
||||||
self._id = element_id
|
self._id = element_id
|
||||||
|
self._element = element
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def element(self):
|
def element(self):
|
||||||
"""Return the dom element"""
|
"""Return the dom element"""
|
||||||
return document.querySelector(f'#{self._id}');
|
if not self._element:
|
||||||
|
self._element = document.querySelector(f'#{self._id}');
|
||||||
|
return self._element
|
||||||
|
|
||||||
def write(self, value, append=False):
|
def write(self, value, append=False):
|
||||||
console.log(f"Element.write: {value} --> {append}")
|
console.log(f"Element.write: {value} --> {append}")
|
||||||
|
# TODO: it should be the opposite... pyscript.write should use the Element.write
|
||||||
|
# so we can consolidate on how we write depending on the element type
|
||||||
pyscript.write(self._id, value, append=append)
|
pyscript.write(self._id, value, append=append)
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
self.write("", append=False)
|
if hasattr(self.element, 'value'):
|
||||||
|
self.element.value = ''
|
||||||
|
else:
|
||||||
|
self.write("", append=False)
|
||||||
|
|
||||||
def clone(self, new_id=None):
|
def select(self, query, from_content=False):
|
||||||
|
el = self.element
|
||||||
|
if from_content:
|
||||||
|
el = el.content
|
||||||
|
|
||||||
|
_el = el.querySelector(query)
|
||||||
|
if _el:
|
||||||
|
return Element(_el.id, _el)
|
||||||
|
else:
|
||||||
|
console.log(f"WARNING: can't find element matching query {query}")
|
||||||
|
|
||||||
|
def clone(self, new_id=None, to=None):
|
||||||
if new_id is None:
|
if new_id is None:
|
||||||
new_id = self.element.id
|
new_id = self.element.id
|
||||||
|
|
||||||
clone = self.element.cloneNode(true);
|
clone = self.element.cloneNode(True);
|
||||||
clone.id = new_id;
|
clone.id = new_id;
|
||||||
|
|
||||||
|
if to:
|
||||||
|
to.element.appendChild(clone)
|
||||||
|
|
||||||
# Inject it into the DOM
|
# Inject it into the DOM
|
||||||
self.element.after(clone);
|
self.element.after(clone);
|
||||||
|
|
||||||
|
return Element(clone.id, clone)
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
||||||
@@ -81,13 +105,13 @@ let loadInterpreter = async function(): any {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// now that we loaded, add additional convenience fuctions
|
// now that we loaded, add additional convenience fuctions
|
||||||
pyodide.loadPackage(['matplotlib', 'numpy'])
|
// pyodide.loadPackage(['matplotlib', 'numpy'])
|
||||||
|
|
||||||
await pyodide.loadPackage("micropip");
|
await pyodide.loadPackage("micropip");
|
||||||
await pyodide.runPythonAsync(`
|
// await pyodide.runPythonAsync(`
|
||||||
import micropip
|
// import micropip
|
||||||
await micropip.install("ipython")
|
// await micropip.install("ipython")
|
||||||
`);
|
// `);
|
||||||
|
|
||||||
let output = pyodide.runPython(additional_definitions);
|
let output = pyodide.runPython(additional_definitions);
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,10 @@ export const mainDiv = writable(null);
|
|||||||
export const currentComponentDetails = writable([]);
|
export const currentComponentDetails = writable([]);
|
||||||
export const mode = writable(DEFAULT_MODE)
|
export const mode = writable(DEFAULT_MODE)
|
||||||
export const scriptsQueue = writable([])
|
export const scriptsQueue = writable([])
|
||||||
|
export const initializers = writable([])
|
||||||
|
|
||||||
let scriptsQueue_ = []
|
let scriptsQueue_ = [];
|
||||||
|
let initializers_ = [];
|
||||||
|
|
||||||
scriptsQueue.subscribe(value => {
|
scriptsQueue.subscribe(value => {
|
||||||
scriptsQueue_ = value;
|
scriptsQueue_ = value;
|
||||||
@@ -33,3 +35,11 @@ scriptsQueue.subscribe(value => {
|
|||||||
export const addToScriptsQueue = (script) => {
|
export const addToScriptsQueue = (script) => {
|
||||||
scriptsQueue.set([...scriptsQueue_, script]);
|
scriptsQueue.set([...scriptsQueue_, script]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
scriptsQueue.subscribe(value => {
|
||||||
|
scriptsQueue_ = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
export const addInitializer = (initializer) => {
|
||||||
|
initializers.set([...initializers_, initializer]);
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user