@poe-platform/safe-bash 0.1.683 → 0.1.684

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 (41) hide show
  1. package/README.md +10 -0
  2. package/dist/safe-bash/chunks/chunk-4MPK7VIM.js +519 -0
  3. package/dist/safe-bash/chunks/chunk-4MPK7VIM.js.map +7 -0
  4. package/dist/safe-bash/chunks/{chunk-6R7IR2MV.js → chunk-BONY6MX5.js} +731 -15
  5. package/dist/safe-bash/chunks/chunk-BONY6MX5.js.map +7 -0
  6. package/dist/safe-bash/commands/python/index.browser.js +12 -2
  7. package/dist/safe-bash/commands/python/index.d.ts +5 -0
  8. package/dist/safe-bash/commands/python/index.d.ts.map +1 -1
  9. package/dist/safe-bash/commands/python/index.js +15 -3
  10. package/dist/safe-bash/commands/python/index.js.map +1 -1
  11. package/dist/safe-bash/commands/python/jspi-assets.d.ts +14 -0
  12. package/dist/safe-bash/commands/python/jspi-assets.d.ts.map +1 -0
  13. package/dist/safe-bash/commands/python/jspi-assets.js +51 -0
  14. package/dist/safe-bash/commands/python/jspi-assets.js.map +1 -0
  15. package/dist/safe-bash/commands/python/jspi-scheduler.d.ts +8 -0
  16. package/dist/safe-bash/commands/python/jspi-scheduler.d.ts.map +1 -0
  17. package/dist/safe-bash/commands/python/jspi-scheduler.js +49 -0
  18. package/dist/safe-bash/commands/python/jspi-scheduler.js.map +1 -0
  19. package/dist/safe-bash/commands/python/jspi-trampoline.d.ts +5 -0
  20. package/dist/safe-bash/commands/python/jspi-trampoline.d.ts.map +1 -0
  21. package/dist/safe-bash/commands/python/jspi-trampoline.js +90 -0
  22. package/dist/safe-bash/commands/python/jspi-trampoline.js.map +1 -0
  23. package/dist/safe-bash/commands/python/jspi.d.ts +22 -0
  24. package/dist/safe-bash/commands/python/jspi.d.ts.map +1 -0
  25. package/dist/safe-bash/commands/python/jspi.js +295 -0
  26. package/dist/safe-bash/commands/python/jspi.js.map +1 -0
  27. package/dist/safe-bash/commands/python/runtime-scripts.d.ts +6 -0
  28. package/dist/safe-bash/commands/python/runtime-scripts.d.ts.map +1 -0
  29. package/dist/safe-bash/commands/python/runtime-scripts.js +168 -0
  30. package/dist/safe-bash/commands/python/runtime-scripts.js.map +1 -0
  31. package/dist/safe-bash/commands/python/worker.browser.js +13 -368
  32. package/dist/safe-bash/commands/python/worker.browser.js.map +3 -3
  33. package/dist/safe-bash/commands/python/worker.d.ts.map +1 -1
  34. package/dist/safe-bash/commands/python/worker.js +6 -168
  35. package/dist/safe-bash/commands/python/worker.js.map +1 -1
  36. package/dist/safe-bash/core.browser.js +12 -2
  37. package/dist/safe-bash/core.browser.js.map +1 -1
  38. package/package.json +2 -2
  39. package/dist/safe-bash/chunks/chunk-3G3EZZ63.js +0 -145
  40. package/dist/safe-bash/chunks/chunk-3G3EZZ63.js.map +0 -7
  41. package/dist/safe-bash/chunks/chunk-6R7IR2MV.js.map +0 -7
package/README.md CHANGED
@@ -85,9 +85,19 @@ These plugins are separate from `agentCommands()`; pass them to `shell.use(...)`
85
85
  | --- | --- |
86
86
  | `curl` | `networkCommands({ authorize, transport?, limits?, replace? })`: required authorization on every request, redirect, and retry. Node uses the native HTTP transport; Workers can inject `createFetchTransport()`. `createOriginAuthorizer([...])` provides exact origin/hostname policy; its omitted allowlist is deliberately `*` (allow all). [Options and limits](src/commands/network/types.ts). |
87
87
  | `node` | `nodeCommands({ runtime, limits?, replace? })`: runs JavaScript with an injected SafeJS runtime, virtual files, and shell streams. [Usage and supported subset](src/commands/node/README.md). |
88
+ | `python`, `python3` | `pythonCommands({ createExecutor })` from `@poe-platform/safe-bash/commands/python`: supply an explicit executor for invocation-local Python, filesystem I/O and shell streams. [Executor and ownership contract](src/contracts/python-executor.md). |
88
89
  | `llm` | `llmCommands({ providers, defaultModel?, replace? })`: opt-in model routing, sandbox attachments and streamed text/binary output. Includes injected-transport OpenAI and ElevenLabs reference providers. [Configuration and provider contract](src/commands/llm/README.md). |
89
90
  | `playwright-cli` | Standard browser commands, storage state, native snapshots, recordings, and traces through a host-owned adapter. [Sessions and host capabilities](src/contracts/playwright-sessions.md). `installPlaywrightNetworkPolicy` from `/playwright` supports browser-native redirects with per-hop bounded host HTTP fetch and independent direct HTTP/WebSocket denial. Cloudflare guardrails do not establish WebRTC/UDP denial or all-protocol accounting; hosts requiring those guarantees must refuse this integration. [Network policy and lifecycle](src/contracts/playwright-network-policy.md). |
90
91
 
92
+ For a custom same-isolate Python JSPI host, use `createPythonJspiExecutor` from
93
+ the same Python entry with an explicit loader, precompiled Wasm modules and
94
+ pinned, authenticated runtime assets; follow the [static host recipe](src/contracts/python-jspi.md).
95
+ Native I/O uses the caller's asynchronous filesystem without workspace copying,
96
+ Node worker threads or a SAB request/reply bridge. This path is qualified with
97
+ installed public-package artifacts in local workerd, not a verified Cloudflare
98
+ deployment or a managed Python native-filesystem integration. JSPI cancellation
99
+ is cooperative; it neither preempts CPU-only loops nor establishes confinement.
100
+
91
101
  Storage can be in memory, a rooted host directory, S3-compatible storage, or WebDAV,
92
102
  with read-only wrappers, mounts, and overlays. Choose and configure it explicitly;
93
103
  see the [filesystem guide](../safe-fs/README.md).
@@ -0,0 +1,519 @@
1
+ import {
2
+ init_platform
3
+ } from "./chunk-O4SKIJ5J.js";
4
+
5
+ // packages/safe-bash/src/commands/python/invocation.ts
6
+ init_platform();
7
+ var PythonInvocationError = class extends Error {
8
+ constructor(message) {
9
+ super(message);
10
+ this.name = "PythonInvocationError";
11
+ }
12
+ };
13
+ function parsePythonInvocation(args, env) {
14
+ const startupArgs = [];
15
+ let informational = false;
16
+ scan: for (let index = 0; index < args.length; index++) {
17
+ const option = args[index];
18
+ if (option === "--" || option === "-" || !option.startsWith("-")) break;
19
+ if (option === "--help") {
20
+ informational = true;
21
+ break;
22
+ }
23
+ if (option === "--version") {
24
+ informational = true;
25
+ continue;
26
+ }
27
+ if (option.startsWith("--")) throw new PythonInvocationError("unsupported option " + option);
28
+ for (let offset = 1; offset < option.length; offset++) {
29
+ const flag = option[offset];
30
+ if (flag === "h" || flag === "?") {
31
+ informational = true;
32
+ break scan;
33
+ }
34
+ if (flag === "V") {
35
+ informational = true;
36
+ continue;
37
+ }
38
+ if ("cmWX".includes(flag)) {
39
+ const operand = option.slice(offset + 1) || args[++index];
40
+ if (operand === void 0) throw new PythonInvocationError("argument expected for -" + flag);
41
+ if (flag === "c" || flag === "m") break scan;
42
+ if (flag === "X") {
43
+ const separator = operand.indexOf("=");
44
+ const name = separator < 0 ? operand : operand.slice(0, separator);
45
+ const value = separator < 0 ? void 0 : operand.slice(separator + 1);
46
+ let decimal = value ?? "";
47
+ while (decimal.length && " \n\r\v\f".includes(decimal[0])) decimal = decimal.slice(1);
48
+ if (decimal[0] === "+" || decimal[0] === "-") decimal = decimal.slice(1);
49
+ const digits = decimal.length > 0 && [...decimal].every((character) => character >= "0" && character <= "9");
50
+ const supported = name === "utf8" && (value === void 0 || value === "0" || value === "1") || (name === "dev" || name === "warn_default_encoding") && value === void 0 || name === "int_max_str_digits" && digits && Number.isSafeInteger(Number(value)) && Number(value) <= 2147483647 && (Number(value) === 0 || Number(value) >= 640);
51
+ if (!supported) throw new PythonInvocationError("unsupported -X option " + operand);
52
+ startupArgs.push("-X", operand);
53
+ }
54
+ break;
55
+ }
56
+ if (!"BEPOusISbdvqR".includes(flag)) throw new PythonInvocationError("unsupported option -" + flag);
57
+ startupArgs.push("-" + flag);
58
+ }
59
+ }
60
+ if (!informational && !startupArgs.includes("-E") && !startupArgs.includes("-I")) {
61
+ if (env.PYTHONINSPECT) throw new PythonInvocationError("PYTHONINSPECT requires an interactive terminal, which the shell does not expose");
62
+ if (env.PYTHONHOME) throw new PythonInvocationError("PYTHONHOME cannot replace the configured Pyodide runtime");
63
+ }
64
+ const runtimeEnv = { ...env };
65
+ delete runtimeEnv.PYTHONPATH;
66
+ delete runtimeEnv.PYTHONHOME;
67
+ delete runtimeEnv.PYTHONWARNINGS;
68
+ runtimeEnv.PYTHONINSPECT = "";
69
+ startupArgs.push("-c", "");
70
+ return { startupArgs, env: runtimeEnv };
71
+ }
72
+
73
+ // packages/safe-bash/src/commands/python/diagnostics.ts
74
+ init_platform();
75
+ var messages = {
76
+ "executor-unavailable": "Python executor is unavailable; configure exactly one supported executor or interpreter worker.",
77
+ "transport-unavailable": "Python worker transport or shared-memory operations are unavailable.",
78
+ "runtime-abi": "Python runtime version or native ABI is unsupported.",
79
+ "runtime-assets": "Python runtime or package assets could not be loaded.",
80
+ "isolation-unavailable": "Python host isolation or resource enforcement is unavailable.",
81
+ deadline: "Python execution exceeded its host deadline.",
82
+ "filesystem-open": "Python filesystem handle access is unavailable; the backend must support retained open.",
83
+ "filesystem-read": "Python filesystem reads are unavailable for this backend.",
84
+ "filesystem-write": "Python filesystem writes are unavailable for this backend.",
85
+ "filesystem-directory": "Python retained directory operations are unavailable for this backend.",
86
+ "filesystem-operation": "The requested Python filesystem operation is unavailable for this backend.",
87
+ capacity: "Python worker capacity exhausted.",
88
+ cleanup: "Python resource cleanup failed; retirement could not be confirmed.",
89
+ startup: "Python startup failed; consult the host diagnostic callback.",
90
+ runtime: "Python runtime failed; consult the host diagnostic callback."
91
+ };
92
+ var PythonFailure = class extends Error {
93
+ constructor(category, options) {
94
+ super(messages[category], options);
95
+ this.category = category;
96
+ this.name = "PythonFailure";
97
+ }
98
+ category;
99
+ };
100
+ function isPythonFailureCategory(value) {
101
+ return typeof value === "string" && Object.hasOwn(messages, value);
102
+ }
103
+ function reportPythonFailure(category, cause, observer) {
104
+ const failure = new PythonFailure(category);
105
+ try {
106
+ void Promise.resolve(observer?.({ failure, cause })).catch(() => {
107
+ });
108
+ } catch {
109
+ }
110
+ return failure;
111
+ }
112
+ function inspectPythonCapabilities(options = {}) {
113
+ const failures = /* @__PURE__ */ new Set();
114
+ if (typeof options.createWorker === "function" === (typeof options.createExecutor === "function") || options.createWorker !== void 0 && typeof options.createWorker !== "function" || options.createExecutor !== void 0 && typeof options.createExecutor !== "function") failures.add("executor-unavailable");
115
+ if (typeof options.createExecutor !== "function" && (typeof SharedArrayBuffer !== "function" || typeof Atomics !== "object" || typeof Atomics.store !== "function" || typeof Atomics.notify !== "function")) failures.add("transport-unavailable");
116
+ if (options.runtimeVersion !== void 0 && options.runtimeVersion !== "314.0.6") failures.add("runtime-abi");
117
+ for (const requirement of options.requiredFileSystem ?? []) {
118
+ if (!["open", "read", "write", "directory"].includes(requirement)) throw new TypeError("Unknown Python filesystem requirement");
119
+ const category = requirement === "open" ? "filesystem-open" : requirement === "read" ? "filesystem-read" : requirement === "write" ? "filesystem-write" : "filesystem-directory";
120
+ try {
121
+ const fs = options.fs;
122
+ if (requirement === "directory") {
123
+ failures.add(category);
124
+ } else if (!fs || typeof fs.open !== "function" || fs.capabilities.open === false) failures.add("filesystem-open");
125
+ else if (requirement === "write" && (fs.capabilities.readOnly === true || fs.capabilities.write === false)) failures.add(category);
126
+ else if (requirement === "read" && fs.capabilities.read === false) failures.add(category);
127
+ } catch {
128
+ failures.add(category);
129
+ }
130
+ }
131
+ return Object.freeze({
132
+ configurationValid: failures.size === 0,
133
+ failures: Object.freeze([...failures].map((category) => new PythonFailure(category)))
134
+ });
135
+ }
136
+
137
+ // packages/safe-bash/src/commands/python/execution.ts
138
+ init_platform();
139
+ var pythonExecution = `
140
+ import sys, os, json, runpy, traceback, types, warnings, textwrap, io, struct, linecache
141
+ _safe_invocation = json.loads(_safe_invocation_json)
142
+ os.environ.clear()
143
+ os.environ.update(_safe_invocation['env'])
144
+ _safe_args = list(_safe_invocation['args'])
145
+ sys.orig_argv = [_safe_invocation.get('command', 'python')] + _safe_args
146
+ _safe_exit = 0
147
+
148
+ class _SafeOptionError(ValueError):
149
+ pass
150
+
151
+ def _safe_system_exit(_error):
152
+ if isinstance(_error.code, int):
153
+ _status = int.__index__(_error.code)
154
+ _long_bound = 1 << (8 * struct.calcsize('@l') - 1)
155
+ status = (_status & 255) if -_long_bound <= _status < _long_bound else 255
156
+ else:
157
+ status = 0 if _error.code is None else 1
158
+ if _error.code is not None and not isinstance(_error.code, int):
159
+ print(_error.code, file=sys.stderr)
160
+ return status
161
+
162
+ def _safe_launch():
163
+ args = list(_safe_args)
164
+ unbuffered = False
165
+ ignore_env = bool(sys.flags.ignore_environment)
166
+ safe_path = bool(sys.flags.safe_path)
167
+ native_warning_options = list(sys.warnoptions)
168
+ # Pyodide adds a bootstrap cwd entry even when CPython safe-path mode is set.
169
+ # Each execution mode below supplies its own entry after explicit PYTHONPATH.
170
+ sys.path[:] = [entry for entry in sys.path if entry != '']
171
+ warning_options = []
172
+ version_count = 0
173
+ options_terminated = False
174
+ while args and args[0].startswith('-') and args[0] != '-':
175
+ option = args.pop(0)
176
+ if option == '--':
177
+ options_terminated = True
178
+ break
179
+ if option in ('--help', '-h', '-?'):
180
+ print('usage: python [-uBEPOsSIbdvqR] [-W filter] [-X option] [-c code | -m module | file | -] [args ...]')
181
+ print('Dedicated Pyodide interpreter; stdin is noninteractive.')
182
+ print('-u: unbuffered binary output; -B: disable bytecode writes; -E: ignore PYTHON* settings')
183
+ print('-P: omit automatic unsafe sys.path entry; -W: Python warning filter')
184
+ print('-O/-OO, -S/-s/-I, -b/-bb, -d/-v/-q/-R: CPython startup flags')
185
+ print('-X: utf8, dev, warn_default_encoding, int_max_str_digits; interactive flags are unsupported.')
186
+ return
187
+ if option == '--version':
188
+ version_count += 1
189
+ continue
190
+ if option.startswith('--'):
191
+ raise _SafeOptionError('unsupported option ' + option)
192
+ index = 1
193
+ while index < len(option):
194
+ flag = option[index]
195
+ if flag in ('h', '?'):
196
+ args = ['--help']
197
+ break
198
+ if flag == 'V':
199
+ version_count += 1
200
+ index += 1
201
+ continue
202
+ if flag in ('c', 'm', 'W', 'X'):
203
+ operand = option[index + 1:] if index + 1 < len(option) else args.pop(0) if args else None
204
+ if operand is None:
205
+ raise _SafeOptionError('argument expected for -' + flag)
206
+ if flag in ('W', 'X'):
207
+ if flag == 'W': warning_options.append(operand)
208
+ break
209
+ args = ['-' + flag, operand] + args
210
+ break
211
+ elif flag in ('O', 'S', 's', 'I', 'b', 'd', 'v', 'q', 'R'):
212
+ pass # Applied by CPython startup configuration before bootstrap.
213
+ elif flag == 'u':
214
+ unbuffered = True
215
+ elif flag == 'B':
216
+ sys.dont_write_bytecode = True
217
+ elif flag == 'E':
218
+ ignore_env = True
219
+ elif flag == 'P':
220
+ safe_path = True
221
+ else:
222
+ raise _SafeOptionError('unsupported option -' + flag)
223
+ index += 1
224
+ if args and args[0] in ('-c', '-m'):
225
+ break
226
+ if version_count:
227
+ print('Python ' + (sys.version if version_count > 1 else sys.version.split()[0]))
228
+ return
229
+ if not ignore_env:
230
+ unbuffered = unbuffered or bool(os.environ.get('PYTHONUNBUFFERED'))
231
+ sys.dont_write_bytecode = sys.dont_write_bytecode or bool(os.environ.get('PYTHONDONTWRITEBYTECODE'))
232
+ safe_path = safe_path or bool(os.environ.get('PYTHONSAFEPATH'))
233
+ path = os.environ.get('PYTHONPATH')
234
+ if path:
235
+ sys.path[0:0] = [os.path.abspath(entry) for entry in path.split(os.pathsep)]
236
+ if os.environ.get('PYTHONWARNINGS'):
237
+ warning_options[0:0] = os.environ['PYTHONWARNINGS'].split(',')
238
+ encoding = os.environ.get('PYTHONIOENCODING')
239
+ if encoding:
240
+ name, separator, errors = encoding.partition(':')
241
+ for stream in (sys.stdin, sys.stdout):
242
+ stream.reconfigure(encoding=name or None, errors=(errors or 'strict'))
243
+ sys.stderr.reconfigure(encoding=name or None, errors='backslashreplace')
244
+ # CPython's -b/-bb filter follows environment and command-line -W filters.
245
+ byte_warning = ('error' if sys.flags.bytes_warning > 1 else 'default') + '::BytesWarning'
246
+ native_before = [value for value in native_warning_options if not (sys.flags.bytes_warning and value == byte_warning)]
247
+ warning_options = native_before + warning_options + ([byte_warning] if sys.flags.bytes_warning else [])
248
+ warnings._processoptions(warning_options)
249
+ sys.warnoptions[:] = warning_options
250
+ if unbuffered:
251
+ for name in ('stdout', 'stderr'):
252
+ stream = getattr(sys, name)
253
+ stream.flush()
254
+ encoding, errors = stream.encoding, stream.errors
255
+ binary = stream.detach()
256
+ raw = binary.detach() if hasattr(binary, 'detach') else binary
257
+ replacement = io.TextIOWrapper(raw, encoding=encoding, errors=errors, write_through=True)
258
+ setattr(sys, name, replacement)
259
+ setattr(sys, '__' + name + '__', replacement)
260
+ main = types.ModuleType('__main__')
261
+ main.__dict__.update(__package__=None, __spec__=None, __loader__=__import__('importlib.machinery', fromlist=['BuiltinImporter']).BuiltinImporter, __builtins__=__builtins__)
262
+ sys.modules['__main__'] = main
263
+ if not options_terminated and args and args[0] == '-c':
264
+ sys.argv = ['-c'] + args[2:]
265
+ if not safe_path: sys.path.insert(0, '')
266
+ source = textwrap.dedent(args[1])
267
+ code = compile(source, '<string>', 'exec')
268
+ # CPython 3.14 retains -c source for both top-level and nested tracebacks.
269
+ linecache._register_code(code, source, '<string>')
270
+ exec(code, main.__dict__)
271
+ elif not options_terminated and args and args[0] == '-m':
272
+ sys.argv = args[1:]
273
+ if not safe_path: sys.path.insert(0, os.getcwd())
274
+ runpy._run_module_as_main(args[1], alter_argv=True)
275
+ elif not args or args[0] == '-':
276
+ sys.argv = (['-'] + args[1:]) if args else ['']
277
+ if not safe_path: sys.path.insert(0, '')
278
+ main.__file__ = '<stdin>'
279
+ exec(compile(sys.stdin.buffer.read(), '<stdin>', 'exec'), main.__dict__)
280
+ else:
281
+ sys.argv = args
282
+ # CPython makes __file__ absolute without collapsing ./ or ../ components.
283
+ path = args[0] if os.path.isabs(args[0]) else os.path.join(os.getcwd(), args[0])
284
+ importer = __import__('pkgutil').get_importer(path)
285
+ if importer is not None:
286
+ sys.path.insert(0, path)
287
+ runpy._run_module_as_main('__main__', alter_argv=False)
288
+ else:
289
+ if not safe_path: sys.path.insert(0, os.path.dirname(os.path.realpath(path)))
290
+ try:
291
+ with open(path, 'rb') as source:
292
+ code = source.read()
293
+ except OSError as error:
294
+ print("python: can't open file " + repr(path) + ': [Errno ' + str(error.errno) + '] ' + error.strerror, file=sys.stderr)
295
+ return 2
296
+ main.__file__ = path
297
+ main.__loader__ = __import__('importlib.machinery', fromlist=['SourceFileLoader']).SourceFileLoader('__main__', path)
298
+ exec(compile(code, path, 'exec'), main.__dict__)
299
+ return 0
300
+
301
+ try:
302
+ _safe_exit = _safe_launch() or 0
303
+ except SystemExit as _error:
304
+ _safe_exit = _safe_system_exit(_error)
305
+ except _SafeOptionError as _error:
306
+ print('python: ' + str(_error), file=sys.stderr)
307
+ _safe_exit = 2
308
+ except BaseException as _error:
309
+ # Hide bridge frames while preserving actual Python frames and chained errors.
310
+ _trace = _error.__traceback__
311
+ while _trace is not None and _trace.tb_frame.f_code.co_filename == '<exec>':
312
+ _trace = _trace.tb_next
313
+ _error.__traceback__ = _trace
314
+ sys.last_exc = _error
315
+ _safe_exit = 130 if isinstance(_error, KeyboardInterrupt) else 1
316
+ try:
317
+ sys.excepthook(type(_error), _error, _trace)
318
+ except SystemExit as _hook_error:
319
+ _safe_exit = _safe_system_exit(_hook_error)
320
+ except BaseException as _hook_error:
321
+ print('Error in sys.excepthook:', file=sys.stderr)
322
+ traceback.print_exception(type(_hook_error), _hook_error, _hook_error.__traceback__.tb_next)
323
+ print('\\nOriginal exception was:', file=sys.stderr)
324
+ sys.__excepthook__(type(_error), _error, _trace)
325
+ finally:
326
+ for _stream in (sys.stdout, sys.stderr):
327
+ if _stream is not None and not getattr(_stream, 'closed', False):
328
+ try:
329
+ _stream.flush()
330
+ except BaseException:
331
+ _safe_exit = 120
332
+ _safe_exit
333
+ `;
334
+
335
+ // packages/safe-bash/src/commands/python/runtime-scripts.ts
336
+ init_platform();
337
+ var pythonRuntimeRelocation = `
338
+ import sys, zipimport, importlib.machinery
339
+
340
+ def _rebase_runtime_path(value):
341
+ return _safe_runtime_mount + value if isinstance(value, str) and (value == '/lib' or value.startswith('/lib/')) else value
342
+
343
+ def _rebase_runtime_loader(loader):
344
+ if isinstance(loader, zipimport.zipimporter):
345
+ archive = _rebase_runtime_path(loader.archive)
346
+ if archive != loader.archive:
347
+ return zipimport.zipimporter(archive + '/' + loader.prefix)
348
+ elif isinstance(loader, (importlib.machinery.SourceFileLoader, importlib.machinery.SourcelessFileLoader, importlib.machinery.ExtensionFileLoader)):
349
+ path = _rebase_runtime_path(loader.path)
350
+ if path != loader.path:
351
+ return type(loader)(loader.name, path)
352
+ return loader
353
+ sys.path[:] = [_rebase_runtime_path(value) for value in sys.path]
354
+ for _module in list(sys.modules.values()):
355
+ if _module is None:
356
+ continue
357
+ for _attribute in ('__file__', '__cached__'):
358
+ if hasattr(_module, _attribute):
359
+ setattr(_module, _attribute, _rebase_runtime_path(getattr(_module, _attribute)))
360
+ if hasattr(_module, '__path__'):
361
+ _module.__path__ = [_rebase_runtime_path(value) for value in _module.__path__]
362
+ if hasattr(_module, '__loader__'):
363
+ _module.__loader__ = _rebase_runtime_loader(_module.__loader__)
364
+ _spec = getattr(_module, '__spec__', None)
365
+ if _spec is not None:
366
+ _spec.origin = _rebase_runtime_path(_spec.origin)
367
+ _spec.loader = _rebase_runtime_loader(_spec.loader)
368
+ if _spec.submodule_search_locations is not None:
369
+ _spec.submodule_search_locations = [_rebase_runtime_path(value) for value in _spec.submodule_search_locations]
370
+ sys.path_importer_cache.clear()
371
+ `;
372
+ var pythonImportMetadata = `
373
+ import importlib._bootstrap_external, types, json
374
+ _safe_import_stat_callback = _safe_import_stat
375
+ _safe_original_import_stat = importlib._bootstrap_external._path_stat
376
+ def _safe_import_path_stat(path):
377
+ if path == _safe_runtime_mount or path.startswith(_safe_runtime_mount + '/'):
378
+ return _safe_original_import_stat(path)
379
+ value = json.loads(_safe_import_stat_callback(path))
380
+ if 'errno' in value:
381
+ raise OSError(value['errno'], 'filesystem import metadata unavailable', path)
382
+ return types.SimpleNamespace(st_mode=value['mode'], st_size=value['size'], st_mtime=value['mtimeMs'] / 1000)
383
+ importlib._bootstrap_external._path_stat = _safe_import_path_stat
384
+ `;
385
+ var pythonDirectoryEntries = `
386
+ import os, json, errno
387
+ _safe_directory_callback = _safe_directory_entries
388
+ def _safe_listdir(path='.'):
389
+ if isinstance(path, int):
390
+ raise OSError(errno.ENOTSUP, 'retained directory descriptors are unsupported')
391
+ original = os.fspath(path) if path is not None else '.'
392
+ value = json.loads(_safe_directory_callback(os.fsdecode(original)))
393
+ if 'errno' in value:
394
+ raise OSError(value['errno'], 'directory enumeration failed', path)
395
+ return [os.fsencode(name) for name in value['entries']] if isinstance(original, bytes) else value['entries']
396
+ os.listdir = _safe_listdir
397
+ # The frozen importer holds the posix module separately from os.
398
+ importlib._bootstrap_external._os.listdir = _safe_listdir
399
+ `;
400
+ var pythonStatProjection = `
401
+ import os, json, errno
402
+ _safe_stat_callback = _safe_stat_projection
403
+ _safe_stat_type = os.stat_result
404
+ _safe_fspath = os.fspath
405
+ _safe_fsdecode = os.fsdecode
406
+
407
+ def _safe_stat(path, *, dir_fd=None, follow_symlinks=True):
408
+ if dir_fd is not None:
409
+ raise OSError(errno.ENOTSUP, 'dir_fd metadata is unsupported')
410
+ if isinstance(path, int):
411
+ if not follow_symlinks:
412
+ raise ValueError('stat: cannot use fd and follow_symlinks together')
413
+ else:
414
+ path = _safe_fsdecode(_safe_fspath(path))
415
+ value = json.loads(_safe_stat_callback(path, follow_symlinks))
416
+ if 'errno' in value:
417
+ raise OSError(value['errno'], 'filesystem metadata unavailable', path)
418
+ keys = ('mode','ino','dev','nlink','uid','gid','size')
419
+ if any(key not in value for key in keys):
420
+ raise OSError(errno.EOVERFLOW, 'canonical identity or required stat metadata unavailable', path)
421
+ times = [value[key] / 1000 for key in ('atimeMs','mtimeMs','ctimeMs')]
422
+ extras = dict(zip(('st_atime','st_mtime','st_ctime'), times))
423
+ for name, milliseconds in zip(('atime','mtime','ctime'), (value['atimeMs'],value['mtimeMs'],value['ctimeMs'])):
424
+ seconds = int(milliseconds // 1000)
425
+ extras['st_' + name + '_ns'] = seconds * 1000000000 + round((milliseconds - seconds * 1000) * 1000000)
426
+ for key in ('blocks','blksize','rdev'):
427
+ if key in value:
428
+ extras['st_' + key] = value[key]
429
+ return _safe_stat_type(tuple(value[key] for key in keys) + tuple(int(time // 1) for time in times), extras)
430
+
431
+ def _safe_lstat(path, *, dir_fd=None):
432
+ return _safe_stat(path, dir_fd=dir_fd, follow_symlinks=False)
433
+
434
+ def _safe_fstat(fd):
435
+ if not isinstance(fd, int):
436
+ raise TypeError('file descriptor must be an integer')
437
+ return _safe_stat(fd)
438
+ os.stat = _safe_stat
439
+ os.lstat = _safe_lstat
440
+ os.fstat = _safe_fstat
441
+ import stat as _safe_stat_module
442
+ class _SafeDirEntry:
443
+ def __init__(self, root, name):
444
+ self.name = name
445
+ self.path = os.path.join(root, name)
446
+ self._cache = {}
447
+ def __fspath__(self):
448
+ return self.path
449
+ def stat(self, *, follow_symlinks=True):
450
+ if follow_symlinks not in self._cache:
451
+ self._cache[follow_symlinks] = os.stat(self.path, follow_symlinks=follow_symlinks)
452
+ return self._cache[follow_symlinks]
453
+ def inode(self):
454
+ return self.stat(follow_symlinks=False).st_ino
455
+ def is_dir(self, *, follow_symlinks=True):
456
+ try:
457
+ return _safe_stat_module.S_ISDIR(self.stat(follow_symlinks=follow_symlinks).st_mode)
458
+ except FileNotFoundError:
459
+ return False
460
+ def is_file(self, *, follow_symlinks=True):
461
+ try:
462
+ return _safe_stat_module.S_ISREG(self.stat(follow_symlinks=follow_symlinks).st_mode)
463
+ except FileNotFoundError:
464
+ return False
465
+ def is_symlink(self):
466
+ try:
467
+ return _safe_stat_module.S_ISLNK(self.stat(follow_symlinks=False).st_mode)
468
+ except FileNotFoundError:
469
+ return False
470
+ class _SafeScandir:
471
+ def __init__(self, path):
472
+ self._entries = iter([_SafeDirEntry(path, name) for name in os.listdir(path)])
473
+ def __iter__(self):
474
+ return self
475
+ def __next__(self):
476
+ return next(self._entries)
477
+ def close(self):
478
+ self._entries = iter(())
479
+ def __enter__(self):
480
+ return self
481
+ def __exit__(self, *args):
482
+ self.close()
483
+ def _safe_scandir(path='.'):
484
+ if isinstance(path, int):
485
+ raise OSError(errno.ENOTSUP, 'retained directory descriptors are unsupported')
486
+ return _SafeScandir(os.fspath(path) if path is not None else '.')
487
+ os.scandir = _safe_scandir
488
+
489
+ `;
490
+ var pythonTreeCleanup = `
491
+ import shutil, os, json
492
+ _safe_tree_callback = _safe_tree_cleanup
493
+ _safe_original_rmtree_impl = shutil._rmtree_impl
494
+ def _safe_rmtree_impl(path, dir_fd, onexc):
495
+ if dir_fd is not None:
496
+ return _safe_original_rmtree_impl(path, dir_fd, onexc)
497
+ value = json.loads(_safe_tree_callback(os.fsdecode(path)))
498
+ if not value['supported']:
499
+ return _safe_original_rmtree_impl(path, dir_fd, onexc)
500
+ if 'errno' in value:
501
+ onexc(os.rmdir, path, OSError(value['errno'], 'directory cleanup failed', path))
502
+ shutil._rmtree_impl = _safe_rmtree_impl
503
+ `;
504
+
505
+ export {
506
+ PythonInvocationError,
507
+ parsePythonInvocation,
508
+ PythonFailure,
509
+ isPythonFailureCategory,
510
+ reportPythonFailure,
511
+ inspectPythonCapabilities,
512
+ pythonExecution,
513
+ pythonRuntimeRelocation,
514
+ pythonImportMetadata,
515
+ pythonDirectoryEntries,
516
+ pythonStatProjection,
517
+ pythonTreeCleanup
518
+ };
519
+ //# sourceMappingURL=chunk-4MPK7VIM.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/python/invocation.ts", "../../src/commands/python/diagnostics.ts", "../../src/commands/python/execution.ts", "../../src/commands/python/runtime-scripts.ts"],
4
+ "sourcesContent": ["/** An explicit compatibility failure, rendered as Python usage status 2. */\nexport class PythonInvocationError extends Error {\n constructor(message: string) { super(message); this.name = 'PythonInvocationError'; }\n}\n\n/** Extract native initialization flags without consuming script/module arguments. */\nexport function parsePythonInvocation(args: readonly string[], env: Readonly<Record<string, string>>): {\n readonly startupArgs: string[];\n readonly env: Record<string, string>;\n} {\n const startupArgs: string[] = [];\n let informational = false;\n scan: for (let index = 0; index < args.length; index++) {\n const option = args[index]!;\n if (option === '--' || option === '-' || !option.startsWith('-')) break;\n if (option === '--help') { informational = true; break; }\n if (option === '--version') { informational = true; continue; }\n if (option.startsWith('--')) throw new PythonInvocationError('unsupported option ' + option);\n for (let offset = 1; offset < option.length; offset++) {\n const flag = option[offset]!;\n if (flag === 'h' || flag === '?') { informational = true; break scan; }\n if (flag === 'V') { informational = true; continue; }\n if ('cmWX'.includes(flag)) {\n const operand = option.slice(offset + 1) || args[++index];\n if (operand === undefined) throw new PythonInvocationError('argument expected for -' + flag);\n if (flag === 'c' || flag === 'm') break scan;\n if (flag === 'X') {\n const separator = operand.indexOf('=');\n const name = separator < 0 ? operand : operand.slice(0, separator);\n const value = separator < 0 ? undefined : operand.slice(separator + 1);\n let decimal = value ?? '';\n while (decimal.length && ' \\t\\n\\r\\v\\f'.includes(decimal[0]!)) decimal = decimal.slice(1);\n if (decimal[0] === '+' || decimal[0] === '-') decimal = decimal.slice(1);\n const digits = decimal.length > 0 && [...decimal].every(character => character >= '0' && character <= '9');\n const supported = (name === 'utf8' && (value === undefined || value === '0' || value === '1'))\n || ((name === 'dev' || name === 'warn_default_encoding') && value === undefined)\n || (name === 'int_max_str_digits' && digits && Number.isSafeInteger(Number(value)) && Number(value) <= 2147483647 && (Number(value) === 0 || Number(value) >= 640));\n if (!supported) throw new PythonInvocationError('unsupported -X option ' + operand);\n startupArgs.push('-X', operand);\n }\n // Warning-as-error can prevent Pyodide bootstrap; apply -W after bootstrap.\n break;\n }\n if (!'BEPOusISbdvqR'.includes(flag)) throw new PythonInvocationError('unsupported option -' + flag);\n startupArgs.push('-' + flag);\n }\n }\n if (!informational && !startupArgs.includes('-E') && !startupArgs.includes('-I')) {\n if (env.PYTHONINSPECT) throw new PythonInvocationError('PYTHONINSPECT requires an interactive terminal, which the shell does not expose');\n if (env.PYTHONHOME) throw new PythonInvocationError('PYTHONHOME cannot replace the configured Pyodide runtime');\n }\n const runtimeEnv = { ...env };\n // These paths belong to the canonical filesystem, mounted after bootstrap.\n delete runtimeEnv.PYTHONPATH;\n delete runtimeEnv.PYTHONHOME;\n delete runtimeEnv.PYTHONWARNINGS;\n // Pyodide otherwise supplies PYTHONINSPECT=1, including with a -c operand.\n runtimeEnv.PYTHONINSPECT = '';\n // Without a command Pyodide initializes CPython in inspect mode.\n startupArgs.push('-c', '');\n return { startupArgs, env: runtimeEnv };\n}\n", "import type { FileSystem } from '../../contracts/filesystem.js';\n\nconst messages = {\n 'executor-unavailable': 'Python executor is unavailable; configure exactly one supported executor or interpreter worker.',\n 'transport-unavailable': 'Python worker transport or shared-memory operations are unavailable.',\n 'runtime-abi': 'Python runtime version or native ABI is unsupported.',\n 'runtime-assets': 'Python runtime or package assets could not be loaded.',\n 'isolation-unavailable': 'Python host isolation or resource enforcement is unavailable.',\n deadline: 'Python execution exceeded its host deadline.',\n 'filesystem-open': 'Python filesystem handle access is unavailable; the backend must support retained open.',\n 'filesystem-read': 'Python filesystem reads are unavailable for this backend.',\n 'filesystem-write': 'Python filesystem writes are unavailable for this backend.',\n 'filesystem-directory': 'Python retained directory operations are unavailable for this backend.',\n 'filesystem-operation': 'The requested Python filesystem operation is unavailable for this backend.',\n capacity: 'Python worker capacity exhausted.',\n cleanup: 'Python resource cleanup failed; retirement could not be confirmed.',\n startup: 'Python startup failed; consult the host diagnostic callback.',\n runtime: 'Python runtime failed; consult the host diagnostic callback.',\n} as const;\n\nexport type PythonFailureCategory = keyof typeof messages;\n\nexport class PythonFailure extends Error {\n constructor(readonly category: PythonFailureCategory, options?: ErrorOptions) {\n super(messages[category], options);\n this.name = 'PythonFailure';\n }\n}\n\nexport interface PythonDiagnostic {\n readonly failure: PythonFailure;\n readonly cause: unknown;\n}\n\nexport type PythonDiagnosticObserver = (diagnostic: PythonDiagnostic) => void | Promise<void>;\nexport type PythonFileSystemRequirement = 'open' | 'read' | 'write' | 'directory';\n\nexport function isPythonFailureCategory(value: unknown): value is PythonFailureCategory {\n return typeof value === 'string' && Object.hasOwn(messages, value);\n}\n\nexport function reportPythonFailure(category: PythonFailureCategory, cause: unknown, observer?: PythonDiagnosticObserver): PythonFailure {\n const failure = new PythonFailure(category);\n try { void Promise.resolve(observer?.({ failure, cause })).catch(() => {}); } catch {}\n return failure;\n}\n\nexport interface PythonCapabilityOptions {\n readonly createWorker?: () => unknown;\n readonly createExecutor?: () => unknown;\n readonly fs?: FileSystem;\n readonly requiredFileSystem?: readonly PythonFileSystemRequirement[];\n readonly runtimeVersion?: string;\n}\n\nexport interface PythonCapabilityReport {\n readonly configurationValid: boolean;\n readonly failures: readonly PythonFailure[];\n}\n\nexport function inspectPythonCapabilities(options: PythonCapabilityOptions = {}): PythonCapabilityReport {\n const failures = new Set<PythonFailureCategory>();\n if ((typeof options.createWorker === 'function') === (typeof options.createExecutor === 'function')\n || options.createWorker !== undefined && typeof options.createWorker !== 'function'\n || options.createExecutor !== undefined && typeof options.createExecutor !== 'function') failures.add('executor-unavailable');\n if (typeof options.createExecutor !== 'function' && (typeof SharedArrayBuffer !== 'function' || typeof Atomics !== 'object'\n || typeof Atomics.store !== 'function' || typeof Atomics.notify !== 'function')) failures.add('transport-unavailable');\n if (options.runtimeVersion !== undefined && options.runtimeVersion !== '314.0.6') failures.add('runtime-abi');\n for (const requirement of options.requiredFileSystem ?? []) {\n if (!['open', 'read', 'write', 'directory'].includes(requirement)) throw new TypeError('Unknown Python filesystem requirement');\n const category: PythonFailureCategory = requirement === 'open' ? 'filesystem-open'\n : requirement === 'read' ? 'filesystem-read' : requirement === 'write' ? 'filesystem-write' : 'filesystem-directory';\n try {\n const fs = options.fs;\n if (requirement === 'directory') {\n failures.add(category);\n } else if (!fs || typeof fs.open !== 'function' || fs.capabilities.open === false) failures.add('filesystem-open');\n else if (requirement === 'write' && (fs.capabilities.readOnly === true || fs.capabilities.write === false)) failures.add(category);\n else if (requirement === 'read' && fs.capabilities.read === false) failures.add(category);\n } catch { failures.add(category); }\n }\n return Object.freeze({ configurationValid: failures.size === 0,\n failures: Object.freeze([...failures].map(category => new PythonFailure(category))) });\n}\n", "/** Executed by CPython after canonical storage and byte streams are installed. */\nexport const pythonExecution = `\nimport sys, os, json, runpy, traceback, types, warnings, textwrap, io, struct, linecache\n_safe_invocation = json.loads(_safe_invocation_json)\nos.environ.clear()\nos.environ.update(_safe_invocation['env'])\n_safe_args = list(_safe_invocation['args'])\nsys.orig_argv = [_safe_invocation.get('command', 'python')] + _safe_args\n_safe_exit = 0\n\nclass _SafeOptionError(ValueError):\n pass\n\ndef _safe_system_exit(_error):\n if isinstance(_error.code, int):\n _status = int.__index__(_error.code)\n _long_bound = 1 << (8 * struct.calcsize('@l') - 1)\n status = (_status & 255) if -_long_bound <= _status < _long_bound else 255\n else:\n status = 0 if _error.code is None else 1\n if _error.code is not None and not isinstance(_error.code, int):\n print(_error.code, file=sys.stderr)\n return status\n\ndef _safe_launch():\n args = list(_safe_args)\n unbuffered = False\n ignore_env = bool(sys.flags.ignore_environment)\n safe_path = bool(sys.flags.safe_path)\n native_warning_options = list(sys.warnoptions)\n # Pyodide adds a bootstrap cwd entry even when CPython safe-path mode is set.\n # Each execution mode below supplies its own entry after explicit PYTHONPATH.\n sys.path[:] = [entry for entry in sys.path if entry != '']\n warning_options = []\n version_count = 0\n options_terminated = False\n while args and args[0].startswith('-') and args[0] != '-':\n option = args.pop(0)\n if option == '--':\n options_terminated = True\n break\n if option in ('--help', '-h', '-?'):\n print('usage: python [-uBEPOsSIbdvqR] [-W filter] [-X option] [-c code | -m module | file | -] [args ...]')\n print('Dedicated Pyodide interpreter; stdin is noninteractive.')\n print('-u: unbuffered binary output; -B: disable bytecode writes; -E: ignore PYTHON* settings')\n print('-P: omit automatic unsafe sys.path entry; -W: Python warning filter')\n print('-O/-OO, -S/-s/-I, -b/-bb, -d/-v/-q/-R: CPython startup flags')\n print('-X: utf8, dev, warn_default_encoding, int_max_str_digits; interactive flags are unsupported.')\n return\n if option == '--version':\n version_count += 1\n continue\n if option.startswith('--'):\n raise _SafeOptionError('unsupported option ' + option)\n index = 1\n while index < len(option):\n flag = option[index]\n if flag in ('h', '?'):\n args = ['--help']\n break\n if flag == 'V':\n version_count += 1\n index += 1\n continue\n if flag in ('c', 'm', 'W', 'X'):\n operand = option[index + 1:] if index + 1 < len(option) else args.pop(0) if args else None\n if operand is None:\n raise _SafeOptionError('argument expected for -' + flag)\n if flag in ('W', 'X'):\n if flag == 'W': warning_options.append(operand)\n break\n args = ['-' + flag, operand] + args\n break\n elif flag in ('O', 'S', 's', 'I', 'b', 'd', 'v', 'q', 'R'):\n pass # Applied by CPython startup configuration before bootstrap.\n elif flag == 'u':\n unbuffered = True\n elif flag == 'B':\n sys.dont_write_bytecode = True\n elif flag == 'E':\n ignore_env = True\n elif flag == 'P':\n safe_path = True\n else:\n raise _SafeOptionError('unsupported option -' + flag)\n index += 1\n if args and args[0] in ('-c', '-m'):\n break\n if version_count:\n print('Python ' + (sys.version if version_count > 1 else sys.version.split()[0]))\n return\n if not ignore_env:\n unbuffered = unbuffered or bool(os.environ.get('PYTHONUNBUFFERED'))\n sys.dont_write_bytecode = sys.dont_write_bytecode or bool(os.environ.get('PYTHONDONTWRITEBYTECODE'))\n safe_path = safe_path or bool(os.environ.get('PYTHONSAFEPATH'))\n path = os.environ.get('PYTHONPATH')\n if path:\n sys.path[0:0] = [os.path.abspath(entry) for entry in path.split(os.pathsep)]\n if os.environ.get('PYTHONWARNINGS'):\n warning_options[0:0] = os.environ['PYTHONWARNINGS'].split(',')\n encoding = os.environ.get('PYTHONIOENCODING')\n if encoding:\n name, separator, errors = encoding.partition(':')\n for stream in (sys.stdin, sys.stdout):\n stream.reconfigure(encoding=name or None, errors=(errors or 'strict'))\n sys.stderr.reconfigure(encoding=name or None, errors='backslashreplace')\n # CPython's -b/-bb filter follows environment and command-line -W filters.\n byte_warning = ('error' if sys.flags.bytes_warning > 1 else 'default') + '::BytesWarning'\n native_before = [value for value in native_warning_options if not (sys.flags.bytes_warning and value == byte_warning)]\n warning_options = native_before + warning_options + ([byte_warning] if sys.flags.bytes_warning else [])\n warnings._processoptions(warning_options)\n sys.warnoptions[:] = warning_options\n if unbuffered:\n for name in ('stdout', 'stderr'):\n stream = getattr(sys, name)\n stream.flush()\n encoding, errors = stream.encoding, stream.errors\n binary = stream.detach()\n raw = binary.detach() if hasattr(binary, 'detach') else binary\n replacement = io.TextIOWrapper(raw, encoding=encoding, errors=errors, write_through=True)\n setattr(sys, name, replacement)\n setattr(sys, '__' + name + '__', replacement)\n main = types.ModuleType('__main__')\n main.__dict__.update(__package__=None, __spec__=None, __loader__=__import__('importlib.machinery', fromlist=['BuiltinImporter']).BuiltinImporter, __builtins__=__builtins__)\n sys.modules['__main__'] = main\n if not options_terminated and args and args[0] == '-c':\n sys.argv = ['-c'] + args[2:]\n if not safe_path: sys.path.insert(0, '')\n source = textwrap.dedent(args[1])\n code = compile(source, '<string>', 'exec')\n # CPython 3.14 retains -c source for both top-level and nested tracebacks.\n linecache._register_code(code, source, '<string>')\n exec(code, main.__dict__)\n elif not options_terminated and args and args[0] == '-m':\n sys.argv = args[1:]\n if not safe_path: sys.path.insert(0, os.getcwd())\n runpy._run_module_as_main(args[1], alter_argv=True)\n elif not args or args[0] == '-':\n sys.argv = (['-'] + args[1:]) if args else ['']\n if not safe_path: sys.path.insert(0, '')\n main.__file__ = '<stdin>'\n exec(compile(sys.stdin.buffer.read(), '<stdin>', 'exec'), main.__dict__)\n else:\n sys.argv = args\n # CPython makes __file__ absolute without collapsing ./ or ../ components.\n path = args[0] if os.path.isabs(args[0]) else os.path.join(os.getcwd(), args[0])\n importer = __import__('pkgutil').get_importer(path)\n if importer is not None:\n sys.path.insert(0, path)\n runpy._run_module_as_main('__main__', alter_argv=False)\n else:\n if not safe_path: sys.path.insert(0, os.path.dirname(os.path.realpath(path)))\n try:\n with open(path, 'rb') as source:\n code = source.read()\n except OSError as error:\n print(\"python: can't open file \" + repr(path) + ': [Errno ' + str(error.errno) + '] ' + error.strerror, file=sys.stderr)\n return 2\n main.__file__ = path\n main.__loader__ = __import__('importlib.machinery', fromlist=['SourceFileLoader']).SourceFileLoader('__main__', path)\n exec(compile(code, path, 'exec'), main.__dict__)\n return 0\n\ntry:\n _safe_exit = _safe_launch() or 0\nexcept SystemExit as _error:\n _safe_exit = _safe_system_exit(_error)\nexcept _SafeOptionError as _error:\n print('python: ' + str(_error), file=sys.stderr)\n _safe_exit = 2\nexcept BaseException as _error:\n # Hide bridge frames while preserving actual Python frames and chained errors.\n _trace = _error.__traceback__\n while _trace is not None and _trace.tb_frame.f_code.co_filename == '<exec>':\n _trace = _trace.tb_next\n _error.__traceback__ = _trace\n sys.last_exc = _error\n _safe_exit = 130 if isinstance(_error, KeyboardInterrupt) else 1\n try:\n sys.excepthook(type(_error), _error, _trace)\n except SystemExit as _hook_error:\n _safe_exit = _safe_system_exit(_hook_error)\n except BaseException as _hook_error:\n print('Error in sys.excepthook:', file=sys.stderr)\n traceback.print_exception(type(_hook_error), _hook_error, _hook_error.__traceback__.tb_next)\n print('\\\\nOriginal exception was:', file=sys.stderr)\n sys.__excepthook__(type(_error), _error, _trace)\nfinally:\n for _stream in (sys.stdout, sys.stderr):\n if _stream is not None and not getattr(_stream, 'closed', False):\n try:\n _stream.flush()\n except BaseException:\n _safe_exit = 120\n_safe_exit\n`;\n", "export const pythonRuntimeRelocation = `\nimport sys, zipimport, importlib.machinery\n\ndef _rebase_runtime_path(value):\n return _safe_runtime_mount + value if isinstance(value, str) and (value == '/lib' or value.startswith('/lib/')) else value\n\ndef _rebase_runtime_loader(loader):\n if isinstance(loader, zipimport.zipimporter):\n archive = _rebase_runtime_path(loader.archive)\n if archive != loader.archive:\n return zipimport.zipimporter(archive + '/' + loader.prefix)\n elif isinstance(loader, (importlib.machinery.SourceFileLoader, importlib.machinery.SourcelessFileLoader, importlib.machinery.ExtensionFileLoader)):\n path = _rebase_runtime_path(loader.path)\n if path != loader.path:\n return type(loader)(loader.name, path)\n return loader\nsys.path[:] = [_rebase_runtime_path(value) for value in sys.path]\nfor _module in list(sys.modules.values()):\n if _module is None:\n continue\n for _attribute in ('__file__', '__cached__'):\n if hasattr(_module, _attribute):\n setattr(_module, _attribute, _rebase_runtime_path(getattr(_module, _attribute)))\n if hasattr(_module, '__path__'):\n _module.__path__ = [_rebase_runtime_path(value) for value in _module.__path__]\n if hasattr(_module, '__loader__'):\n _module.__loader__ = _rebase_runtime_loader(_module.__loader__)\n _spec = getattr(_module, '__spec__', None)\n if _spec is not None:\n _spec.origin = _rebase_runtime_path(_spec.origin)\n _spec.loader = _rebase_runtime_loader(_spec.loader)\n if _spec.submodule_search_locations is not None:\n _spec.submodule_search_locations = [_rebase_runtime_path(value) for value in _spec.submodule_search_locations]\nsys.path_importer_cache.clear()\n`;\n\nexport const pythonImportMetadata = `\nimport importlib._bootstrap_external, types, json\n_safe_import_stat_callback = _safe_import_stat\n_safe_original_import_stat = importlib._bootstrap_external._path_stat\ndef _safe_import_path_stat(path):\n if path == _safe_runtime_mount or path.startswith(_safe_runtime_mount + '/'):\n return _safe_original_import_stat(path)\n value = json.loads(_safe_import_stat_callback(path))\n if 'errno' in value:\n raise OSError(value['errno'], 'filesystem import metadata unavailable', path)\n return types.SimpleNamespace(st_mode=value['mode'], st_size=value['size'], st_mtime=value['mtimeMs'] / 1000)\nimportlib._bootstrap_external._path_stat = _safe_import_path_stat\n`;\n\nexport const pythonDirectoryEntries = `\nimport os, json, errno\n_safe_directory_callback = _safe_directory_entries\ndef _safe_listdir(path='.'):\n if isinstance(path, int):\n raise OSError(errno.ENOTSUP, 'retained directory descriptors are unsupported')\n original = os.fspath(path) if path is not None else '.'\n value = json.loads(_safe_directory_callback(os.fsdecode(original)))\n if 'errno' in value:\n raise OSError(value['errno'], 'directory enumeration failed', path)\n return [os.fsencode(name) for name in value['entries']] if isinstance(original, bytes) else value['entries']\nos.listdir = _safe_listdir\n# The frozen importer holds the posix module separately from os.\nimportlib._bootstrap_external._os.listdir = _safe_listdir\n`;\n\nexport const pythonStatProjection = `\nimport os, json, errno\n_safe_stat_callback = _safe_stat_projection\n_safe_stat_type = os.stat_result\n_safe_fspath = os.fspath\n_safe_fsdecode = os.fsdecode\n\ndef _safe_stat(path, *, dir_fd=None, follow_symlinks=True):\n if dir_fd is not None:\n raise OSError(errno.ENOTSUP, 'dir_fd metadata is unsupported')\n if isinstance(path, int):\n if not follow_symlinks:\n raise ValueError('stat: cannot use fd and follow_symlinks together')\n else:\n path = _safe_fsdecode(_safe_fspath(path))\n value = json.loads(_safe_stat_callback(path, follow_symlinks))\n if 'errno' in value:\n raise OSError(value['errno'], 'filesystem metadata unavailable', path)\n keys = ('mode','ino','dev','nlink','uid','gid','size')\n if any(key not in value for key in keys):\n raise OSError(errno.EOVERFLOW, 'canonical identity or required stat metadata unavailable', path)\n times = [value[key] / 1000 for key in ('atimeMs','mtimeMs','ctimeMs')]\n extras = dict(zip(('st_atime','st_mtime','st_ctime'), times))\n for name, milliseconds in zip(('atime','mtime','ctime'), (value['atimeMs'],value['mtimeMs'],value['ctimeMs'])):\n seconds = int(milliseconds // 1000)\n extras['st_' + name + '_ns'] = seconds * 1000000000 + round((milliseconds - seconds * 1000) * 1000000)\n for key in ('blocks','blksize','rdev'):\n if key in value:\n extras['st_' + key] = value[key]\n return _safe_stat_type(tuple(value[key] for key in keys) + tuple(int(time // 1) for time in times), extras)\n\ndef _safe_lstat(path, *, dir_fd=None):\n return _safe_stat(path, dir_fd=dir_fd, follow_symlinks=False)\n\ndef _safe_fstat(fd):\n if not isinstance(fd, int):\n raise TypeError('file descriptor must be an integer')\n return _safe_stat(fd)\nos.stat = _safe_stat\nos.lstat = _safe_lstat\nos.fstat = _safe_fstat\nimport stat as _safe_stat_module\nclass _SafeDirEntry:\n def __init__(self, root, name):\n self.name = name\n self.path = os.path.join(root, name)\n self._cache = {}\n def __fspath__(self):\n return self.path\n def stat(self, *, follow_symlinks=True):\n if follow_symlinks not in self._cache:\n self._cache[follow_symlinks] = os.stat(self.path, follow_symlinks=follow_symlinks)\n return self._cache[follow_symlinks]\n def inode(self):\n return self.stat(follow_symlinks=False).st_ino\n def is_dir(self, *, follow_symlinks=True):\n try:\n return _safe_stat_module.S_ISDIR(self.stat(follow_symlinks=follow_symlinks).st_mode)\n except FileNotFoundError:\n return False\n def is_file(self, *, follow_symlinks=True):\n try:\n return _safe_stat_module.S_ISREG(self.stat(follow_symlinks=follow_symlinks).st_mode)\n except FileNotFoundError:\n return False\n def is_symlink(self):\n try:\n return _safe_stat_module.S_ISLNK(self.stat(follow_symlinks=False).st_mode)\n except FileNotFoundError:\n return False\nclass _SafeScandir:\n def __init__(self, path):\n self._entries = iter([_SafeDirEntry(path, name) for name in os.listdir(path)])\n def __iter__(self):\n return self\n def __next__(self):\n return next(self._entries)\n def close(self):\n self._entries = iter(())\n def __enter__(self):\n return self\n def __exit__(self, *args):\n self.close()\ndef _safe_scandir(path='.'):\n if isinstance(path, int):\n raise OSError(errno.ENOTSUP, 'retained directory descriptors are unsupported')\n return _SafeScandir(os.fspath(path) if path is not None else '.')\nos.scandir = _safe_scandir\n\n`;\n\nexport const pythonTreeCleanup = `\nimport shutil, os, json\n_safe_tree_callback = _safe_tree_cleanup\n_safe_original_rmtree_impl = shutil._rmtree_impl\ndef _safe_rmtree_impl(path, dir_fd, onexc):\n if dir_fd is not None:\n return _safe_original_rmtree_impl(path, dir_fd, onexc)\n value = json.loads(_safe_tree_callback(os.fsdecode(path)))\n if not value['supported']:\n return _safe_original_rmtree_impl(path, dir_fd, onexc)\n if 'errno' in value:\n onexc(os.rmdir, path, OSError(value['errno'], 'directory cleanup failed', path))\nshutil._rmtree_impl = _safe_rmtree_impl\n`;\n"],
5
+ "mappings": "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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoChC,IAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAc7B,IAAM,yBAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgB/B,IAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2F7B,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
6
+ "names": []
7
+ }