I am trying to use the Python turtle module with pyodide. This isn't officially supported but I found another StackOverflow answer that suggested using a modified version from Basthon. I therefore copied the files from Basthon into a new directory structure:
pyodide/
turtle/
src/
turtle/
__init__.py
svg.py
pyproject.toml
My pyproject.toml file contains the following:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "turtle"
version = "0.0.1"
And I am successfully building a wheel with the following script:
#!/bin/bash
pushd pyodide/turtle
python3 -m pip install --upgrade build
python3 -m build
popd
I am then succesfully loading pyodide with the turtle wheel using the folowing HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Pyodide</title>
<script src="https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide.js"></script>
</head>
<body>
<textarea id="input" cols="80" rows="15">
import turtle
t = turtle.Turtle()
t.forward(100)
</textarea>
<br/>
<button id="run" onclick="run()" disabled>Run</button>
<pre id="output">Loading pyodide...</pre>
<div id="visual"></div>
<script type="text/javascript">
const runButton = document.getElementById("run");
const input = document.getElementById("input");
const output = document.getElementById("output");
let pyodide;
const main = async () => {
pyodide = await loadPyodide({
stdout: (text) => output.innerHTML += text + "\n",
});
runButton.disabled = false;
output.innerHTML = "";
};
main();
const run = async () => {
output.innerHTML = "";
try {
await pyodide.loadPackage("./turtle/dist/turtle-0.0.1-py2.py3-none-any.whl");
await pyodide.loadPackagesFromImports(input.value);
await pyodide.runPython(input.value);
} catch (error) {
console.log(error);
}
};
</script>
</body>
</html>
I ran the above HTML from a web server by running python -m http.server. This allows it to read the .whl file, due to CORS browser restrictions.
However, I am not sure how to actually output the SVG on the web page. I looked through the Basthon source code but couldn't see a method to do this. The closest I could find was turtle.svg() but when I called this from python, I received the following error in the JavaScript console:
TypeError: 'pyodide.ffi.JsProxy' object is not callable
I tried to read about pyodide Type Conversions but didn't understand what I need to do.
Is it possible to bind the drawing context to an SVG on the page so that the turtle will animate in real time? Or is it only possible to render a finished SVG using the Basthon turtle package? Is there an easier way to get pyodide and turtle working with realtime graphics in a browser window?
I figured it out based on this web worker example I found that used the same Basthon turtle package. These were the additional lines I needed in my python: