@volter/browser-python 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +14 -0
  3. package/dist/asgi-bridge.d.ts +3 -0
  4. package/dist/asgi-bridge.d.ts.map +1 -0
  5. package/dist/asgi-bridge.js +307 -0
  6. package/dist/asgi-bridge.js.map +1 -0
  7. package/dist/command.d.ts +20 -0
  8. package/dist/command.d.ts.map +1 -0
  9. package/dist/command.js +154 -0
  10. package/dist/command.js.map +1 -0
  11. package/dist/filesystem.d.ts +9 -0
  12. package/dist/filesystem.d.ts.map +1 -0
  13. package/dist/filesystem.js +96 -0
  14. package/dist/filesystem.js.map +1 -0
  15. package/dist/index.d.ts +4 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +3 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/package-manager.d.ts +8 -0
  20. package/dist/package-manager.d.ts.map +1 -0
  21. package/dist/package-manager.js +103 -0
  22. package/dist/package-manager.js.map +1 -0
  23. package/dist/process-host.d.ts +27 -0
  24. package/dist/process-host.d.ts.map +1 -0
  25. package/dist/process-host.js +326 -0
  26. package/dist/process-host.js.map +1 -0
  27. package/dist/protocol.d.ts +169 -0
  28. package/dist/protocol.d.ts.map +1 -0
  29. package/dist/protocol.js +2 -0
  30. package/dist/protocol.js.map +1 -0
  31. package/dist/pyodide-runtime.d.ts +37 -0
  32. package/dist/pyodide-runtime.d.ts.map +1 -0
  33. package/dist/pyodide-runtime.js +13 -0
  34. package/dist/pyodide-runtime.js.map +1 -0
  35. package/dist/server-host.d.ts +21 -0
  36. package/dist/server-host.d.ts.map +1 -0
  37. package/dist/server-host.js +526 -0
  38. package/dist/server-host.js.map +1 -0
  39. package/dist/sqlite-coherence.d.ts +19 -0
  40. package/dist/sqlite-coherence.d.ts.map +1 -0
  41. package/dist/sqlite-coherence.js +167 -0
  42. package/dist/sqlite-coherence.js.map +1 -0
  43. package/dist/subprocess-bridge.d.ts +12 -0
  44. package/dist/subprocess-bridge.d.ts.map +1 -0
  45. package/dist/subprocess-bridge.js +407 -0
  46. package/dist/subprocess-bridge.js.map +1 -0
  47. package/dist/worker.d.ts +2 -0
  48. package/dist/worker.d.ts.map +1 -0
  49. package/dist/worker.js +251 -0
  50. package/dist/worker.js.map +1 -0
  51. package/dist/wsgi-bridge.d.ts +21 -0
  52. package/dist/wsgi-bridge.d.ts.map +1 -0
  53. package/dist/wsgi-bridge.js +268 -0
  54. package/dist/wsgi-bridge.js.map +1 -0
  55. package/package.json +23 -0
package/dist/worker.js ADDED
@@ -0,0 +1,251 @@
1
+ import { absolutePythonPath, pythonBasename, restorePythonSnapshot, snapshotPythonFilesystem, } from "./filesystem.js";
2
+ import { installPythonPackages, parsePipInvocation, restorePythonPackages, } from "./package-manager.js";
3
+ import { loadPythonRuntime, } from "./pyodide-runtime.js";
4
+ import { ASGI_BRIDGE } from "./asgi-bridge.js";
5
+ import { pythonBootstrap, PythonServerClient, WSGI_BRIDGE } from "./wsgi-bridge.js";
6
+ import { PYTHON_SUBPROCESS_BOOTSTRAP, PythonProcessClient } from "./subprocess-bridge.js";
7
+ import { BrowserFileLockClient } from "@volter/browser-runtime/browser-file-locks.js";
8
+ import { BrowserFileCoherenceClient } from "@volter/browser-runtime/browser-file-coherence.js";
9
+ import { PythonSqliteCoherence } from "./sqlite-coherence.js";
10
+ const scope = globalThis;
11
+ let nextCommitId = 1;
12
+ const commitAcknowledgements = new Map();
13
+ let shutdownRequested = false;
14
+ let shutdownStarted = false;
15
+ let shutdownHandler;
16
+ let activeFilesystem;
17
+ let snapshotActiveFilesystem;
18
+ scope.onmessage = (event) => {
19
+ const message = event.data;
20
+ if (message.type === "run") {
21
+ void run(message);
22
+ return;
23
+ }
24
+ if (message.type === "shutdown") {
25
+ requestShutdown();
26
+ return;
27
+ }
28
+ const acknowledgement = commitAcknowledgements.get(message.commitId);
29
+ if (!acknowledgement)
30
+ return;
31
+ commitAcknowledgements.delete(message.commitId);
32
+ if (message.error)
33
+ acknowledgement.reject(new Error(message.error));
34
+ else
35
+ acknowledgement.resolve();
36
+ };
37
+ async function run(request) {
38
+ let pyodide;
39
+ let sqliteCoherence;
40
+ activeFilesystem = request.filesystem;
41
+ try {
42
+ pyodide = await loadPythonRuntime();
43
+ pyodide.setStdout({ batched: (chunk) => send({ type: "stdout", chunk: `${chunk}\n` }) });
44
+ pyodide.setStderr({ batched: (chunk) => send({ type: "stderr", chunk: `${chunk}\n` }) });
45
+ restorePythonSnapshot(pyodide.FS, request.filesystem);
46
+ sqliteCoherence = new PythonSqliteCoherence(pyodide.FS, new BrowserFileLockClient(request.fileLocks.channel), new BrowserFileCoherenceClient(request.fileCoherence), request.fileLocks.owner);
47
+ await sqliteCoherence.install(pyodide);
48
+ snapshotActiveFilesystem = () => snapshotPythonFilesystem(pyodide.FS, request.filesystem);
49
+ const commit = () => commitFilesystem(snapshotPythonFilesystem(pyodide.FS, request.filesystem));
50
+ const serverClient = new PythonServerClient(pyodide, request.serverPort, commit);
51
+ new PythonProcessClient(pyodide, request.serverPort);
52
+ await pyodide.runPythonAsync(PYTHON_SUBPROCESS_BOOTSTRAP);
53
+ await pyodide.runPythonAsync(`
54
+ import base64 as __browser_runtime_stdin_base64, io as __browser_runtime_stdin_io, sys as __browser_runtime_stdin_sys
55
+ __browser_runtime_stdin_sys.stdin = __browser_runtime_stdin_io.TextIOWrapper(
56
+ __browser_runtime_stdin_io.BytesIO(__browser_runtime_stdin_base64.b64decode(${JSON.stringify(request.stdinBase64)})),
57
+ encoding="utf-8",
58
+ )
59
+ `);
60
+ installShutdownHandler(async () => {
61
+ sqliteCoherence.releaseAll();
62
+ await commit();
63
+ sendResult(130, pyodide, request.filesystem);
64
+ });
65
+ const staticServer = parseStaticServer(request.argv, request.cwd);
66
+ if (staticServer) {
67
+ const result = await serverClient.listenStatic(staticServer.port, staticServer.root);
68
+ if (result < 0)
69
+ throw new Error(`python http.server could not listen on port ${staticServer.port} (${result}).`);
70
+ send({ type: "stdout", chunk: `Serving HTTP on 0.0.0.0 port ${staticServer.port} (http://localhost:${staticServer.port}/) ...\n` });
71
+ await forever();
72
+ return;
73
+ }
74
+ await restorePythonPackages(pyodide);
75
+ const pip = parsePipInvocation(pyodide.FS, request.argv, request.cwd);
76
+ if (pip) {
77
+ await installPythonPackages(pyodide, pip);
78
+ send({ type: "stdout", chunk: `Successfully installed ${pip.requirements.join(" ")}\n` });
79
+ sqliteCoherence.releaseAll();
80
+ sendResult(0, pyodide, request.filesystem);
81
+ return;
82
+ }
83
+ const asgiServer = parseAsgiServer(request.argv);
84
+ if (asgiServer) {
85
+ await pyodide.runPythonAsync(`
86
+ import importlib, os, sys
87
+ os.chdir(${JSON.stringify(request.cwd)})
88
+ os.environ.clear()
89
+ os.environ.update(${JSON.stringify(request.env)})
90
+ sys.argv = ${JSON.stringify(request.argv)}
91
+ if ${JSON.stringify(request.cwd)} not in sys.path:
92
+ sys.path.insert(0, ${JSON.stringify(request.cwd)})
93
+ __browser_runtime_asgi_module = importlib.import_module(${JSON.stringify(asgiServer.module)})
94
+ __browser_runtime_asgi_app = __browser_runtime_asgi_module
95
+ for __browser_runtime_asgi_part in ${JSON.stringify(asgiServer.attribute.split("."))}:
96
+ __browser_runtime_asgi_app = getattr(__browser_runtime_asgi_app, __browser_runtime_asgi_part)
97
+ __browser_runtime_asgi_port = ${asgiServer.port}
98
+ `);
99
+ await pyodide.runPythonAsync(ASGI_BRIDGE);
100
+ await pyodide.runPythonAsync("await __browser_runtime_start_asgi_lifespan()");
101
+ await commit();
102
+ const result = await serverClient.listenAsgi(asgiServer.port);
103
+ if (result < 0)
104
+ throw new Error(`Python ASGI app could not listen on port ${asgiServer.port} (${result}).`);
105
+ send({ type: "stdout", chunk: `Serving Python ASGI app on http://localhost:${asgiServer.port}/ ...\n` });
106
+ installShutdownHandler(async () => {
107
+ await serverClient.idle();
108
+ await pyodide.runPythonAsync("await __browser_runtime_stop_asgi_websockets()");
109
+ await pyodide.runPythonAsync("await __browser_runtime_stop_asgi_lifespan()");
110
+ sqliteCoherence.releaseAll();
111
+ await commit();
112
+ sendResult(130, pyodide, request.filesystem);
113
+ });
114
+ await forever();
115
+ return;
116
+ }
117
+ const { code, argv } = pythonInvocation(pyodide.FS, request.argv, request.cwd);
118
+ await pyodide.runPythonAsync(pythonBootstrap(request.cwd, request.env, argv, code));
119
+ const wsgiPort = Number(await pyodide.runPythonAsync("int(globals().get('__browser_runtime_wsgi_port', 0))"));
120
+ if (wsgiPort > 0) {
121
+ await pyodide.runPythonAsync(WSGI_BRIDGE);
122
+ await commit();
123
+ const result = await serverClient.listenWsgi(wsgiPort);
124
+ if (result < 0)
125
+ throw new Error(`Python WSGI app could not listen on port ${wsgiPort} (${result}).`);
126
+ send({ type: "stdout", chunk: `Serving Python WSGI app on http://localhost:${wsgiPort}/ ...\n` });
127
+ await forever();
128
+ return;
129
+ }
130
+ sqliteCoherence.releaseAll();
131
+ sendResult(0, pyodide, request.filesystem);
132
+ }
133
+ catch (error) {
134
+ try {
135
+ sqliteCoherence?.releaseAll();
136
+ }
137
+ catch { /* The original failure remains authoritative. */ }
138
+ send({
139
+ type: "result",
140
+ exitCode: 1,
141
+ filesystem: pyodide ? snapshotPythonFilesystem(pyodide.FS, request.filesystem) : request.filesystem,
142
+ error: error instanceof Error ? error.stack ?? error.message : String(error),
143
+ });
144
+ }
145
+ }
146
+ function pythonInvocation(fs, argv, cwd) {
147
+ const executable = pythonBasename(argv[0] ?? "");
148
+ const args = executable === "python" || executable === "python3" ? argv.slice(1) : argv;
149
+ if (args[0] === "-c" && args[1] !== undefined)
150
+ return { code: args[1], argv: ["-c", ...args.slice(2)] };
151
+ const path = args[0];
152
+ if (!path || path.startsWith("-"))
153
+ throw new Error("usage: python [-c command] | script.py [args...]");
154
+ const resolved = absolutePythonPath(path, cwd);
155
+ if (!fs.analyzePath(resolved).exists)
156
+ throw new Error(`python: can't open file '${path}': No such file or directory`);
157
+ return { code: new TextDecoder().decode(fs.readFile(resolved)), argv: [path, ...args.slice(1)] };
158
+ }
159
+ function parseStaticServer(argv, cwd) {
160
+ const executable = pythonBasename(argv[0] ?? "");
161
+ const args = executable === "python" || executable === "python3" ? argv.slice(1) : argv;
162
+ if (args[0] !== "-m" || args[1] !== "http.server")
163
+ return;
164
+ let port = 8000;
165
+ let root = cwd;
166
+ for (let index = 2; index < args.length; index += 1) {
167
+ if (args[index] === "--directory" && args[index + 1])
168
+ root = absolutePythonPath(args[++index], cwd);
169
+ else if (!args[index].startsWith("-"))
170
+ port = Number(args[index]);
171
+ }
172
+ if (!Number.isSafeInteger(port) || port <= 0 || port > 65_535)
173
+ throw new Error("http.server port must be 1..65535.");
174
+ return { port, root };
175
+ }
176
+ function parseAsgiServer(argv) {
177
+ const executable = pythonBasename(argv[0] ?? "");
178
+ const args = executable === "python" || executable === "python3" ? argv.slice(1) : argv;
179
+ const uvicorn = args[0] === "-m" && args[1] === "uvicorn" ? args.slice(2)
180
+ : pythonBasename(args[0] ?? "") === "uvicorn" ? args.slice(1) : undefined;
181
+ if (!uvicorn)
182
+ return;
183
+ let port = 8000;
184
+ let target;
185
+ for (let index = 0; index < uvicorn.length; index += 1) {
186
+ if (uvicorn[index] === "--port" && uvicorn[index + 1])
187
+ port = Number(uvicorn[++index]);
188
+ else if (uvicorn[index] === "--host" && uvicorn[index + 1])
189
+ index += 1;
190
+ else if (uvicorn[index] === "--no-access-log")
191
+ continue;
192
+ else if (uvicorn[index].startsWith("-")) {
193
+ throw new Error(`browser uvicorn does not support option: ${uvicorn[index]}`);
194
+ }
195
+ else if (!target)
196
+ target = uvicorn[index];
197
+ else
198
+ throw new Error(`browser uvicorn does not support argument: ${uvicorn[index]}`);
199
+ }
200
+ if (!target || !target.includes(":"))
201
+ throw new Error("uvicorn requires an ASGI target such as main:app.");
202
+ const [module, attribute] = target.split(":", 2);
203
+ if (!module || !attribute || !/^[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*$/u.test(module)
204
+ || !/^[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*$/u.test(attribute)) {
205
+ throw new Error("Invalid uvicorn ASGI target.");
206
+ }
207
+ if (!Number.isSafeInteger(port) || port <= 0 || port > 65_535)
208
+ throw new Error("uvicorn port must be 1..65535.");
209
+ return { module, attribute, port };
210
+ }
211
+ function sendResult(exitCode, pyodide, original) {
212
+ send({ type: "result", exitCode, filesystem: snapshotPythonFilesystem(pyodide.FS, original) });
213
+ }
214
+ function commitFilesystem(filesystem) {
215
+ const commitId = nextCommitId++;
216
+ return new Promise((resolve, reject) => {
217
+ commitAcknowledgements.set(commitId, { resolve, reject });
218
+ send({ type: "commit", commitId, filesystem });
219
+ });
220
+ }
221
+ function installShutdownHandler(handler) {
222
+ shutdownHandler = handler;
223
+ beginShutdown();
224
+ }
225
+ function requestShutdown() {
226
+ shutdownRequested = true;
227
+ beginShutdown();
228
+ }
229
+ function beginShutdown() {
230
+ const filesystem = activeFilesystem;
231
+ if (!shutdownRequested || shutdownStarted || !shutdownHandler || !filesystem)
232
+ return;
233
+ shutdownStarted = true;
234
+ void shutdownHandler().catch((error) => send({
235
+ type: "result",
236
+ exitCode: 1,
237
+ filesystem: currentFilesystem(filesystem),
238
+ error: error instanceof Error ? error.stack ?? error.message : String(error),
239
+ }));
240
+ }
241
+ function currentFilesystem(fallback) {
242
+ try {
243
+ return snapshotActiveFilesystem?.() ?? fallback;
244
+ }
245
+ catch {
246
+ return fallback;
247
+ }
248
+ }
249
+ function forever() { return new Promise(() => undefined); }
250
+ function send(message) { postMessage(message); }
251
+ //# sourceMappingURL=worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { PyodideRuntime } from "./pyodide-runtime.js";
2
+ /** Worker-side virtual server client. Requests are serialized through one CPython interpreter. */
3
+ export declare class PythonServerClient {
4
+ private readonly pyodide;
5
+ private readonly port;
6
+ private readonly commit;
7
+ private readonly acknowledgements;
8
+ private nextRequestId;
9
+ private requestQueue;
10
+ constructor(pyodide: PyodideRuntime, port: MessagePort, commit: () => Promise<void>);
11
+ listenStatic(port: number, root: string): Promise<number>;
12
+ listenWsgi(port: number): Promise<number>;
13
+ listenAsgi(port: number): Promise<number>;
14
+ idle(): Promise<void>;
15
+ private listen;
16
+ private handleRequest;
17
+ private handleWebSocket;
18
+ }
19
+ export declare function pythonBootstrap(cwd: string, env: Record<string, string>, argv: string[], code: string): string;
20
+ export declare const WSGI_BRIDGE: string;
21
+ //# sourceMappingURL=wsgi-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wsgi-bridge.d.ts","sourceRoot":"","sources":["../src/wsgi-bridge.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,kGAAkG;AAClG,qBAAa,kBAAkB;IAM3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPzB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA+C;IAChF,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,YAAY,CAAqB;gBAGtB,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC;IA6D9C,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIzD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIzC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIzC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,OAAO,CAAC,MAAM;YAeA,aAAa;YAgFb,eAAe;CAyB9B;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,EAAE,MAAM,GACX,MAAM,CAkBR;AAED,eAAO,MAAM,WAAW,QA4DvB,CAAC"}
@@ -0,0 +1,268 @@
1
+ /** Worker-side virtual server client. Requests are serialized through one CPython interpreter. */
2
+ export class PythonServerClient {
3
+ pyodide;
4
+ port;
5
+ commit;
6
+ acknowledgements = new Map();
7
+ nextRequestId = 1;
8
+ requestQueue = Promise.resolve();
9
+ constructor(pyodide, port, commit) {
10
+ this.pyodide = pyodide;
11
+ this.port = port;
12
+ this.commit = commit;
13
+ pyodide.globals.set("__browser_runtime_asgi_websocket_callback", (rawFrame) => {
14
+ const frame = JSON.parse(String(rawFrame));
15
+ if (frame.type === "opened") {
16
+ this.port.postMessage({
17
+ type: "websocket-opened",
18
+ connectionId: frame.connectionId,
19
+ protocol: frame.protocol ?? "",
20
+ });
21
+ }
22
+ else if (frame.type === "message") {
23
+ this.port.postMessage({
24
+ type: "websocket-message",
25
+ connectionId: frame.connectionId,
26
+ data: frame.kind === "binary"
27
+ ? { kind: "binary", base64: frame.base64 ?? "" }
28
+ : { kind: "text", text: frame.text ?? "" },
29
+ });
30
+ }
31
+ else if (frame.type === "close") {
32
+ this.port.postMessage({
33
+ type: "websocket-close",
34
+ connectionId: frame.connectionId,
35
+ code: frame.code ?? 1000,
36
+ reason: frame.reason ?? "",
37
+ clean: frame.clean !== false,
38
+ });
39
+ }
40
+ else if (frame.type === "error") {
41
+ this.port.postMessage({
42
+ type: "websocket-error",
43
+ connectionId: frame.connectionId,
44
+ error: frame.error ?? "Python ASGI WebSocket failed.",
45
+ });
46
+ }
47
+ });
48
+ port.onmessage = (event) => {
49
+ const message = event.data;
50
+ if (message.type === "ack") {
51
+ const resolve = this.acknowledgements.get(message.requestId);
52
+ if (!resolve)
53
+ return;
54
+ this.acknowledgements.delete(message.requestId);
55
+ resolve(message.result);
56
+ return;
57
+ }
58
+ this.requestQueue = this.requestQueue.then(() => message.type === "http-request"
59
+ ? this.handleRequest(message)
60
+ : this.handleWebSocket(message));
61
+ };
62
+ port.start();
63
+ }
64
+ listenStatic(port, root) {
65
+ return this.listen({ type: "listen", requestId: 0, port, server: "static", root });
66
+ }
67
+ listenWsgi(port) {
68
+ return this.listen({ type: "listen", requestId: 0, port, server: "wsgi" });
69
+ }
70
+ listenAsgi(port) {
71
+ return this.listen({ type: "listen", requestId: 0, port, server: "asgi" });
72
+ }
73
+ idle() {
74
+ return this.requestQueue;
75
+ }
76
+ listen(message) {
77
+ const requestId = this.nextRequestId++;
78
+ return new Promise((resolve) => {
79
+ const timeout = setTimeout(() => {
80
+ this.acknowledgements.delete(requestId);
81
+ resolve(-110);
82
+ }, 5_000);
83
+ this.acknowledgements.set(requestId, (result) => {
84
+ clearTimeout(timeout);
85
+ resolve(result);
86
+ });
87
+ this.port.postMessage({ ...message, requestId });
88
+ });
89
+ }
90
+ async handleRequest(message) {
91
+ const streaming = message.application === "asgi" && message.streaming === true;
92
+ try {
93
+ const payload = JSON.stringify({
94
+ method: message.method,
95
+ url: message.url,
96
+ headers: message.headers,
97
+ bodyBase64: message.bodyBase64,
98
+ });
99
+ const handler = message.application === "asgi" ? "__browser_runtime_handle_asgi" : "__browser_runtime_handle_wsgi";
100
+ if (streaming) {
101
+ this.pyodide.globals.set("__browser_runtime_asgi_stream_callback", (rawFrame) => {
102
+ const frame = JSON.parse(String(rawFrame));
103
+ if (frame.type === "start") {
104
+ this.port.postMessage({
105
+ type: "http-stream-start",
106
+ requestId: message.requestId,
107
+ statusCode: frame.statusCode ?? 500,
108
+ statusMessage: frame.statusMessage ?? "",
109
+ headers: frame.headers ?? {},
110
+ });
111
+ }
112
+ else if (frame.type === "chunk") {
113
+ this.port.postMessage({
114
+ type: "http-stream-chunk",
115
+ requestId: message.requestId,
116
+ bodyBase64: frame.bodyBase64 ?? "",
117
+ });
118
+ }
119
+ });
120
+ }
121
+ const invocation = message.application === "asgi"
122
+ ? `await ${handler}(${JSON.stringify(payload)}, ${streaming ? "True" : "False"})`
123
+ : `${handler}(${JSON.stringify(payload)})`;
124
+ const raw = await this.pyodide.runPythonAsync(invocation);
125
+ if (streaming) {
126
+ await this.commit();
127
+ this.port.postMessage({ type: "http-stream-end", requestId: message.requestId });
128
+ return;
129
+ }
130
+ const response = JSON.parse(String(raw));
131
+ await this.commit();
132
+ this.port.postMessage({
133
+ type: "http-response",
134
+ requestId: message.requestId,
135
+ ...response,
136
+ });
137
+ }
138
+ catch (cause) {
139
+ if (message.application === "asgi" && message.streaming === true) {
140
+ this.port.postMessage({
141
+ type: "http-stream-error",
142
+ requestId: message.requestId,
143
+ error: cause instanceof Error ? cause.message : String(cause),
144
+ });
145
+ return;
146
+ }
147
+ this.port.postMessage({
148
+ type: "http-response",
149
+ requestId: message.requestId,
150
+ statusCode: 500,
151
+ statusMessage: "Internal Server Error",
152
+ headers: {},
153
+ bodyBase64: "",
154
+ error: cause instanceof Error ? cause.message : String(cause),
155
+ });
156
+ }
157
+ finally {
158
+ if (streaming)
159
+ this.pyodide.globals.set("__browser_runtime_asgi_stream_callback", () => undefined);
160
+ }
161
+ }
162
+ async handleWebSocket(message) {
163
+ const payload = JSON.stringify(message);
164
+ try {
165
+ if (message.type === "websocket-open") {
166
+ await this.pyodide.runPythonAsync(`await __browser_runtime_open_asgi_websocket(${JSON.stringify(payload)})`);
167
+ }
168
+ else {
169
+ await this.pyodide.runPythonAsync(`await __browser_runtime_asgi_websocket_event(${JSON.stringify(payload)})`);
170
+ }
171
+ }
172
+ catch (cause) {
173
+ this.port.postMessage({
174
+ type: "websocket-error",
175
+ connectionId: message.connectionId,
176
+ error: cause instanceof Error ? cause.message : String(cause),
177
+ });
178
+ this.port.postMessage({
179
+ type: "websocket-close",
180
+ connectionId: message.connectionId,
181
+ code: 1011,
182
+ reason: "Python ASGI WebSocket failed",
183
+ clean: false,
184
+ });
185
+ }
186
+ }
187
+ }
188
+ export function pythonBootstrap(cwd, env, argv, code) {
189
+ return `
190
+ import os, sys
191
+ os.chdir(${JSON.stringify(cwd)})
192
+ os.environ.clear()
193
+ os.environ.update(${JSON.stringify(env)})
194
+ sys.argv = ${JSON.stringify(argv)}
195
+ globals()["__name__"] = "__main__"
196
+ try:
197
+ import flask as __browser_runtime_flask
198
+ def __browser_runtime_flask_run(self, host=None, port=None, **options):
199
+ globals()["__browser_runtime_wsgi_app"] = self
200
+ globals()["__browser_runtime_wsgi_port"] = int(port or 5000)
201
+ __browser_runtime_flask.Flask.run = __browser_runtime_flask_run
202
+ except ImportError:
203
+ pass
204
+ exec(compile(${JSON.stringify(code)}, ${JSON.stringify(argv[0] ?? "<string>")}, "exec"), globals(), globals())
205
+ `;
206
+ }
207
+ export const WSGI_BRIDGE = String.raw `
208
+ import base64, io, json, sys
209
+ from urllib.parse import urlsplit
210
+
211
+ def __browser_runtime_handle_wsgi(payload_json):
212
+ payload = json.loads(payload_json)
213
+ parsed = urlsplit(payload["url"])
214
+ body = base64.b64decode(payload.get("bodyBase64", ""))
215
+ headers = payload.get("headers", {})
216
+ environ = {
217
+ "REQUEST_METHOD": payload["method"],
218
+ "SCRIPT_NAME": "",
219
+ "PATH_INFO": parsed.path,
220
+ "QUERY_STRING": parsed.query,
221
+ "SERVER_NAME": "localhost",
222
+ "SERVER_PORT": str(globals()["__browser_runtime_wsgi_port"]),
223
+ "SERVER_PROTOCOL": "HTTP/1.1",
224
+ "REMOTE_ADDR": "127.0.0.1",
225
+ "wsgi.version": (1, 0),
226
+ "wsgi.url_scheme": "http",
227
+ "wsgi.input": io.BytesIO(body),
228
+ "wsgi.errors": sys.stderr,
229
+ "wsgi.multithread": False,
230
+ "wsgi.multiprocess": False,
231
+ "wsgi.run_once": False,
232
+ }
233
+ for name, value in headers.items():
234
+ key = name.upper().replace("-", "_")
235
+ if key == "CONTENT_TYPE":
236
+ environ["CONTENT_TYPE"] = value
237
+ elif key == "CONTENT_LENGTH":
238
+ environ["CONTENT_LENGTH"] = value
239
+ else:
240
+ environ["HTTP_" + key] = value
241
+ if body and "CONTENT_LENGTH" not in environ:
242
+ environ["CONTENT_LENGTH"] = str(len(body))
243
+ captured = {}
244
+ def start_response(status, response_headers, exc_info=None):
245
+ captured["status"] = status
246
+ captured["headers"] = response_headers
247
+ chunks = globals()["__browser_runtime_wsgi_app"](environ, start_response)
248
+ try:
249
+ response_body = b"".join(chunks)
250
+ finally:
251
+ if hasattr(chunks, "close"):
252
+ chunks.close()
253
+ status_parts = captured.get("status", "500 Internal Server Error").split(" ", 1)
254
+ response_headers = {}
255
+ for name, value in captured.get("headers", []):
256
+ if name in response_headers:
257
+ existing = response_headers[name]
258
+ response_headers[name] = existing + [value] if isinstance(existing, list) else [existing, value]
259
+ else:
260
+ response_headers[name] = value
261
+ return json.dumps({
262
+ "statusCode": int(status_parts[0]),
263
+ "statusMessage": status_parts[1] if len(status_parts) > 1 else "",
264
+ "headers": response_headers,
265
+ "bodyBase64": base64.b64encode(response_body).decode("ascii"),
266
+ })
267
+ `;
268
+ //# sourceMappingURL=wsgi-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wsgi-bridge.js","sourceRoot":"","sources":["../src/wsgi-bridge.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@volter/browser-python",
3
+ "version": "0.1.0",
4
+ "description": "Pyodide application lane for the browser execution chassis",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/volter-ai/browser-substrate.git",
9
+ "directory": "packages/python"
10
+ },
11
+ "publishConfig": { "access": "public" },
12
+ "files": ["dist", "README.md", "LICENSE"],
13
+ "type": "module",
14
+ "types": "./dist/index.d.ts",
15
+ "dependencies": {
16
+ "@volter/browser-runtime": "^0.1.0"
17
+ },
18
+ "exports": {
19
+ ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" },
20
+ "./*.js": { "types": "./dist/*.d.ts", "import": "./dist/*.js" }
21
+ },
22
+ "scripts": { "build": "tsc -p tsconfig.build.json" }
23
+ }