PyTerminal: use Pyodide instead of Python (#1833)

This commit is contained in:
Andrea Giammarchi
2023-11-03 17:59:11 +01:00
committed by GitHub
parent aef028be6e
commit 3e2a67d434
3 changed files with 26 additions and 13 deletions

View File

@@ -81,26 +81,23 @@ const pyTerminal = async () => {
const workerReady = ({ interpreter }, { sync }) => {
sync.pyterminal_drop_hooks();
const decoder = new TextDecoder();
let data = "";
const generic = {
isatty: true,
write(buffer) {
sync.pyterminal_write(decoder.decode(buffer));
data = decoder.decode(buffer);
sync.pyterminal_write(data);
return buffer.length;
},
};
interpreter.setStdout(generic);
interpreter.setStderr(generic);
interpreter.setStdin({
isatty: true,
stdin: () => sync.pyterminal_read(data),
});
};
// run in python code able to replace builtins.input
// using the xworker.sync non blocking prompt
const codeBefore = `
import builtins
from pyscript import sync as _sync
builtins.input = lambda prompt: _sync.pyterminal_read(prompt)
`;
// at the end of the code, make the terminal interactive
const codeAfter = `
import code as _code
@@ -121,7 +118,6 @@ const pyTerminal = async () => {
// allow a worker to drop main thread hooks ASAP
xworker.sync.pyterminal_drop_hooks = () => {
hooks.worker.onReady.delete(workerReady);
hooks.worker.codeBeforeRun.delete(codeBefore);
hooks.worker.codeAfterRun.delete(codeAfter);
};
});
@@ -129,7 +125,6 @@ const pyTerminal = async () => {
// setup remote thread JS/Python code for whenever the
// worker is ready to become a terminal
hooks.worker.onReady.add(workerReady);
hooks.worker.codeBeforeRun.add(codeBefore);
hooks.worker.codeAfterRun.add(codeAfter);
} else {
// in the main case, just bootstrap XTerm without

View File

@@ -13,7 +13,7 @@
def greetings(event):
print('hello world')
</script>
<py-script terminal>
<py-script worker terminal>
import sys
from pyscript import display
display("Hello", "PyScript Next - PyTerminal", append=False)

View File

@@ -40,6 +40,24 @@ class TestPyTerminal(PyScriptTest):
self.page.keyboard.press("Enter")
self.page.get_by_text("the answer is 42").wait_for()
@only_worker
def test_py_terminal_os_write(self):
"""
An `os.write("text")` should land in the terminal
"""
self.pyscript_run(
"""
<script type="py" terminal>
import os
os.write(1, str.encode("hello\\n"))
os.write(2, str.encode("world\\n"))
</script>
""",
wait_for_pyscript=False,
)
self.page.get_by_text("hello\n").wait_for()
self.page.get_by_text("world\n").wait_for()
def test_py_terminal(self):
"""
1. <py-terminal> should redirect stdout and stderr to the DOM