Is it possible to have a user upload an arbitrary Python script (that uses built-ins only, no external packages) and then execute it using PyScript?
You can use an HTML <input
> element to upload the file, and use await file.txt()
to get the source. Then there are a couple ways to execute the code.
Using Python's exec()
method:
<script defer src="https://pyscript.net/releases/2022.12.1/pyscript.js"></script>
<link rel="stylesheet" href="https://pyscript.net/releases/2022.12.1/pyscript.css">
<input type="file" id="file-upload">
<py-script>
import js
from pyodide.ffi.wrappers import add_event_listener
async def upload_and_run(event):
file_list = event.target.files
first_item = file_list.item(0)
src = await first_item.text()
exec(src)
input_elem = js.document.getElementById("file-upload")
add_event_listener(input_elem, "change", upload_and_run);
</py-script>
Or, if you want the script to behave like a <py-script> tag, with pretty error handling and such, you could add source to a new <py-script> tag:
<script defer src="https://pyscript.net/releases/2022.12.1/pyscript.js"></script>
<link rel="stylesheet" href="https://pyscript.net/releases/2022.12.1/pyscript.css">
<input type="file" id="file-upload">
<py-script>
import js
from pyodide.ffi.wrappers import add_event_listener
async def upload_as_script_tag(event):
file_list = event.target.files
first_item = file_list.item(0)
src = await first_item.text()
newTag = js.document.createElement("py-script")
newTag.innerText = src
js.document.body.appendChild(newTag)
input_elem = js.document.getElementById("file-upload")
add_event_listener(input_elem, "change", upload_as_script_tag);
</py-script>
</body>