Skip to content

Commit 7a1c0a3

Browse files
committed
Change Pyodide to Skulpt to run Python client-side
1 parent e25aa6d commit 7a1c0a3

File tree

3 files changed

+102
-44
lines changed

3 files changed

+102
-44
lines changed

_layouts/bootstrap.html

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@
77
<link rel="icon" href="/assets/img/logo.png" type="image/x-icon">
88
<!-- Bootstrap CSS -->
99
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" integrity="sha384-DyZ88mC6Up2uqS4h/KRgHuoeGwBcD4Ng9SiP4dIRy0EXTlnuz47vAwmeGwVChigm" crossorigin="anonymous">
10-
<!-- <script type="text/javascript">
11-
// set the pyodide files URL (packages.json, pyodide.asm.data etc)
12-
window.languagePluginUrl = 'https://cdn.jsdelivr.net/pyodide/v0.18.1/full/';
13-
</script> -->
14-
<script src="https://cdn.jsdelivr.net/pyodide/v0.18.1/full/pyodide.js"></script>
10+
<!-- <script src="https://cdn.jsdelivr.net/pyodide/v0.18.1/full/pyodide.js"></script> -->
11+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js" type="text/javascript"></script>
12+
<script src="https://skulpt.org/js/skulpt.min.js" type="text/javascript"></script>
13+
<script src="https://skulpt.org/js/skulpt-stdlib.js" type="text/javascript"></script>
1514
<link rel="stylesheet" href="/assets/css/main.css">
1615
<link rel="stylesheet" href="/assets/css/code-editor.css">
1716
{% if page.sass_needed %}

_posts/2021-10-14-lesson-1.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ An if is a conditional.
2424
A for loop is a loop.
2525

2626
<div class="editor-container p-3 pt-0">
27-
<button onclick="runPython()" class="btn btn-primary my-3">Run</button>
27+
<button onclick="runit()" class="btn btn-primary my-3">Run</button>
2828
<div id="editor"></div>
2929
<div class="mt-3 input-output-container">
3030
<div data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-original-title="Input" class="d-block position-relative input-container">

assets/js/code-editor.js

Lines changed: 97 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,48 +3,107 @@ editor.setTheme("ace/theme/monokai");
33
editor.session.setMode("ace/mode/python");
44

55

6-
async function setup_pyodide() {
7-
// setup pyodide environment to run code blocks as needed
8-
let pyodide = await pyodideReadyPromise;
9-
var setup_code = `
10-
import sys, io, traceback
11-
from js import document, console
12-
namespace = {} # use separate namespace to hide run_code, modules, etc.
13-
def run_code(code):
14-
"""run specified code and return stdout and stderr"""
15-
out = io.StringIO()
16-
sys.stdin = io.StringIO(document.getElementById('input-tmp').value)
17-
oldout = sys.stdout
18-
olderr = sys.stderr
19-
sys.stdout = sys.stderr = out
20-
try:
21-
# change next line to exec(code, {}) if you want to clear vars each time
22-
exec(code, namespace)
23-
except:
24-
traceback.print_exc()
25-
26-
sys.stdout = oldout
27-
sys.stderr = olderr
28-
return out.getvalue()
29-
`
30-
pyodide.runPython(setup_code)
6+
7+
function outf(text) {
8+
const output_element = document.getElementById("output");
9+
output_element.innerText = output_element.innerText + text;
3110
}
3211

33-
async function runPython() {
34-
// run code currently stored in editor
35-
let pyodide = await pyodideReadyPromise;
36-
pyodide.globals.code_to_run = editor.getValue()
37-
document.getElementById("output").innerText = pyodide.runPython('run_code(code_to_run)')
12+
13+
var current_inp = 0;
14+
15+
function get_input(prompt) {
16+
return new Promise((resolve, reject) => {
17+
let input = document.getElementById('input-tmp').value.split(/\r?\n/);
18+
if (current_inp >= input.length) {
19+
throw "Place your input(s) in the \"input\" box!";
20+
}
21+
resolve(input[current_inp]);
22+
current_inp++;
23+
})
3824
}
3925

40-
async function get_pyodide() {
41-
let pyodide = await loadPyodide({
42-
indexURL: "https://cdn.jsdelivr.net/pyodide/v0.18.1/full/",
43-
});
44-
return pyodide;
45-
26+
function runit() {
27+
var prog = editor.getValue();
28+
current_inp = 0;
29+
var output_element = document.getElementById("output");
30+
output_element.innerText = '';
31+
Sk.pre = "output";
32+
Sk.configure({ output: outf, inputfun: get_input, inputfunTakesPrompt: true });
33+
var myPromise = Sk.misceval.asyncToPromise(function () {
34+
return Sk.importMainWithBody("<stdin>", false, prog, true);
35+
});
36+
myPromise.then(function (mod) {
37+
38+
},
39+
function (err) {
40+
output_element.innerText = err.toString();
41+
});
4642
}
4743

48-
let pyodideReadyPromise = get_pyodide();
4944

50-
pyodideReadyPromise.then(setup_pyodide)
45+
// Uncomment below lines to use Pyodide instead of Skulpt!
46+
47+
// async function setup_pyodide() {
48+
// // setup pyodide environment to run code blocks as needed
49+
// let pyodide = await pyodideReadyPromise;
50+
// var setup_code = `
51+
// import sys, io, traceback
52+
// import signal
53+
54+
55+
56+
// from js import document, console
57+
// namespace = {} # use separate namespace to hide run_code, modules, etc.
58+
// def run_code(code):
59+
// """run specified code and return stdout and stderr"""
60+
// out = io.StringIO()
61+
// sys.stdin = io.StringIO(document.getElementById('input-tmp').value)
62+
// oldout = sys.stdout
63+
// olderr = sys.stderr
64+
// sys.stdout = sys.stderr = out
65+
// try:
66+
// # change next line to exec(code, {}) if you want to clear vars each time
67+
68+
// class Timeout(Exception):
69+
// pass
70+
71+
// def handler(sig, frame):
72+
// raise Timeout
73+
74+
// signal.signal(signal.SIGALRM, handler) # register interest in SIGALRM events
75+
76+
// signal.alarm(2) # timeout in 2 seconds
77+
// try:
78+
// exec(code, {})
79+
// except Timeout:
80+
// print('Your code took too much time to run!')
81+
82+
// except:
83+
// traceback.print_exc()
84+
85+
// sys.stdout = oldout
86+
// sys.stderr = olderr
87+
// return out.getvalue()
88+
// `
89+
// pyodide.runPython(setup_code)
90+
// }
91+
92+
// async function runPython() {
93+
// // run code currently stored in editor
94+
// let pyodide = await pyodideReadyPromise;
95+
// pyodide.globals.code_to_run = editor.getValue()
96+
// document.getElementById("output").innerText = pyodide.runPython('run_code(code_to_run)')
97+
// }
98+
99+
// async function get_pyodide() {
100+
// let pyodide = await loadPyodide({
101+
// indexURL: "https://cdn.jsdelivr.net/pyodide/v0.18.1/full/",
102+
// });
103+
// return pyodide;
104+
105+
// }
106+
107+
// let pyodideReadyPromise = get_pyodide();
108+
109+
// pyodideReadyPromise.then(setup_pyodide)

0 commit comments

Comments
 (0)