tywrap 0.4.0 → 0.5.1
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.
- package/README.md +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/runtime/base.d.ts +7 -7
- package/dist/runtime/base.js +8 -8
- package/dist/runtime/bounded-context.d.ts +15 -31
- package/dist/runtime/bounded-context.d.ts.map +1 -1
- package/dist/runtime/bounded-context.js +16 -15
- package/dist/runtime/bounded-context.js.map +1 -1
- package/dist/runtime/http.d.ts +24 -5
- package/dist/runtime/http.d.ts.map +1 -1
- package/dist/runtime/http.js +57 -12
- package/dist/runtime/http.js.map +1 -1
- package/dist/runtime/node.d.ts +33 -7
- package/dist/runtime/node.d.ts.map +1 -1
- package/dist/runtime/node.js +139 -151
- package/dist/runtime/node.js.map +1 -1
- package/dist/runtime/pooled-transport.d.ts +2 -18
- package/dist/runtime/pooled-transport.d.ts.map +1 -1
- package/dist/runtime/pooled-transport.js +2 -29
- package/dist/runtime/pooled-transport.js.map +1 -1
- package/dist/runtime/process-io.d.ts +2 -18
- package/dist/runtime/process-io.d.ts.map +1 -1
- package/dist/runtime/process-io.js +3 -30
- package/dist/runtime/process-io.js.map +1 -1
- package/dist/runtime/pyodide-bootstrap-core.generated.d.ts +12 -0
- package/dist/runtime/pyodide-bootstrap-core.generated.d.ts.map +1 -0
- package/dist/runtime/pyodide-bootstrap-core.generated.js +12 -0
- package/dist/runtime/pyodide-bootstrap-core.generated.js.map +1 -0
- package/dist/runtime/pyodide-io.d.ts +7 -37
- package/dist/runtime/pyodide-io.d.ts.map +1 -1
- package/dist/runtime/pyodide-io.js +90 -214
- package/dist/runtime/pyodide-io.js.map +1 -1
- package/dist/runtime/pyodide.d.ts +25 -5
- package/dist/runtime/pyodide.d.ts.map +1 -1
- package/dist/runtime/pyodide.js +59 -10
- package/dist/runtime/pyodide.js.map +1 -1
- package/dist/runtime/{bridge-protocol.d.ts → rpc-client.d.ts} +59 -46
- package/dist/runtime/rpc-client.d.ts.map +1 -0
- package/dist/runtime/{bridge-protocol.js → rpc-client.js} +60 -42
- package/dist/runtime/rpc-client.js.map +1 -0
- package/dist/runtime/worker-pool.d.ts +2 -19
- package/dist/runtime/worker-pool.d.ts.map +1 -1
- package/dist/runtime/worker-pool.js +2 -30
- package/dist/runtime/worker-pool.js.map +1 -1
- package/dist/types/index.d.ts +8 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/tywrap.d.ts.map +1 -1
- package/dist/tywrap.js +1 -3
- package/dist/tywrap.js.map +1 -1
- package/package.json +9 -12
- package/runtime/__pycache__/safe_codec.cpython-311.pyc +0 -0
- package/runtime/__pycache__/tywrap_bridge_core.cpython-311.pyc +0 -0
- package/runtime/python_bridge.py +85 -702
- package/runtime/safe_codec.py +10 -2
- package/runtime/tywrap_bridge_core.py +875 -0
- package/src/index.ts +6 -6
- package/src/runtime/base.ts +8 -8
- package/src/runtime/bounded-context.ts +17 -56
- package/src/runtime/http.ts +85 -13
- package/src/runtime/node.ts +165 -217
- package/src/runtime/pooled-transport.ts +2 -57
- package/src/runtime/process-io.ts +3 -55
- package/src/runtime/pyodide-bootstrap-core.generated.ts +12 -0
- package/src/runtime/pyodide-io.ts +92 -243
- package/src/runtime/pyodide.ts +87 -10
- package/src/runtime/{bridge-protocol.ts → rpc-client.ts} +76 -49
- package/src/runtime/worker-pool.ts +2 -58
- package/src/types/index.ts +20 -4
- package/src/tywrap.ts +1 -3
- package/dist/core/analyzer.d.ts +0 -64
- package/dist/core/analyzer.d.ts.map +0 -1
- package/dist/core/analyzer.js +0 -710
- package/dist/core/analyzer.js.map +0 -1
- package/dist/runtime/bridge-core.d.ts +0 -65
- package/dist/runtime/bridge-core.d.ts.map +0 -1
- package/dist/runtime/bridge-core.js +0 -379
- package/dist/runtime/bridge-core.js.map +0 -1
- package/dist/runtime/bridge-protocol.d.ts.map +0 -1
- package/dist/runtime/bridge-protocol.js.map +0 -1
- package/dist/utils/parallel-processor.d.ts +0 -146
- package/dist/utils/parallel-processor.d.ts.map +0 -1
- package/dist/utils/parallel-processor.js +0 -707
- package/dist/utils/parallel-processor.js.map +0 -1
- package/src/core/analyzer.ts +0 -824
- package/src/runtime/bridge-core.ts +0 -494
- package/src/utils/parallel-processor.ts +0 -955
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
*
|
|
14
14
|
* @see https://github.com/bbopen/tywrap/issues/149
|
|
15
15
|
*/
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
16
|
+
import { DisposableBase } from './bounded-context.js';
|
|
17
|
+
import { BridgeProtocolError } from './errors.js';
|
|
18
|
+
import { PYODIDE_BRIDGE_CORE_SOURCE } from './pyodide-bootstrap-core.generated.js';
|
|
18
19
|
import { PROTOCOL_ID, } from './transport.js';
|
|
19
20
|
// =============================================================================
|
|
20
21
|
// CONSTANTS
|
|
@@ -24,125 +25,99 @@ const DEFAULT_INDEX_URL = 'https://cdn.jsdelivr.net/pyodide/v0.28.0/full/';
|
|
|
24
25
|
/**
|
|
25
26
|
* Bootstrap Python code that sets up the dispatch function.
|
|
26
27
|
*
|
|
27
|
-
* This
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* This is injected into Pyodide once at init. It does two things:
|
|
29
|
+
*
|
|
30
|
+
* 1. Loads the SHARED bridge core (the exact same code runtime/python_bridge.py
|
|
31
|
+
* imports) by exec'ing the build-time-embedded source into a fresh module and
|
|
32
|
+
* registering it in sys.modules as 'tywrap_bridge_core'. Pyodide has no
|
|
33
|
+
* filesystem to import from, so the source is shipped as a string constant
|
|
34
|
+
* (PYODIDE_BRIDGE_CORE_SOURCE) kept in sync with the .py by a drift-guard test.
|
|
35
|
+
*
|
|
36
|
+
* 2. Defines the single dispatch entry point __tywrap_dispatch(message_json) the
|
|
37
|
+
* JS transport calls. It routes through core.dispatch_request and encodes the
|
|
38
|
+
* response through core.encode_value, mirroring the reference server's error
|
|
39
|
+
* ladder so the on-the-wire envelopes are byte-identical.
|
|
40
|
+
*
|
|
41
|
+
* CONTRACT (Pyodide side): markers are forced to JSON (force_json_markers=True)
|
|
42
|
+
* because pyarrow is not available in WASM, NaN/Infinity are rejected
|
|
43
|
+
* (allow_nan=False), the bridge identifies itself as 'pyodide' with pid=None, and
|
|
44
|
+
* arrowAvailable is reported False. These choices match the JS-side decoder and
|
|
45
|
+
* the relaxed BridgeInfo validator (bridge in {python-subprocess, pyodide, http},
|
|
46
|
+
* pid number|null).
|
|
47
|
+
*
|
|
48
|
+
* The PYODIDE_CORE_MODULE_NAME must match the import name used inside the core
|
|
49
|
+
* module's own docstring/contract and the conformance harness.
|
|
31
50
|
*/
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
51
|
+
const PYODIDE_CORE_MODULE_NAME = 'tywrap_bridge_core';
|
|
52
|
+
// Exported so the cross-backend conformance suite can run the EXACT bootstrap
|
|
53
|
+
// source (this string, with the generated core constant inlined and the real
|
|
54
|
+
// __tywrap_dispatch error ladder) under CPython — proving the glue, not just the
|
|
55
|
+
// shared core module. It is not part of the public package surface.
|
|
56
|
+
export const BOOTSTRAP_PYTHON = `
|
|
57
|
+
import sys as __tywrap_sys
|
|
58
|
+
import json as __tywrap_json
|
|
59
|
+
import types as __tywrap_types
|
|
38
60
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
61
|
+
# Load the shared bridge core from the embedded source into a real module so the
|
|
62
|
+
# Pyodide server runs the IDENTICAL protocol/serialization code as the reference
|
|
63
|
+
# subprocess server. Registering in sys.modules lets the core's own internal
|
|
64
|
+
# 'import sys' (used lazily in dispatch_request for meta) resolve normally.
|
|
65
|
+
__tywrap_core_source = ${JSON.stringify(PYODIDE_BRIDGE_CORE_SOURCE)}
|
|
66
|
+
__tywrap_core = __tywrap_types.ModuleType(${JSON.stringify(PYODIDE_CORE_MODULE_NAME)})
|
|
67
|
+
__tywrap_sys.modules[${JSON.stringify(PYODIDE_CORE_MODULE_NAME)}] = __tywrap_core
|
|
68
|
+
exec(compile(__tywrap_core_source, '<tywrap_bridge_core>', 'exec'), __tywrap_core.__dict__)
|
|
44
69
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return []
|
|
48
|
-
if not isinstance(value, list):
|
|
49
|
-
raise ValueError(f'Invalid {key}')
|
|
50
|
-
return value
|
|
70
|
+
__tywrap_instances = {}
|
|
71
|
+
__tywrap_protocol = __tywrap_core.PROTOCOL
|
|
51
72
|
|
|
52
|
-
def __tywrap_coerce_dict(value, key):
|
|
53
|
-
if value is None:
|
|
54
|
-
return {}
|
|
55
|
-
if not isinstance(value, dict):
|
|
56
|
-
raise ValueError(f'Invalid {key}')
|
|
57
|
-
return value
|
|
58
73
|
|
|
59
74
|
def __tywrap_dispatch(message_json):
|
|
60
75
|
"""
|
|
61
|
-
Dispatch a protocol message and return a JSON response.
|
|
62
|
-
|
|
63
|
-
Args:
|
|
64
|
-
message_json: JSON-encoded ProtocolMessage string
|
|
76
|
+
Dispatch a protocol message and return a JSON response string.
|
|
65
77
|
|
|
66
|
-
|
|
67
|
-
|
|
78
|
+
Mirrors runtime/python_bridge.py main()'s error ladder: ProtocolError ->
|
|
79
|
+
error envelope WITHOUT traceback; any other handler error -> error envelope
|
|
80
|
+
WITH traceback. The final encode goes through core.encode_value(allow_nan=False)
|
|
81
|
+
so NaN/Infinity is rejected with the same wording the subprocess server uses.
|
|
68
82
|
"""
|
|
69
|
-
|
|
70
|
-
|
|
83
|
+
core = __tywrap_core
|
|
84
|
+
mid = None
|
|
71
85
|
try:
|
|
72
|
-
msg =
|
|
73
|
-
if
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
args = __tywrap_coerce_list(params.get('args'), 'args')
|
|
94
|
-
kwargs = __tywrap_coerce_dict(params.get('kwargs'), 'kwargs')
|
|
95
|
-
mod = importlib.import_module(module_name)
|
|
96
|
-
fn = getattr(mod, function_name)
|
|
97
|
-
result = fn(*args, **kwargs)
|
|
98
|
-
|
|
99
|
-
elif method == 'instantiate':
|
|
100
|
-
module_name = __tywrap_require_str(params, 'module')
|
|
101
|
-
class_name = __tywrap_require_str(params, 'className')
|
|
102
|
-
args = __tywrap_coerce_list(params.get('args'), 'args')
|
|
103
|
-
kwargs = __tywrap_coerce_dict(params.get('kwargs'), 'kwargs')
|
|
104
|
-
mod = importlib.import_module(module_name)
|
|
105
|
-
cls = getattr(mod, class_name)
|
|
106
|
-
obj = cls(*args, **kwargs)
|
|
107
|
-
handle = str(id(obj))
|
|
108
|
-
__tywrap_instances[handle] = obj
|
|
109
|
-
result = handle
|
|
110
|
-
|
|
111
|
-
elif method == 'call_method':
|
|
112
|
-
handle = __tywrap_require_str(params, 'handle')
|
|
113
|
-
method_name = __tywrap_require_str(params, 'methodName')
|
|
114
|
-
args = __tywrap_coerce_list(params.get('args'), 'args')
|
|
115
|
-
kwargs = __tywrap_coerce_dict(params.get('kwargs'), 'kwargs')
|
|
116
|
-
if handle not in __tywrap_instances:
|
|
117
|
-
raise ValueError(f'Unknown instance handle: {handle}')
|
|
118
|
-
obj = __tywrap_instances[handle]
|
|
119
|
-
bound_method = getattr(obj, method_name)
|
|
120
|
-
result = bound_method(*args, **kwargs)
|
|
121
|
-
|
|
122
|
-
elif method == 'dispose_instance':
|
|
123
|
-
handle = __tywrap_require_str(params, 'handle')
|
|
124
|
-
result = __tywrap_instances.pop(handle, None) is not None
|
|
125
|
-
|
|
126
|
-
else:
|
|
127
|
-
raise ValueError(f'Unknown method: {method}')
|
|
128
|
-
|
|
129
|
-
return json.dumps({
|
|
130
|
-
'id': msg_id,
|
|
131
|
-
'protocol': __tywrap_protocol,
|
|
132
|
-
'result': result
|
|
133
|
-
})
|
|
86
|
+
msg = __tywrap_json.loads(message_json)
|
|
87
|
+
if isinstance(msg, dict) and isinstance(msg.get('id'), int):
|
|
88
|
+
mid = msg.get('id')
|
|
89
|
+
try:
|
|
90
|
+
out = core.dispatch_request(
|
|
91
|
+
msg,
|
|
92
|
+
__tywrap_instances,
|
|
93
|
+
bridge='pyodide',
|
|
94
|
+
pid=None,
|
|
95
|
+
force_json_markers=True,
|
|
96
|
+
allow_nan=False,
|
|
97
|
+
arrow_available_override=False,
|
|
98
|
+
)
|
|
99
|
+
except core.ProtocolError as e:
|
|
100
|
+
out = core.build_error_payload(mid, e, include_traceback=False)
|
|
101
|
+
except Exception as e:
|
|
102
|
+
out = core.build_error_payload(mid, e, include_traceback=True)
|
|
103
|
+
except Exception as e:
|
|
104
|
+
# Malformed JSON / unexpected pre-dispatch failure: well-formed error,
|
|
105
|
+
# no traceback (matches the reference's outer handler).
|
|
106
|
+
out = core.build_error_payload(mid, e, include_traceback=False)
|
|
134
107
|
|
|
108
|
+
try:
|
|
109
|
+
return core.encode_value(out, allow_nan=False)
|
|
110
|
+
except core.CodecError as e:
|
|
111
|
+
# The subprocess server's encode_response() converts CodecError -> ValueError
|
|
112
|
+
# so the NaN/Infinity rejection surfaces with type 'ValueError'. Match that
|
|
113
|
+
# so the error envelope is byte-identical across backends.
|
|
114
|
+
err_out = core.build_error_payload(mid, ValueError(str(e)), include_traceback=False)
|
|
115
|
+
return __tywrap_json.dumps(err_out)
|
|
135
116
|
except Exception as e:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
'error': {
|
|
141
|
-
'type': type(e).__name__,
|
|
142
|
-
'message': str(e),
|
|
143
|
-
'traceback': traceback.format_exc()
|
|
144
|
-
}
|
|
145
|
-
})
|
|
117
|
+
# Any other encoding failure: well-formed error envelope, no traceback,
|
|
118
|
+
# exactly as the subprocess server's fallback does.
|
|
119
|
+
err_out = core.build_error_payload(mid, e, include_traceback=False)
|
|
120
|
+
return __tywrap_json.dumps(err_out)
|
|
146
121
|
`;
|
|
147
122
|
// =============================================================================
|
|
148
123
|
// PYODIDE IO TRANSPORT
|
|
@@ -150,8 +125,10 @@ def __tywrap_dispatch(message_json):
|
|
|
150
125
|
/**
|
|
151
126
|
* Transport implementation for in-memory Pyodide communication.
|
|
152
127
|
*
|
|
153
|
-
* This transport extends
|
|
154
|
-
* implements the Transport interface for message-based communication.
|
|
128
|
+
* This transport extends DisposableBase for lifecycle management and
|
|
129
|
+
* implements the Transport interface for message-based communication. It is a
|
|
130
|
+
* pure transport: it moves bytes via send() and carries no RPC methods (those
|
|
131
|
+
* live on PythonRuntime, implemented by PyodideBridge through an RpcClient).
|
|
155
132
|
*
|
|
156
133
|
* @example
|
|
157
134
|
* ```typescript
|
|
@@ -171,10 +148,9 @@ def __tywrap_dispatch(message_json):
|
|
|
171
148
|
* await transport.dispose();
|
|
172
149
|
* ```
|
|
173
150
|
*/
|
|
174
|
-
export class PyodideIO extends
|
|
151
|
+
export class PyodideIO extends DisposableBase {
|
|
175
152
|
indexURL;
|
|
176
153
|
packages;
|
|
177
|
-
requestId = 0;
|
|
178
154
|
py;
|
|
179
155
|
/**
|
|
180
156
|
* Create a new PyodideIO transport.
|
|
@@ -187,7 +163,7 @@ export class PyodideIO extends BoundedContext {
|
|
|
187
163
|
this.packages = Object.freeze([...(options.packages ?? [])]);
|
|
188
164
|
}
|
|
189
165
|
// ===========================================================================
|
|
190
|
-
// LIFECYCLE
|
|
166
|
+
// LIFECYCLE
|
|
191
167
|
// ===========================================================================
|
|
192
168
|
/**
|
|
193
169
|
* Initialize the Pyodide runtime.
|
|
@@ -303,86 +279,6 @@ export class PyodideIO extends BoundedContext {
|
|
|
303
279
|
}, { timeoutMs, signal });
|
|
304
280
|
}
|
|
305
281
|
// ===========================================================================
|
|
306
|
-
// RUNTIME EXECUTION (BoundedContext abstract methods)
|
|
307
|
-
// ===========================================================================
|
|
308
|
-
/**
|
|
309
|
-
* Call a Python function.
|
|
310
|
-
*
|
|
311
|
-
* Convenience method that constructs a 'call' message and sends it.
|
|
312
|
-
*/
|
|
313
|
-
async call(module, functionName, args, kwargs) {
|
|
314
|
-
const message = {
|
|
315
|
-
id: this.generateId(),
|
|
316
|
-
protocol: PROTOCOL_ID,
|
|
317
|
-
method: 'call',
|
|
318
|
-
params: {
|
|
319
|
-
module,
|
|
320
|
-
functionName,
|
|
321
|
-
args: args ?? [],
|
|
322
|
-
kwargs,
|
|
323
|
-
},
|
|
324
|
-
};
|
|
325
|
-
const responseJson = await this.send(JSON.stringify(message), 30000);
|
|
326
|
-
return this.parseResponse(responseJson);
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* Instantiate a Python class.
|
|
330
|
-
*
|
|
331
|
-
* Convenience method that constructs an 'instantiate' message and sends it.
|
|
332
|
-
*/
|
|
333
|
-
async instantiate(module, className, args, kwargs) {
|
|
334
|
-
const message = {
|
|
335
|
-
id: this.generateId(),
|
|
336
|
-
protocol: PROTOCOL_ID,
|
|
337
|
-
method: 'instantiate',
|
|
338
|
-
params: {
|
|
339
|
-
module,
|
|
340
|
-
className,
|
|
341
|
-
args: args ?? [],
|
|
342
|
-
kwargs,
|
|
343
|
-
},
|
|
344
|
-
};
|
|
345
|
-
const responseJson = await this.send(JSON.stringify(message), 30000);
|
|
346
|
-
return this.parseResponse(responseJson);
|
|
347
|
-
}
|
|
348
|
-
/**
|
|
349
|
-
* Call a method on a Python instance.
|
|
350
|
-
*
|
|
351
|
-
* Convenience method that constructs a 'call_method' message and sends it.
|
|
352
|
-
*/
|
|
353
|
-
async callMethod(handle, methodName, args, kwargs) {
|
|
354
|
-
const message = {
|
|
355
|
-
id: this.generateId(),
|
|
356
|
-
protocol: PROTOCOL_ID,
|
|
357
|
-
method: 'call_method',
|
|
358
|
-
params: {
|
|
359
|
-
handle,
|
|
360
|
-
methodName,
|
|
361
|
-
args: args ?? [],
|
|
362
|
-
kwargs,
|
|
363
|
-
},
|
|
364
|
-
};
|
|
365
|
-
const responseJson = await this.send(JSON.stringify(message), 30000);
|
|
366
|
-
return this.parseResponse(responseJson);
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Dispose a Python instance.
|
|
370
|
-
*
|
|
371
|
-
* Convenience method that constructs a 'dispose_instance' message and sends it.
|
|
372
|
-
*/
|
|
373
|
-
async disposeInstance(handle) {
|
|
374
|
-
const message = {
|
|
375
|
-
id: this.generateId(),
|
|
376
|
-
protocol: PROTOCOL_ID,
|
|
377
|
-
method: 'dispose_instance',
|
|
378
|
-
params: {
|
|
379
|
-
handle,
|
|
380
|
-
},
|
|
381
|
-
};
|
|
382
|
-
const responseJson = await this.send(JSON.stringify(message), 30000);
|
|
383
|
-
this.parseResponse(responseJson);
|
|
384
|
-
}
|
|
385
|
-
// ===========================================================================
|
|
386
282
|
// PRIVATE HELPERS
|
|
387
283
|
// ===========================================================================
|
|
388
284
|
/**
|
|
@@ -419,26 +315,6 @@ export class PyodideIO extends BoundedContext {
|
|
|
419
315
|
}
|
|
420
316
|
await this.py.runPythonAsync(BOOTSTRAP_PYTHON);
|
|
421
317
|
}
|
|
422
|
-
/**
|
|
423
|
-
* Parse a JSON response and extract the result or throw an error.
|
|
424
|
-
*/
|
|
425
|
-
parseResponse(responseJson) {
|
|
426
|
-
const response = JSON.parse(responseJson);
|
|
427
|
-
if (response.error) {
|
|
428
|
-
const err = new BridgeExecutionError(`${response.error.type}: ${response.error.message}`, {
|
|
429
|
-
code: response.error.type,
|
|
430
|
-
});
|
|
431
|
-
err.traceback = response.error.traceback;
|
|
432
|
-
throw err;
|
|
433
|
-
}
|
|
434
|
-
return response.result;
|
|
435
|
-
}
|
|
436
|
-
/**
|
|
437
|
-
* Generate a unique message ID.
|
|
438
|
-
*/
|
|
439
|
-
generateId() {
|
|
440
|
-
return ++this.requestId;
|
|
441
|
-
}
|
|
442
318
|
/**
|
|
443
319
|
* Safely destroy a Pyodide proxy object.
|
|
444
320
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pyodide-io.js","sourceRoot":"","sources":["../../src/runtime/pyodide-io.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"pyodide-io.js","sourceRoot":"","sources":["../../src/runtime/pyodide-io.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pyodide runtime bridge
|
|
2
|
+
* Pyodide runtime bridge.
|
|
3
3
|
*
|
|
4
|
-
* PyodideBridge
|
|
5
|
-
*
|
|
4
|
+
* PyodideBridge is a thin facade: it extends DisposableBase (lifecycle) and
|
|
5
|
+
* implements PythonRuntime by HOLDING an RpcClient over a PyodideIO transport
|
|
6
|
+
* for in-memory Python execution in browser environments via WebAssembly.
|
|
6
7
|
*
|
|
7
8
|
* @see https://github.com/bbopen/tywrap/issues/149
|
|
8
9
|
*/
|
|
9
|
-
import {
|
|
10
|
+
import type { PythonRuntime, BridgeInfo } from '../types/index.js';
|
|
11
|
+
import { DisposableBase } from './bounded-context.js';
|
|
12
|
+
import { type GetBridgeInfoOptions } from './rpc-client.js';
|
|
10
13
|
import type { CodecOptions } from './safe-codec.js';
|
|
11
14
|
/**
|
|
12
15
|
* Configuration options for PyodideBridge.
|
|
@@ -48,12 +51,29 @@ export interface PyodideBridgeOptions {
|
|
|
48
51
|
* await bridge.dispose();
|
|
49
52
|
* ```
|
|
50
53
|
*/
|
|
51
|
-
export declare class PyodideBridge extends
|
|
54
|
+
export declare class PyodideBridge extends DisposableBase implements PythonRuntime {
|
|
55
|
+
private readonly rpc;
|
|
52
56
|
/**
|
|
53
57
|
* Create a new PyodideBridge instance.
|
|
54
58
|
*
|
|
55
59
|
* @param options - Configuration options for the bridge
|
|
56
60
|
*/
|
|
57
61
|
constructor(options?: PyodideBridgeOptions);
|
|
62
|
+
protected doInit(): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* No facade-specific teardown: the RpcClient (and its transport) is tracked
|
|
65
|
+
* as a resource and disposed automatically by DisposableBase.
|
|
66
|
+
*/
|
|
67
|
+
protected doDispose(): Promise<void>;
|
|
68
|
+
call<T = unknown>(module: string, functionName: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
|
|
69
|
+
instantiate<T = unknown>(module: string, className: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
|
|
70
|
+
callMethod<T = unknown>(handle: string, methodName: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
|
|
71
|
+
disposeInstance(handle: string): Promise<void>;
|
|
72
|
+
getBridgeInfo(options?: GetBridgeInfoOptions): Promise<BridgeInfo>;
|
|
73
|
+
/**
|
|
74
|
+
* Ensure the facade is initialized before delegating an RPC, replicating the
|
|
75
|
+
* auto-init that the bounded execute path provided pre-composition.
|
|
76
|
+
*/
|
|
77
|
+
private ensureReady;
|
|
58
78
|
}
|
|
59
79
|
//# sourceMappingURL=pyodide.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pyodide.d.ts","sourceRoot":"","sources":["../../src/runtime/pyodide.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pyodide.d.ts","sourceRoot":"","sources":["../../src/runtime/pyodide.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAa,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAMpD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,iDAAiD;IACjD,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,aAAc,SAAQ,cAAe,YAAW,aAAa;IACxE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAEhC;;;;OAIG;gBACS,OAAO,GAAE,oBAAyB;cAqB9B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAKvC;;;OAGG;cACa,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAQpC,IAAI,CAAC,CAAC,GAAG,OAAO,EACpB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,OAAO,EAAE,EACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAKP,WAAW,CAAC,CAAC,GAAG,OAAO,EAC3B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,OAAO,EAAE,EACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAKP,UAAU,CAAC,CAAC,GAAG,OAAO,EAC1B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,OAAO,EAAE,EACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAKP,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9C,aAAa,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,UAAU,CAAC;IAKxE;;;OAGG;YACW,WAAW;CAK1B"}
|
package/dist/runtime/pyodide.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pyodide runtime bridge
|
|
2
|
+
* Pyodide runtime bridge.
|
|
3
3
|
*
|
|
4
|
-
* PyodideBridge
|
|
5
|
-
*
|
|
4
|
+
* PyodideBridge is a thin facade: it extends DisposableBase (lifecycle) and
|
|
5
|
+
* implements PythonRuntime by HOLDING an RpcClient over a PyodideIO transport
|
|
6
|
+
* for in-memory Python execution in browser environments via WebAssembly.
|
|
6
7
|
*
|
|
7
8
|
* @see https://github.com/bbopen/tywrap/issues/149
|
|
8
9
|
*/
|
|
9
|
-
import {
|
|
10
|
+
import { DisposableBase } from './bounded-context.js';
|
|
11
|
+
import { RpcClient } from './rpc-client.js';
|
|
10
12
|
import { PyodideIO } from './pyodide-io.js';
|
|
11
13
|
// =============================================================================
|
|
12
14
|
// PYODIDE BRIDGE
|
|
@@ -38,25 +40,72 @@ import { PyodideIO } from './pyodide-io.js';
|
|
|
38
40
|
* await bridge.dispose();
|
|
39
41
|
* ```
|
|
40
42
|
*/
|
|
41
|
-
export class PyodideBridge extends
|
|
43
|
+
export class PyodideBridge extends DisposableBase {
|
|
44
|
+
rpc;
|
|
42
45
|
/**
|
|
43
46
|
* Create a new PyodideBridge instance.
|
|
44
47
|
*
|
|
45
48
|
* @param options - Configuration options for the bridge
|
|
46
49
|
*/
|
|
47
50
|
constructor(options = {}) {
|
|
48
|
-
|
|
51
|
+
super();
|
|
49
52
|
const transport = new PyodideIO({
|
|
50
53
|
indexURL: options.indexURL,
|
|
51
54
|
packages: options.packages,
|
|
52
55
|
});
|
|
53
|
-
|
|
54
|
-
const protocolOptions = {
|
|
56
|
+
this.rpc = new RpcClient({
|
|
55
57
|
transport,
|
|
56
58
|
codec: options.codec,
|
|
57
59
|
defaultTimeoutMs: options.timeoutMs,
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
+
});
|
|
61
|
+
// One disposal chain: facade -> rpc -> transport.
|
|
62
|
+
this.trackResource(this.rpc);
|
|
63
|
+
}
|
|
64
|
+
// ===========================================================================
|
|
65
|
+
// LIFECYCLE
|
|
66
|
+
// ===========================================================================
|
|
67
|
+
async doInit() {
|
|
68
|
+
// No facade-specific pre-init; the held RpcClient drives transport.init().
|
|
69
|
+
await this.rpc.init();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* No facade-specific teardown: the RpcClient (and its transport) is tracked
|
|
73
|
+
* as a resource and disposed automatically by DisposableBase.
|
|
74
|
+
*/
|
|
75
|
+
async doDispose() {
|
|
76
|
+
// Intentionally empty; tracked resources handle disposal.
|
|
77
|
+
}
|
|
78
|
+
// ===========================================================================
|
|
79
|
+
// RPC METHODS (delegate to the held RpcClient; never PyodideIO directly)
|
|
80
|
+
// ===========================================================================
|
|
81
|
+
async call(module, functionName, args, kwargs) {
|
|
82
|
+
await this.ensureReady();
|
|
83
|
+
return this.rpc.call(module, functionName, args, kwargs);
|
|
84
|
+
}
|
|
85
|
+
async instantiate(module, className, args, kwargs) {
|
|
86
|
+
await this.ensureReady();
|
|
87
|
+
return this.rpc.instantiate(module, className, args, kwargs);
|
|
88
|
+
}
|
|
89
|
+
async callMethod(handle, methodName, args, kwargs) {
|
|
90
|
+
await this.ensureReady();
|
|
91
|
+
return this.rpc.callMethod(handle, methodName, args, kwargs);
|
|
92
|
+
}
|
|
93
|
+
async disposeInstance(handle) {
|
|
94
|
+
await this.ensureReady();
|
|
95
|
+
return this.rpc.disposeInstance(handle);
|
|
96
|
+
}
|
|
97
|
+
async getBridgeInfo(options) {
|
|
98
|
+
await this.ensureReady();
|
|
99
|
+
return this.rpc.getBridgeInfo(options);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Ensure the facade is initialized before delegating an RPC, replicating the
|
|
103
|
+
* auto-init that the bounded execute path provided pre-composition.
|
|
104
|
+
*/
|
|
105
|
+
async ensureReady() {
|
|
106
|
+
if (!this.isReady) {
|
|
107
|
+
await this.init();
|
|
108
|
+
}
|
|
60
109
|
}
|
|
61
110
|
}
|
|
62
111
|
//# sourceMappingURL=pyodide.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pyodide.js","sourceRoot":"","sources":["../../src/runtime/pyodide.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pyodide.js","sourceRoot":"","sources":["../../src/runtime/pyodide.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAA6B,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAwB5C,gFAAgF;AAChF,iBAAiB;AACjB,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,OAAO,aAAc,SAAQ,cAAc;IAC9B,GAAG,CAAY;IAEhC;;;;OAIG;IACH,YAAY,UAAgC,EAAE;QAC5C,KAAK,EAAE,CAAC;QAER,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC;YAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,GAAG,IAAI,SAAS,CAAC;YACvB,SAAS;YACT,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,gBAAgB,EAAE,OAAO,CAAC,SAAS;SACpC,CAAC,CAAC;QACH,kDAAkD;QAClD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,8EAA8E;IAC9E,YAAY;IACZ,8EAA8E;IAEpE,KAAK,CAAC,MAAM;QACpB,2EAA2E;QAC3E,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC;IAED;;;OAGG;IACO,KAAK,CAAC,SAAS;QACvB,0DAA0D;IAC5D,CAAC;IAED,8EAA8E;IAC9E,yEAAyE;IACzE,8EAA8E;IAE9E,KAAK,CAAC,IAAI,CACR,MAAc,EACd,YAAoB,EACpB,IAAe,EACf,MAAgC;QAEhC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAI,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,WAAW,CACf,MAAc,EACd,SAAiB,EACjB,IAAe,EACf,MAAgC;QAEhC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAI,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,UAAU,CACd,MAAc,EACd,UAAkB,EAClB,IAAe,EACf,MAAgC;QAEhC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAI,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,MAAc;QAClC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAA8B;QAChD,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,WAAW;QACvB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;CACF"}
|