Skip to content

Commit c901bc0

Browse files
coolreader18youknowone
authored andcommitted
Upgrade wasm deps + fix demo
1 parent b7db23b commit c901bc0

File tree

10 files changed

+121
-85
lines changed

10 files changed

+121
-85
lines changed

Lib/_dummy_os.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,30 @@
55
try:
66
from os import *
77
except ImportError:
8-
import abc
8+
import abc, sys
99

1010
def __getattr__(name):
11-
raise OSError("no os specific module found")
11+
if name in {"_path_normpath", "__path__"}:
12+
raise AttributeError(name)
13+
if name.isupper():
14+
return 0
15+
def dummy(*args, **kwargs):
16+
import io
17+
return io.UnsupportedOperation(f"{name}: no os specific module found")
18+
dummy.__name__ = f"dummy_{name}"
19+
return dummy
1220

13-
def _shim():
14-
import _dummy_os, sys
15-
sys.modules['os'] = _dummy_os
16-
sys.modules['os.path'] = _dummy_os.path
21+
sys.modules['os'] = sys.modules['posix'] = sys.modules[__name__]
1722

1823
import posixpath as path
19-
import sys
2024
sys.modules['os.path'] = path
2125
del sys
2226

2327
sep = path.sep
28+
supports_dir_fd = set()
29+
supports_effective_ids = set()
30+
supports_fd = set()
31+
supports_follow_symlinks = set()
2432

2533

2634
def fspath(path):

Lib/io.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,15 @@
5555
import abc
5656

5757
from _io import (DEFAULT_BUFFER_SIZE, BlockingIOError, UnsupportedOperation,
58-
open, open_code, FileIO, BytesIO, StringIO, BufferedReader,
58+
open, open_code, BytesIO, StringIO, BufferedReader,
5959
BufferedWriter, BufferedRWPair, BufferedRandom,
6060
IncrementalNewlineDecoder, text_encoding, TextIOWrapper)
6161

62+
try:
63+
from _io import FileIO
64+
except ImportError:
65+
pass
66+
6267
# Pretend this exception was created here.
6368
UnsupportedOperation.__module__ = "io"
6469

@@ -82,7 +87,10 @@ class BufferedIOBase(_io._BufferedIOBase, IOBase):
8287
class TextIOBase(_io._TextIOBase, IOBase):
8388
__doc__ = _io._TextIOBase.__doc__
8489

85-
RawIOBase.register(FileIO)
90+
try:
91+
RawIOBase.register(FileIO)
92+
except NameError:
93+
pass
8694

8795
for klass in (BytesIO, BufferedReader, BufferedWriter, BufferedRandom,
8896
BufferedRWPair):

wasm/demo/package.json

+15-14
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,25 @@
44
"description": "Bindings to the RustPython library for WebAssembly",
55
"main": "index.js",
66
"dependencies": {
7-
"codemirror": "^5.42.0",
8-
"local-echo": "^0.2.0",
9-
"xterm": "^3.8.0"
7+
"@codemirror/lang-python": "^6.1.6",
8+
"@xterm/addon-fit": "^0.10.0",
9+
"@xterm/xterm": "^5.3.0",
10+
"codemirror": "^6.0.1",
11+
"upgrade": "^1.1.0",
12+
"xterm-readline": "^1.1.2"
1013
},
1114
"devDependencies": {
12-
"@wasm-tool/wasm-pack-plugin": "^1.1.0",
13-
"clean-webpack-plugin": "^3.0.0",
14-
"css-loader": "^3.4.1",
15-
"html-webpack-plugin": "^3.2.0",
16-
"mini-css-extract-plugin": "^0.9.0",
17-
"raw-loader": "^4.0.0",
18-
"serve": "^11.0.2",
19-
"webpack": "^4.16.3",
20-
"webpack-cli": "^3.1.0",
21-
"webpack-dev-server": "^3.1.5"
15+
"@wasm-tool/wasm-pack-plugin": "^1.7.0",
16+
"css-loader": "^7.1.2",
17+
"html-webpack-plugin": "^5.6.3",
18+
"mini-css-extract-plugin": "^2.9.2",
19+
"serve": "^14.2.4",
20+
"webpack": "^5.97.1",
21+
"webpack-cli": "^6.0.1",
22+
"webpack-dev-server": "^5.2.0"
2223
},
2324
"scripts": {
24-
"dev": "webpack-dev-server -d",
25+
"dev": "webpack serve",
2526
"build": "webpack",
2627
"dist": "webpack --mode production",
2728
"test": "webpack --mode production && cd ../tests && pytest"

wasm/demo/snippets/import_pypi.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
import asyncweb
2-
import whlimport
3-
4-
whlimport.setup()
5-
61
# make sys.modules['os'] a dumb version of the os module, which has posixpath
72
# available as os.path as well as a few other utilities, but will raise an
83
# OSError for anything that actually requires an OS
94
import _dummy_os
10-
_dummy_os._shim()
5+
6+
import asyncweb
7+
import whlimport
8+
9+
whlimport.setup()
1110

1211
@asyncweb.main
1312
async def main():

wasm/demo/src/browser_module.rs

Whitespace-only changes.

wasm/demo/src/index.ejs

+1-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
browser's devtools and play with <code>rp.pyEval('1 + 1')</code>
1515
</p>
1616
<div id="code-wrapper">
17-
<textarea id="code"><%= defaultSnippet %></textarea>
1817
<select id="snippets">
1918
<% for (const name of snippets) { %>
2019
<option
@@ -77,7 +76,7 @@
7776
<a href="https://github.com/RustPython/RustPython">
7877
<img
7978
style="position: absolute; top: 0; right: 0; border: 0;"
80-
src="https://s3.amazonaws.com/github/ribbons/forkme_right_green_007200.png"
79+
src="https://github.blog/wp-content/uploads/2008/12/forkme_right_green_007200.png"
8180
alt="Fork me on GitHub"
8281
/>
8382
</a>

wasm/demo/src/index.js

+52-49
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import './style.css';
2-
import 'xterm/lib/xterm.css';
3-
import CodeMirror from 'codemirror';
4-
import 'codemirror/mode/python/python';
5-
import 'codemirror/addon/comment/comment';
6-
import 'codemirror/lib/codemirror.css';
7-
import { Terminal } from 'xterm';
8-
import LocalEchoController from 'local-echo';
2+
import '@xterm/xterm/css/xterm.css';
3+
import { EditorView, basicSetup } from 'codemirror';
4+
import { keymap } from '@codemirror/view';
5+
import { indentUnit } from '@codemirror/language';
6+
import { indentWithTab } from '@codemirror/commands';
7+
import { python } from '@codemirror/lang-python';
8+
import { Terminal } from '@xterm/xterm';
9+
import { FitAddon } from '@xterm/addon-fit';
10+
import { Readline } from 'xterm-readline';
911

1012
let rp;
1113

@@ -22,23 +24,24 @@ import('rustpython')
2224
document.getElementById('error').textContent = e;
2325
});
2426

25-
const editor = CodeMirror.fromTextArea(document.getElementById('code'), {
26-
extraKeys: {
27-
'Ctrl-Enter': runCodeFromTextarea,
28-
'Cmd-Enter': runCodeFromTextarea,
29-
'Shift-Tab': 'indentLess',
30-
'Ctrl-/': 'toggleComment',
31-
'Cmd-/': 'toggleComment',
32-
Tab: (editor) => {
33-
var spaces = Array(editor.getOption('indentUnit') + 1).join(' ');
34-
editor.replaceSelection(spaces);
35-
},
36-
},
37-
lineNumbers: true,
38-
mode: 'text/x-python',
39-
indentUnit: 4,
40-
autofocus: true,
27+
const fixedHeightEditor = EditorView.theme({
28+
'&': { height: '100%' },
29+
'.cm-scroller': { overflow: 'auto' },
4130
});
31+
const editor = new EditorView({
32+
parent: document.getElementById('code-wrapper'),
33+
extensions: [
34+
basicSetup,
35+
python(),
36+
keymap.of(
37+
{ key: 'Ctrl-Enter', mac: 'Cmd-Enter', run: runCodeFromTextarea },
38+
indentWithTab,
39+
),
40+
indentUnit.of(' '),
41+
fixedHeightEditor,
42+
],
43+
});
44+
editor.focus();
4245

4346
const consoleElement = document.getElementById('console');
4447
const errorElement = document.getElementById('error');
@@ -48,7 +51,7 @@ function runCodeFromTextarea() {
4851
consoleElement.value = '';
4952
errorElement.textContent = '';
5053

51-
const code = editor.getValue();
54+
const code = editor.state.doc.toString();
5255
try {
5356
rp.pyExec(code, {
5457
stdout: (output) => {
@@ -78,18 +81,25 @@ function updateSnippet() {
7881
// the require here creates a webpack context; it's fine to use it
7982
// dynamically.
8083
// https://webpack.js.org/guides/dependency-management/
81-
const { default: snippet } = require(
82-
`raw-loader!../snippets/${selected}.py`,
83-
);
84+
const snippet = require(`../snippets/${selected}.py?raw`);
8485

85-
editor.setValue(snippet);
86-
runCodeFromTextarea();
86+
editor.dispatch({
87+
changes: { from: 0, to: editor.state.doc.length, insert: snippet },
88+
});
8789
}
90+
function updateSnippetAndRun() {
91+
updateSnippet();
92+
requestAnimationFrame(runCodeFromTextarea);
93+
}
94+
updateSnippet();
8895

8996
const term = new Terminal();
97+
const readline = new Readline();
98+
const fitAddon = new FitAddon();
99+
term.loadAddon(readline);
100+
term.loadAddon(fitAddon);
90101
term.open(document.getElementById('terminal'));
91-
92-
const localEcho = new LocalEchoController(term);
102+
fitAddon.fit();
93103

94104
let terminalVM;
95105

@@ -107,48 +117,41 @@ finally:
107117
}
108118

109119
async function readPrompts() {
110-
let continuing = false;
120+
let continuing = '';
111121

112122
while (true) {
113-
const ps1 = getPrompt('ps1');
114-
const ps2 = getPrompt('ps2');
115-
let input;
123+
let input = await readline.read(getPrompt(continuing ? 'ps2' : 'ps1'));
124+
if (input.endsWith('\n')) input = input.slice(0, -1);
116125
if (continuing) {
117-
const prom = localEcho.read(ps2, ps2);
118-
localEcho._activePrompt.prompt = ps1;
119-
localEcho._input = localEcho.history.entries.pop() + '\n';
120-
localEcho._cursor = localEcho._input.length;
121-
localEcho._active = true;
122-
input = await prom;
123-
if (!input.endsWith('\n')) continue;
124-
} else {
125-
input = await localEcho.read(ps1, ps2);
126+
input = continuing += '\n' + input;
127+
if (!continuing.endsWith('\n')) continue;
126128
}
127129
try {
130+
console.log([input]);
128131
terminalVM.execSingle(input);
129132
} catch (err) {
130133
if (err.canContinue) {
131-
continuing = true;
134+
continuing = input;
132135
continue;
133136
} else if (err instanceof WebAssembly.RuntimeError) {
134137
err = window.__RUSTPYTHON_ERROR || err;
135138
}
136-
localEcho.println(err);
139+
readline.print('' + err);
137140
}
138-
continuing = false;
141+
continuing = '';
139142
}
140143
}
141144

142145
function onReady() {
143-
snippets.addEventListener('change', updateSnippet);
146+
snippets.addEventListener('change', updateSnippetAndRun);
144147
document
145148
.getElementById('run-btn')
146149
.addEventListener('click', runCodeFromTextarea);
147150
// Run once for demo
148151
runCodeFromTextarea();
149152

150153
terminalVM = rp.vmStore.init('term_vm');
151-
terminalVM.setStdout((data) => localEcho.print(data));
154+
terminalVM.setStdout((data) => readline.print(data));
152155
readPrompts().catch((err) => console.error(err));
153156

154157
// so that the test knows that we're ready

wasm/demo/src/style.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ textarea {
33
resize: vertical;
44
}
55

6-
#code,
6+
#code-wrapper,
77
#console {
88
height: 30vh;
99
width: calc(100% - 3px);

wasm/demo/webpack.config.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
const HtmlWebpackPlugin = require('html-webpack-plugin');
22
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
33
const WasmPackPlugin = require('@wasm-tool/wasm-pack-plugin');
4-
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
54

65
const path = require('path');
76
const fs = require('fs');
@@ -12,6 +11,7 @@ module.exports = (env = {}) => {
1211
output: {
1312
path: path.join(__dirname, 'dist'),
1413
filename: 'index.js',
14+
clean: true,
1515
},
1616
mode: 'development',
1717
resolve: {
@@ -28,10 +28,17 @@ module.exports = (env = {}) => {
2828
test: /\.css$/,
2929
use: [MiniCssExtractPlugin.loader, 'css-loader'],
3030
},
31+
{
32+
resourceQuery: '?raw',
33+
type: 'asset/source',
34+
},
35+
{
36+
test: /\.wasm$/,
37+
type: 'webassembly/async',
38+
},
3139
],
3240
},
3341
plugins: [
34-
new CleanWebpackPlugin(),
3542
new HtmlWebpackPlugin({
3643
filename: 'index.html',
3744
template: 'src/index.ejs',
@@ -51,6 +58,9 @@ module.exports = (env = {}) => {
5158
filename: 'styles.css',
5259
}),
5360
],
61+
experiments: {
62+
asyncWebAssembly: true,
63+
},
5464
};
5565
if (!env.noWasmPack) {
5666
config.plugins.push(

wasm/lib/src/convert.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use crate::js_module;
44
use crate::vm_class::{stored_vm_from_wasm, WASMVirtualMachine};
55
use js_sys::{Array, ArrayBuffer, Object, Promise, Reflect, SyntaxError, Uint8Array};
6-
use rustpython_parser::ParseErrorType;
6+
use rustpython_parser::{lexer::LexicalErrorType, ParseErrorType};
77
use rustpython_vm::{
88
builtins::PyBaseExceptionRef,
99
compiler::{CompileError, CompileErrorType},
@@ -258,7 +258,15 @@ pub fn syntax_err(err: CompileError) -> SyntaxError {
258258
&"col".into(),
259259
&(err.location.unwrap().column.get()).into(),
260260
);
261-
let can_continue = matches!(&err.error, CompileErrorType::Parse(ParseErrorType::Eof));
261+
let can_continue = matches!(
262+
&err.error,
263+
CompileErrorType::Parse(
264+
ParseErrorType::Eof
265+
| ParseErrorType::Lexical(LexicalErrorType::Eof)
266+
| ParseErrorType::Lexical(LexicalErrorType::IndentationError)
267+
| ParseErrorType::UnrecognizedToken(rustpython_parser::Tok::Dedent, _)
268+
)
269+
);
262270
let _ = Reflect::set(&js_err, &"canContinue".into(), &can_continue.into());
263271
js_err
264272
}

0 commit comments

Comments
 (0)