@poe-platform/safe-bash 0.1.826 → 0.1.827

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 (150) hide show
  1. package/dist/image-ast/index.js +39 -18
  2. package/dist/pdf-ast/image.js +1 -1
  3. package/dist/pdf-ast/index.js +1 -1
  4. package/dist/pdf-ast/vendor/pdfjs-fonts.mjs +9 -3
  5. package/dist/safe-bash/chunks/{chunk-AGHV53VF.js → chunk-M6XFU6LQ.js} +3 -1
  6. package/dist/safe-bash/chunks/{chunk-363QOIDR.js → chunk-T6FHWSHM.js} +3 -1
  7. package/dist/safe-bash/command-chunks/{chunk-ZPBL7TYJ.js → chunk-2JRHCVMQ.js} +1 -1
  8. package/dist/safe-bash/command-chunks/{chunk-FMGNXOMV.js → chunk-2L3NMRLG.js} +7 -3
  9. package/dist/safe-bash/command-chunks/{chunk-DAQO64WC.js → chunk-2YKOJPIW.js} +1 -1
  10. package/dist/safe-bash/command-chunks/{chunk-EPYJSPOY.js → chunk-3QCW4VQF.js} +12 -8
  11. package/dist/safe-bash/command-chunks/{chunk-YRBFNT5B.js → chunk-3YL2TMLA.js} +10 -1
  12. package/dist/safe-bash/command-chunks/{chunk-5H7ZHP7F.js → chunk-43NDRBKY.js} +1 -1
  13. package/dist/safe-bash/command-chunks/{chunk-BBOYR6LV.js → chunk-46GA576V.js} +3 -3
  14. package/dist/safe-bash/command-chunks/{chunk-WPT2FCHH.js → chunk-4SLPM2WM.js} +1 -1
  15. package/dist/safe-bash/command-chunks/{chunk-7ZQVMPSB.js → chunk-5CAXR62E.js} +1 -1
  16. package/dist/safe-bash/command-chunks/{chunk-3DTHX5UU.js → chunk-66653AEZ.js} +40 -14
  17. package/dist/safe-bash/command-chunks/{chunk-ETFJ4L7F.js → chunk-6OLE6CLV.js} +1 -1
  18. package/dist/safe-bash/command-chunks/{chunk-ZIDESNHW.js → chunk-7M3M6FKC.js} +1 -1
  19. package/dist/safe-bash/command-chunks/{chunk-2KMNVJB7.js → chunk-A7PKUIJT.js} +1 -1
  20. package/dist/safe-bash/command-chunks/{chunk-P66Q5F6K.js → chunk-DEQ47SBQ.js} +3 -3
  21. package/dist/safe-bash/command-chunks/{chunk-EV7A5FNN.js → chunk-FFFRLPXU.js} +2 -2
  22. package/dist/safe-bash/command-chunks/{chunk-4MVQE6CT.js → chunk-FYTBEGSY.js} +1 -1
  23. package/dist/safe-bash/command-chunks/{chunk-VKTM2SOL.js → chunk-HQIZR6EU.js} +192 -489
  24. package/dist/safe-bash/command-chunks/chunk-HS2L7I4N.js +219 -0
  25. package/dist/safe-bash/command-chunks/{chunk-WKS2PAZL.js → chunk-HUGKO4ZE.js} +10 -1
  26. package/dist/safe-bash/command-chunks/{chunk-NXZJJM4J.js → chunk-IGXH5W5Z.js} +1 -1
  27. package/dist/safe-bash/command-chunks/{chunk-CMJBRGU2.js → chunk-IHQZKUBS.js} +1 -1
  28. package/dist/safe-bash/command-chunks/chunk-JADJ4BMN.js +1519 -0
  29. package/dist/safe-bash/command-chunks/{chunk-5AQAWIYK.js → chunk-JEZC5V3B.js} +4 -0
  30. package/dist/safe-bash/command-chunks/{chunk-YB5TNDY6.js → chunk-K5VJ4NNL.js} +39 -5
  31. package/dist/safe-bash/command-chunks/{chunk-7RQGRFHJ.js → chunk-KHWDEAE4.js} +2 -2
  32. package/dist/safe-bash/command-chunks/chunk-L54KVUSY.js +604 -0
  33. package/dist/safe-bash/command-chunks/{chunk-3NJETNC2.js → chunk-MBXNG6C3.js} +2 -2
  34. package/dist/safe-bash/command-chunks/{chunk-HCPEYQKT.js → chunk-N4SH6QY5.js} +285 -302
  35. package/dist/safe-bash/command-chunks/{chunk-3DID6MQY.js → chunk-OWTQYLID.js} +2 -2
  36. package/dist/safe-bash/command-chunks/{chunk-4EA7WI3L.js → chunk-QOOQD6BD.js} +42 -33
  37. package/dist/safe-bash/command-chunks/{chunk-RQTFK7AV.js → chunk-QZYEI4N6.js} +1 -1
  38. package/dist/safe-bash/command-chunks/{chunk-R3SLT3ZX.js → chunk-R6GON4H3.js} +11 -1
  39. package/dist/safe-bash/command-chunks/{chunk-2GILUQJY.js → chunk-R7ZGDHME.js} +3 -3
  40. package/dist/safe-bash/command-chunks/{chunk-LKAFLJ5L.js → chunk-RWQKX44L.js} +1 -1
  41. package/dist/safe-bash/command-chunks/{chunk-PKH57OIC.js → chunk-SG2KOOD4.js} +2 -2
  42. package/dist/safe-bash/command-chunks/chunk-T4TGJYFV.js +60 -0
  43. package/dist/safe-bash/command-chunks/{chunk-NXCJNPL3.js → chunk-UCE77LYV.js} +2 -1
  44. package/dist/safe-bash/command-chunks/{chunk-EWECMOQ5.js → chunk-UIHPHIKI.js} +1 -1
  45. package/dist/safe-bash/command-chunks/{chunk-T7RT2BNL.js → chunk-UJPWPRVB.js} +191 -146
  46. package/dist/safe-bash/command-chunks/{chunk-E5CDHXFA.js → chunk-VOR6YDZC.js} +26 -1
  47. package/dist/safe-bash/command-chunks/chunk-VSNVYOK2.js +30 -0
  48. package/dist/safe-bash/command-chunks/{chunk-4XYGJB24.js → chunk-VTH4AORO.js} +3 -3
  49. package/dist/safe-bash/command-chunks/{chunk-W5LH7D23.js → chunk-WKKJJBJQ.js} +8 -8
  50. package/dist/safe-bash/command-chunks/{chunk-Q2ACHUTY.js → chunk-WRO3PB2M.js} +1 -1
  51. package/dist/safe-bash/command-chunks/{chunk-RUAGHZNF.js → chunk-X5ODTF3E.js} +7 -5
  52. package/dist/safe-bash/command-chunks/{chunk-LH4VBNF6.js → chunk-XGTSP2CP.js} +84 -16
  53. package/dist/safe-bash/command-chunks/{chunk-K576GZED.js → chunk-XTHKXCF2.js} +2 -2
  54. package/dist/safe-bash/command-chunks/{chunk-J3VS55K4.js → chunk-YHRESVJ7.js} +9 -3
  55. package/dist/safe-bash/command-chunks/{chunk-UWIDPTOB.js → chunk-YSCKOUQP.js} +1 -1
  56. package/dist/safe-bash/command-chunks/{chunk-UYNJF5QN.js → chunk-ZALAWNOE.js} +76 -122
  57. package/dist/safe-bash/command-chunks/{chunk-OT75C5YS.js → chunk-ZYXKW2K7.js} +1 -1
  58. package/dist/safe-bash/command-chunks/{pdf-renderer-346WYKSZ.js → pdf-renderer-5QWOVFA4.js} +1 -1
  59. package/dist/safe-bash/command-chunks/{prompt-tool-debug-3POFNRYP.js → prompt-tool-debug-G7ATE7D5.js} +6 -4
  60. package/dist/safe-bash/commands/llm/index.browser.js +5 -1
  61. package/dist/safe-bash/commands/llm/index.js +1 -1
  62. package/dist/safe-bash/commands/python/executor.browser.js +3 -1
  63. package/dist/safe-bash/commands/python/executor.js +1 -1
  64. package/dist/safe-bash/commands/python/index.browser.js +5 -1
  65. package/dist/safe-bash/commands/python/index.js +1 -1
  66. package/dist/safe-bash/core.browser.js +2 -2
  67. package/dist/safe-bash/full-core.browser.js +10 -2
  68. package/dist/safe-bash-command-awk/awk-runtime.js +2 -2
  69. package/dist/safe-bash-command-awk/awk-syntax.js +1 -1
  70. package/dist/safe-bash-command-awk/awk.js +3 -3
  71. package/dist/safe-bash-command-awk/index.js +3 -3
  72. package/dist/safe-bash-command-gpg/index.js +11 -3
  73. package/dist/safe-bash-command-imagemagick/index.js +2 -2
  74. package/dist/safe-bash-command-llm/collections.js +6 -4
  75. package/dist/safe-bash-command-llm/command.js +4 -4
  76. package/dist/safe-bash-command-llm/import-json-document.d.ts +9 -2
  77. package/dist/safe-bash-command-llm/index.d.ts +2 -1
  78. package/dist/safe-bash-command-llm/index.js +10 -4
  79. package/dist/safe-bash-command-llm/loader-provider.d.ts +5 -0
  80. package/dist/safe-bash-command-mcp/index.js +10 -13
  81. package/dist/safe-bash-command-pdftoppm/index.js +2 -2
  82. package/dist/safe-bash-command-playwright-cli/index.js +2 -2
  83. package/dist/safe-bash-command-playwright-cli/playwright/ability-execution.d.ts +1 -0
  84. package/dist/safe-bash-command-playwright-cli/playwright/ability-execution.js +1 -1
  85. package/dist/safe-bash-command-playwright-cli/playwright/controller.d.ts +2 -0
  86. package/dist/safe-bash-command-playwright-cli/playwright/controller.js +2 -2
  87. package/dist/safe-bash-command-playwright-cli/playwright/index.js +2 -2
  88. package/dist/safe-bash-command-python/build-backend.d.ts +2 -0
  89. package/dist/safe-bash-command-python/cache.d.ts +1 -1
  90. package/dist/safe-bash-command-python/executor.d.ts +5 -2
  91. package/dist/safe-bash-command-python/executor.js +11 -6
  92. package/dist/safe-bash-command-python/host-capabilities.js +1 -1
  93. package/dist/safe-bash-command-python/index.js +11 -6
  94. package/dist/safe-bash-command-python/jspi.js +5 -3
  95. package/dist/safe-bash-command-python/manifest-file.d.ts +44 -0
  96. package/dist/safe-bash-command-python/manifest.d.ts +45 -0
  97. package/dist/safe-bash-command-python/provisioning.d.ts +20 -1
  98. package/dist/safe-bash-command-python/provisioning.js +3 -2
  99. package/dist/safe-bash-command-python/reply.js +7 -11
  100. package/dist/safe-bash-command-python/source-archive.js +2 -2
  101. package/dist/safe-bash-command-python/source-zip.js +2 -2
  102. package/dist/safe-bash-command-python/worker.js +34 -21
  103. package/dist/safe-bash-command-sqlite3/engine.d.ts +4 -0
  104. package/dist/safe-bash-command-sqlite3/index.js +174 -18
  105. package/dist/safe-bash-command-svgo/index.js +1 -1
  106. package/dist/safe-bash-command-tar/create.js +3 -3
  107. package/dist/safe-bash-command-tar/extract.js +3 -3
  108. package/dist/safe-bash-command-tar/index.js +5 -5
  109. package/dist/safe-bash-command-tar/modes.js +5 -5
  110. package/dist/safe-bash-command-tar/options.d.ts +1 -1
  111. package/dist/safe-bash-command-tar/options.js +1 -1
  112. package/dist/safe-bash-command-tar/stream.js +1 -1
  113. package/dist/safe-bash-command-wkhtmltopdf/index.js +1 -1
  114. package/dist/safe-bash-command-xan/argv.js +1 -1
  115. package/dist/safe-bash-command-xan/commands.js +3 -3
  116. package/dist/safe-bash-command-xan/index.js +3 -3
  117. package/dist/safe-bash-command-xan/io.js +2 -2
  118. package/dist/safe-bash-compression-engine/bounded-codec.js +3 -3
  119. package/dist/safe-bash-compression-engine/codec-loader.js +2 -2
  120. package/dist/safe-bash-compression-engine/files.js +6 -6
  121. package/dist/safe-bash-compression-engine/index.js +5 -5
  122. package/dist/safe-bash-compression-engine/operand.js +6 -6
  123. package/dist/safe-bash-compression-engine/options.js +1 -1
  124. package/dist/safe-bash-compression-engine/stream.js +5 -5
  125. package/dist/safe-bash-compression-engine/zstd-decode.js +4 -4
  126. package/dist/safe-bash-contracts/filesystem-descriptor.js +1 -1
  127. package/dist/safe-bash-contracts/filesystem-output.js +1 -1
  128. package/dist/safe-bash-csv-engine/index.js +4 -4
  129. package/dist/safe-bash-csv-engine/python-codec-aliases.js +1 -1
  130. package/dist/safe-bash-csv-engine/python-codepages.js +2 -2
  131. package/dist/safe-bash-csv-engine/python-utf16.js +3 -3
  132. package/dist/safe-bash-csv-engine/text-decoder.js +4 -4
  133. package/dist/safe-bash-graphviz-engine/index.js +1 -1
  134. package/dist/safe-bash-pager-engine/index.js +2 -2
  135. package/dist/safe-bash-query-engine/capture.js +3 -3
  136. package/dist/safe-bash-query-engine/delpaths.js +3 -3
  137. package/dist/safe-bash-query-engine/formats.js +2 -2
  138. package/dist/safe-bash-query-engine/index.js +10 -10
  139. package/dist/safe-bash-query-engine/indices.js +3 -3
  140. package/dist/safe-bash-query-engine/input.d.ts +3 -3
  141. package/dist/safe-bash-query-engine/input.js +1 -1
  142. package/dist/safe-bash-query-engine/interpreter.js +9 -9
  143. package/dist/safe-bash-query-engine/query-core.js +10 -10
  144. package/dist/safe-bash-query-engine/regex.js +4 -4
  145. package/dist/safe-bash-query-engine/splits.js +5 -5
  146. package/dist/safe-bash-query-engine/values.js +2 -2
  147. package/package.json +2 -2
  148. package/dist/safe-bash/command-chunks/chunk-BKQWFABY.js +0 -960
  149. package/dist/safe-bash/command-chunks/chunk-DV7TCGJR.js +0 -691
  150. package/dist/safe-bash/command-chunks/chunk-ZERCTWUI.js +0 -467
@@ -1,691 +0,0 @@
1
- // packages/safe-bash-command-python/src/invocation.ts
2
- var PythonInvocationError = class extends Error {
3
- constructor(message) {
4
- super(message);
5
- this.name = "PythonInvocationError";
6
- }
7
- };
8
- function parsePythonInvocation(args, env) {
9
- const startupArgs = [];
10
- let informational = false;
11
- let module;
12
- scan: for (let index = 0; index < args.length; index++) {
13
- const option = args[index];
14
- if (option === "--" || option === "-" || !option.startsWith("-")) break;
15
- if (option === "--help") {
16
- informational = true;
17
- break;
18
- }
19
- if (option === "--version") {
20
- informational = true;
21
- continue;
22
- }
23
- if (option.startsWith("--")) throw new PythonInvocationError("unsupported option " + option);
24
- for (let offset = 1; offset < option.length; offset++) {
25
- const flag = option[offset];
26
- if (flag === "h" || flag === "?") {
27
- informational = true;
28
- break scan;
29
- }
30
- if (flag === "V") {
31
- informational = true;
32
- continue;
33
- }
34
- if ("cmWX".includes(flag)) {
35
- const operand = option.slice(offset + 1) || args[++index];
36
- if (operand === void 0) throw new PythonInvocationError("argument expected for -" + flag);
37
- if (flag === "m" && !informational) module = { name: operand, args: args.slice(index + 1) };
38
- if (flag === "c" || flag === "m") break scan;
39
- if (flag === "X") {
40
- const separator = operand.indexOf("=");
41
- const name = separator < 0 ? operand : operand.slice(0, separator);
42
- const value = separator < 0 ? void 0 : operand.slice(separator + 1);
43
- let decimal = value ?? "";
44
- while (decimal.length && " \n\r\v\f".includes(decimal[0])) decimal = decimal.slice(1);
45
- if (decimal[0] === "+" || decimal[0] === "-") decimal = decimal.slice(1);
46
- const digits = decimal.length > 0 && [...decimal].every((character) => character >= "0" && character <= "9");
47
- 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);
48
- if (!supported) throw new PythonInvocationError("unsupported -X option " + operand);
49
- startupArgs.push("-X", operand);
50
- }
51
- break;
52
- }
53
- if (!"BEPOusISbdvqR".includes(flag)) throw new PythonInvocationError("unsupported option -" + flag);
54
- startupArgs.push("-" + flag);
55
- }
56
- }
57
- if (!informational && !startupArgs.includes("-E") && !startupArgs.includes("-I")) {
58
- if (env.PYTHONINSPECT) throw new PythonInvocationError("PYTHONINSPECT requires an interactive terminal, which the shell does not expose");
59
- if (env.PYTHONHOME) throw new PythonInvocationError("PYTHONHOME cannot replace the configured Pyodide runtime");
60
- }
61
- const runtimeEnv = { ...env };
62
- delete runtimeEnv.PYTHONPATH;
63
- delete runtimeEnv.PYTHONHOME;
64
- delete runtimeEnv.PYTHONWARNINGS;
65
- runtimeEnv.PYTHONINSPECT = "";
66
- startupArgs.push("-c", "");
67
- return { startupArgs, env: runtimeEnv, module };
68
- }
69
-
70
- // packages/safe-bash-command-python/src/package-program.generated.ts
71
- var pythonPackageProgramGzip = "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";
72
-
73
- // packages/safe-bash-command-python/src/package-program.ts
74
- var decoded;
75
- function loadPythonPackageProgram() {
76
- return decoded ??= new Response(new Blob([Uint8Array.from(atob(pythonPackageProgramGzip), (character) => character.charCodeAt(0))]).stream().pipeThrough(new DecompressionStream("gzip"))).text();
77
- }
78
-
79
- // packages/safe-bash-command-python/src/native-wheel.generated.ts
80
- var pythonNativeWheelGzip = "H4sIAAAAAAACA60aXXPctvH9fsU2eSBZUbTs1p70amaaOHbHk9bOOE4zY42GA5HLIyISYAHQ0rnT/95ZfJDg3UmJM32RjuDuYrHfu+CmwRYqzVqs8M4oVptKMMM/YnXbIfapQtbkoFFx1vNP2GTbDfBhlMoAl8A0BHAuc/hFSxGv0XMOupsM7+N1t7KBVskBRma6nl8Hqj8w01nYNxaWHj3gJz62vMcA+IGPr+hxgf3Ax5yWX4tWRsv0GPbay4Y3M4lqZPUN22HVS9agill0K2u0om15QFWTqPRe1Ktj7UW92UDdMz1v/rOV4iKk4h27ff32W6aRJAlW+hUX3FRVqrFvc9D8k3sH9FzQY+5+jlJzw6WAEtzqxQx1y0Ujb/P4oZJtq9FACddJ4mBpN1Iou+7R7ub2UWgmJeC9mtADacSbXwUy2PfHACtOI3L+dI6pHG47FDWWFw6Xt34BhDTABaQXOTzO4Yl7DYpxjfAv1k/4Uimp0oSLj6znjUdLMgKL5OPPfmYJrVjKF7Fmlw77yrMw4z+Hi3jftz+6TZ88ySF57TdmajcNKIzb+lA/kQCCYA5kQnqINF6ePw5iHBgXXOyghIHdzfwTEJyvN3Jb04sywuOtW+Ma3kiBIJV7fg4XgL1GGLhInQHNSJbSl/Dih73ppIBRyWvUwAwMUht49mf4nn8LZ8CNhidPzq/3BuHl2xffQYfkJgW8NR15C9GopdDTgErDMGkDrK5xNKA78hpr/PboGrjQBlkDsiWYaZh6Zoh9BjbyFNHZFoafPX369CvLrJzMOFnr3htkSrF9atdvOwoKPYrUQWTw3JJxCuWttbATbvK8PFDi81NQZ5Zy9MIbKCj894TaYOPZffb06Z+eRao7P1YcIempN1Z53hgiM50pemDeQsc0M0alDi+HxHQoksDCQi4OSB7YE4k496LT9wIsAeTQp08KkuzsUDjw9XKMmcuVT83+FCzPRWSou0ncON8CbZg6YuP8mFML3KPYmS4ymvPIFvIjDs8tcbePAyrwzqBoYqhLC7S1f8/cBleetZXJnJV++8jtnYz9/psNfAnv0DAuwHQIIxcCG+DCoBoVGlQwMqUpFYkGFI49qxGk6PfW9ZDtUEHDFdZGqj0R65hoZNsW8L5D8IpA0UpVo7ZbaDYgNFj3TGEDKBrKWN8SU6/fpg0zLMuBi7qfGi52RHFgfSvVgM0joyZRM7LplmPf6AJeCqP2IK9/wdpo0Ib3PVxjL8UOjARndSExFz551lIYvDNRivcrAxP2PFEGXb/ZwN/ue2Hzpn83y6Nysku1nFTtcqjfkWlDp9Qj1iYHonSr2LgBkIrvuGA9Oc1cRBTVO2T939G8oF2F0RsAo5AiEdOmsLukgUjRYIPCpJ56sUPj9k8D7SwjWyEX9wSaaRjThVJCWoAS2rFwcYB/wqpusiQrrmWzv7ywtnY9tS2qeyi0I5TAZbHS6xqfiwbvoIRdL69Zr9OMOE0TV/rFJV9lIa3rkZRr1vepHFExF5b+yNROh1Tl443FOAaKvOBURHogork85RY9H72UN9MYb3KDe8eHjRU61BZQwuWVr41cMqCaxUUfCwnl0aFucB/QswVQF2wcKRTYJx8jfB6wnh6/4G20As/hq8d/ebK9VshunBhqqZooNFNpXFCRqdMkKX6R3KNqayxEzaP4LL51YfN73Lu4SYe3NQ/bE5XcenbpkegFWlct4yK4qCqBt1WVRmuWSCsVCDZgDh+pxKIC7ASffqtszqRcUw5nosbU4uXQ8NpkW0fEp5eCgkCHdw7kMrGLiQ+f2FMeoQhVlkB+gJXhAyYzCTONvaceAq6xBmOPl8dcZ/OpiwpFs2QvLkyKoonN0YJtwJfqFNU4amdLchKEZM2H7M6bgKvULJ4XgBfHoU7JNXV6mTrO/uPP6w5UkByy/56WnQX0lu8ONOvFKmSlR91Lo6sqdqFIIg5z1uXl7lho2ZVXgXWFxJ0y8ScsqM9yB9ABrXClnhdrlofzR3nQye6shMdBeFXVo/CdTbaNOwQLu4Bxg2qGsxTpBFI1NjhzAYqJnWtHHGq23VNOCmEh2aFJ8oCQLYR3aLjBYe6uAsRsxGEPqvnD77PygMlQ7lxQmbhgLEDePV9TIHQOGrMSzO5eZp0dvmGDt8LTvFu9bQ9o0WLi3wVUiuwLSk5rbOpNSYHEn9yofayPSwK8cj55Zwv2EGkClKcROjojFaWNAVOm6o5/xJVzeHFFRu6hrGX1nNKx97psG17R8d9LMvDLtRVeQTl7rGsnWR8IZltnwLSWOHMN9Gy5RtWBDalMa74T1LHdk0OtMiMe7lb7362zqVTNnIw9fpKQyX7iNHwgg8WPqDQ2qZbKoC8nl9Pf4L7s2XDdMIeydf8OvIyk6dbXIW152MDqxQkiSbKwPpvaO7xV3KA9/xvZ4HvFhLZlnwq5nXq00pcd9IskQf/t0XUcIj9yzU31jRVwsDvZBEvTHRsxlrl9N+cQW5Zwbe3FtqtU+XqcMtLaNupPHCsh0MzuRTvUctxXvaxtYo/V6wqdyG4do3dRmeTZDqzNTJAs4u2dbI62J+6PcJ38Yuwg0c9j31Z47gxLvevq/bQd3QxhXTTGp/E70MJaaa+kOtbYvWpZq9Dpx69Yq8jic3o7iY9p25nIBWfPWSfEA1dZlagYosbGr1tOKxsSbPY4MPf1voVUNr+WcElHuPoV+UeYJ6Rp2dyhQMXryopzNm3l3AvK2dGypYfwLwuHQou2Pm/nF86+/lDCY+qpw2qwm7B+WkVpAHc+ckjEK4WWvZ/bvPVuElR3+Zb8J6GncbRha+7pXv+w9J2+R02WzPWzNcQoda0nmrYfiiebfi4S1p1TLXOvGCHQvG9eFmZEB0Q+Ywi2xnQq9i1ZxObSm0UVz7LfuWsIbOMVGwktbMAFz5Ga+dIWyXNzWFSV78iqKr/Hwcuf/XT3MIaVy8/TblL6JJsfOUtJf4hTvMM6reUw8t6lg5bfVQPXmovd7AnamWkOyXOiszaHr5McEiKTZPlyUKJt7SSkDlq8TA5b68TmJFZ3dnLmQ6jtOz3AkuhJrEIK4qn3KG7i+NJdXNhObkDDrPLIGZq9oLFDw3UtPyJNLkYUy1SED8NkaMxNymJcBHpO4dbBqCpGYfp9AT92TKEdw3ifIIM4d7MZ64qU/k3HtS2p7dCmcPR+Egp7P0fpUUM6z1v8fEJDMyn7SCGw763MM7hBHIlbrkDeCrdL4bqcWjbOVUJpP1dhSZBAFaCS3Mo19JVzJTaG4OHPK9X8bpANUpBIVLKNrdkF7KART9Br7zASLUyWHuTy4spRq/J5p6qWg4uvR2XbsrTkguNaMY/H/otVRMcs7PXDevTqznPvAbYPnfco8G6jRspy7+eWv4V9KEMhnGa56wBS39gfbj17SRpE+38VYyQwe7Njq+Yv7VxxHlNa60QVZvwaQomsQdOcVxjOenIWChD2Js/6h0BstKU24HCNSnd8tO4ye6tNeX8FgZwuEhwCMNBYS9FAO/X9vNXiB6duBV/IYezR4Hdc6WX+p/fahiPTVYNspt4mjL0u3IO+jLGKysNUFcWmV0ybf9heK6f7QkUxiS54FlpFDBKvB/BozliFKjqaNtISqSUG02h3uUzrXudQ97qwmLTumvu61/aeLOY8j5jNrnwctRuug+i62nqgM4tdP133ZJYJN2Pi4sjC4lnL+uixRS9d749o7iseZs5twvVPVD+6XwsWJQzGhT5ol+eKPEKP7N5OQd3M5IT/+9vOuaElwAJFo2+56dLkUTK3469YrzGWFxP7NEy2nB3AGSSPkrXgVlwF6VkQj0OTH29GBxrIXEm5tyd8YHhNYXGZY58yvJChwyjQ2lxsisTFyjSdVIN50dKSgGLAMn5Yrspcu+T0PhvEbzZLV7/FlFdhcu0t/myVvx6yQyMKHYTa/xbZhX3ul93awD9DiIeMxm83m/hSpOW707Pj6MOMDZBRnv7uwJG4TKh8Ta6y+MrFi27rWpCErqJ2ipt9Ek+BHb4LHi6idkzTVxu0wvqdVNx0Qw54R3cgGA9Fw9YL4Ss3s8f6Rk8DlIFUIfA2nWlFd7luaL8tD1l2Fbm9aM3CeN8RLaaRZsnReJ6yfHjZ4V3Dd6hNmlGNE3i+70uDg4vJ+RwwcD0wU3dbSOAM1px7G0+++CLZgFfMfddVB8eaY/RSydkZ3z36cFlw4LWSIx+LOaN6PbkrnYZrU9FoiHaPtT9v0XC1UDvIqQef5Hzgo/sqB2Blch/4eHSWeK9PfPQRgJLkkgOJWHqKoTTCzI8Mai2dqyyDR5D88+X7b7775v03ySrUnBjQr8+y3omGiMRillkTq+iqb665ymQy7flXibunCXiGqZ314VNnChyHD6warpIrq+F45Vi/LtCtv0iifFX5Qmwlo7CJ44TkccxfMdwQis8nJWU38lkyDnljH1dI7jOtopoEGX/lreJQx/nBJs5zf49d8PZB8YXEl1xlhZ7alt/ZW6Pitut9l3IoK43G32kGY3mAaA4nzc0d6n7zC1dZh3vPOmKG2bbv9269UonraHUUXyOz8C9PKOizpHqKgQccac1ZtnngY8ITl83u+8ITLxx/2eZ/4PnXC6EoAAA=";
81
-
82
- // packages/safe-bash-command-python/src/native-wheel.ts
83
- var decoded2;
84
- function loadPythonNativeWheel() {
85
- return decoded2 ??= new Response(new Blob([Uint8Array.from(atob(pythonNativeWheelGzip), (character) => character.charCodeAt(0))]).stream().pipeThrough(new DecompressionStream("gzip"))).text();
86
- }
87
-
88
- // packages/safe-bash-command-python/src/package-url-hash.ts
89
- function pythonPackageUrlHash(url) {
90
- const match = /(sha1|sha224|sha384|sha256|sha512|md5)=([a-f0-9]+)/.exec(url);
91
- return match ? [match[1], match[2]] : void 0;
92
- }
93
-
94
- // packages/safe-bash-command-python/src/provisioning-runtime.ts
95
- async function installPythonPackages(supplied, start, request, maxTransferBytes) {
96
- if (!start.requirements.length && !start.uninstall && !start.bootstrap) return;
97
- const runtime = supplied;
98
- if (runtime.version !== "314.0.6" || !runtime._api?.packageManager || !runtime._api.lockfile_packages || typeof runtime._api.packageManager.installPackage !== "function" || typeof runtime.loadPackage !== "function" || typeof runtime.runPythonAsync !== "function") throw new Error("Python package installer ABI requires Pyodide 314.0.6");
99
- let transportFailure;
100
- let accepting = true;
101
- let pending = Promise.resolve();
102
- let installing = Promise.resolve();
103
- const manager = runtime._api.packageManager;
104
- const transfer = (consume) => {
105
- if (!accepting) return Promise.reject(new Error("Python package transport is only available during installation"));
106
- const work = pending.then(async () => {
107
- if (transportFailure) throw transportFailure.error;
108
- try {
109
- return await consume();
110
- } catch (error) {
111
- transportFailure ??= { error };
112
- throw error;
113
- }
114
- });
115
- pending = work.then(() => {
116
- }, () => {
117
- });
118
- return work;
119
- };
120
- const readArtifact = (operation, key, offset, length) => {
121
- const failed = (error) => {
122
- transportFailure ??= { error };
123
- throw error;
124
- };
125
- try {
126
- const result = request(operation, start.session, key, offset, Math.min(length, maxTransferBytes, 65536));
127
- return result instanceof Promise ? result.catch(failed) : result;
128
- } catch (error) {
129
- return failed(error);
130
- }
131
- };
132
- const withArtifact = (url, expected, metadata, consume) => transfer(async () => {
133
- const opened = await request("package-open", start.session, url, expected, ...metadata ? [metadata] : []);
134
- try {
135
- return await consume(opened, (offset, length) => readArtifact("package-read", opened.key, offset, length));
136
- } finally {
137
- await request("package-close", start.session, opened.key);
138
- }
139
- });
140
- const wheel = async (size, read, configuration) => {
141
- const globals = ["_safe_native_wheel_read", "_safe_native_wheel_config", "_safe_extract_native_wheel", "_safe_native_wheel_index"];
142
- let indexed = false;
143
- try {
144
- runtime.globals.set(globals[0], read);
145
- runtime.globals.set(globals[3], (operation, ...args) => {
146
- if (operation === "start") indexed = true;
147
- const failed = (error) => {
148
- transportFailure ??= { error };
149
- throw error;
150
- };
151
- try {
152
- const result2 = request("package-index", start.session, operation, ...args);
153
- return result2 instanceof Promise ? result2.catch(failed) : result2;
154
- } catch (error) {
155
- return failed(error);
156
- }
157
- });
158
- runtime.globals.set(globals[1], JSON.stringify({ ...configuration, size }));
159
- const result = JSON.parse(await runtime.runPythonAsync(await loadPythonNativeWheel()));
160
- if (Array.isArray(result)) for (const path of result) await runtime._api.loadDynlib(path);
161
- return result;
162
- } finally {
163
- try {
164
- if (indexed) await request("package-index", start.session, "close");
165
- } finally {
166
- for (const name of globals) runtime.globals.delete(name);
167
- }
168
- }
169
- };
170
- const fetch = (url, expected, metadata) => withArtifact(url, expected, metadata, async (opened, read) => {
171
- const bytes = new Uint8Array(opened.size);
172
- for (let offset = 0; offset < bytes.length; ) {
173
- const chunk = await read(offset, bytes.length - offset);
174
- if (!Array.isArray(chunk) || chunk.length === 0 || offset + chunk.length > bytes.length) throw new Error("Invalid Python package chunk");
175
- bytes.set(chunk, offset);
176
- offset += chunk.length;
177
- }
178
- return { bytes, headers: opened.headers };
179
- });
180
- manager.downloadPackage = async (metadata) => {
181
- if (!accepting) throw new Error("Python package transport is only available during installation");
182
- if (metadata.channel === manager.defaultChannel) {
183
- const pkg = runtime._api.lockfile_packages[metadata.normalizedName];
184
- if (!pkg) throw new Error(`Missing matching Pyodide package: ${metadata.normalizedName}`);
185
- return { url: new URL(pkg.file_name, "https://cdn.jsdelivr.net/pyodide/v314.0.6/full/").href, expected: pkg.sha256 };
186
- }
187
- return { url: metadata.channel };
188
- };
189
- manager.installPackage = (metadata, source) => {
190
- if (!accepting) return Promise.reject(new Error("Python package transport is only available during installation"));
191
- const work = installing.then(async () => {
192
- if (source instanceof Uint8Array) throw new Error("Expected retained Python package source");
193
- const pkg = runtime._api.lockfile_packages[metadata.normalizedName] ?? metadata.packageData;
194
- if (!pkg) throw new Error(`Missing matching Pyodide package: ${metadata.normalizedName}`);
195
- return withArtifact(source.url, source.expected, void 0, (opened, read) => wheel(opened.size, read, {
196
- filename: pkg.file_name,
197
- target: pkg.install_dir ?? null,
198
- metadata: { INSTALLER: "pyodide.loadPackage", PYODIDE_SOURCE: metadata.channel === manager.defaultChannel ? "pyodide" : metadata.channel }
199
- }));
200
- });
201
- installing = work.then(() => {
202
- }, () => {
203
- });
204
- return work;
205
- };
206
- const loadPackages = async (names) => {
207
- const errors = [];
208
- await runtime.loadPackage(names, { messageCallback() {
209
- }, errorCallback(message) {
210
- errors.push(message);
211
- } });
212
- if (errors.length) throw new Error(errors.join("\n"));
213
- };
214
- const installedGlobals = [];
215
- const bind = (name, value) => {
216
- runtime.globals.set(name, value);
217
- installedGlobals.push(name);
218
- };
219
- try {
220
- await loadPackages(["micropip", ...start.bootstrapPackages ?? []]);
221
- bind("_safe_package_native", loadPackages);
222
- bind("_safe_package_bytes", async (url, hash) => (await fetch(url, hash)).bytes);
223
- bind("_safe_package_metadata", async (url) => {
224
- const result = await fetch(url, void 0, "metadata");
225
- return JSON.stringify({ text: new TextDecoder().decode(result.bytes), headers: Object.fromEntries(result.headers.map(([name, value]) => [name.toLowerCase(), value])) });
226
- });
227
- bind("_safe_package_wheel_download", async (url, expected) => withArtifact(url, expected, void 0, async (opened, read) => {
228
- const hash = pythonPackageUrlHash(url);
229
- if (hash) await wheel(opened.size, read, { integrity: hash });
230
- return JSON.stringify(await request("package-retain", start.session, opened.key));
231
- }));
232
- bind("_safe_package_wheel_metadata", async (serialized) => transfer(async () => {
233
- const { source, name } = JSON.parse(serialized);
234
- return wheel(source.size, (offset, length) => readArtifact("package-read-retained", source.token, offset, length), { metadata_name: name });
235
- }));
236
- bind("_safe_package_wheel_install", async (serialized) => transfer(async () => {
237
- const { source, ...configuration } = JSON.parse(serialized);
238
- await wheel(source.size, (offset, length) => readArtifact("package-read-retained", source.token, offset, length), configuration);
239
- }));
240
- bind("_safe_package_requirements_json", JSON.stringify(start.requested ?? start.requirements));
241
- for (const key of ["pre", "upgrade", "forceReinstall", "legacy"]) {
242
- bind("_safe_package_" + key, !!start[key]);
243
- }
244
- bind("_safe_package_restore_json", JSON.stringify(start.restore ?? []));
245
- bind("_safe_package_records_json", JSON.stringify(start.records ?? null));
246
- bind("_safe_package_uninstall_json", JSON.stringify(start.uninstall ?? null));
247
- bind("_safe_package_emit", async (stream, message) => {
248
- if (stream !== "stdout" && stream !== "stderr") throw new Error("Invalid package output stream");
249
- const bytes = new TextEncoder().encode(message);
250
- for (let offset = 0; offset < bytes.length; offset += maxTransferBytes) await request(stream, Array.from(bytes.subarray(offset, offset + maxTransferBytes)));
251
- });
252
- bind("_safe_package_line", async () => {
253
- const bytes = [];
254
- while (true) {
255
- const chunk = await request("stdin", 1);
256
- if (!chunk.length) {
257
- if (!bytes.length) throw new Error("EOF when reading package confirmation");
258
- break;
259
- }
260
- if (chunk[0] === 10) break;
261
- bytes.push(chunk[0]);
262
- }
263
- return new TextDecoder().decode(Uint8Array.from(bytes));
264
- });
265
- await runtime.runPythonAsync(await loadPythonPackageProgram());
266
- await installing;
267
- accepting = false;
268
- await pending;
269
- if (transportFailure) throw transportFailure.error;
270
- const pinned = JSON.parse(runtime.runPython("_safe_installed_json"));
271
- await request("package-commit", start.session, start.restore === void 0 ? pinned : { version: 3, installed: pinned, records: JSON.parse(runtime.runPython("_safe_records_json")) });
272
- if (start.uninstall) {
273
- const removed = JSON.parse(runtime.runPython("_safe_uninstalled_json"));
274
- for (const name of removed) {
275
- const bytes = new TextEncoder().encode(" Successfully uninstalled " + name + "\n");
276
- for (let offset = 0; offset < bytes.length; offset += maxTransferBytes) await request("stdout", Array.from(bytes.subarray(offset, offset + maxTransferBytes)));
277
- }
278
- }
279
- } catch (error) {
280
- await installing;
281
- accepting = false;
282
- await pending;
283
- throw transportFailure ? transportFailure.error : error;
284
- } finally {
285
- await installing;
286
- accepting = false;
287
- await pending;
288
- manager.downloadPackage = manager.installPackage = async () => {
289
- throw new Error("Python package transport is only available during installation");
290
- };
291
- for (const name of installedGlobals) runtime.globals.delete(name);
292
- }
293
- }
294
-
295
- // packages/safe-bash-command-python/src/execution.ts
296
- var pythonExecution = `
297
- import sys, os, json, runpy, traceback, types, warnings, textwrap, io, struct, linecache
298
- _safe_invocation = json.loads(_safe_invocation_json)
299
- os.environ.clear()
300
- os.environ.update(_safe_invocation['env'])
301
- _safe_args = list(_safe_invocation['args'])
302
- sys.orig_argv = [_safe_invocation.get('command', 'python')] + _safe_args
303
- _safe_exit = 0
304
-
305
- class _SafeOptionError(ValueError):
306
- pass
307
-
308
- def _safe_system_exit(_error):
309
- if isinstance(_error.code, int):
310
- _status = int.__index__(_error.code)
311
- _long_bound = 1 << (8 * struct.calcsize('@l') - 1)
312
- status = (_status & 255) if -_long_bound <= _status < _long_bound else 255
313
- else:
314
- status = 0 if _error.code is None else 1
315
- if _error.code is not None and not isinstance(_error.code, int):
316
- print(_error.code, file=sys.stderr)
317
- return status
318
-
319
- def _safe_launch():
320
- args = list(_safe_args)
321
- unbuffered = False
322
- ignore_env = bool(sys.flags.ignore_environment)
323
- safe_path = bool(sys.flags.safe_path)
324
- native_warning_options = list(sys.warnoptions)
325
- # Pyodide adds a bootstrap cwd entry even when CPython safe-path mode is set.
326
- # Each execution mode below supplies its own entry after explicit PYTHONPATH.
327
- sys.path[:] = [entry for entry in sys.path if entry != '']
328
- warning_options = []
329
- version_count = 0
330
- options_terminated = False
331
- while args and args[0].startswith('-') and args[0] != '-':
332
- option = args.pop(0)
333
- if option == '--':
334
- options_terminated = True
335
- break
336
- if option in ('--help', '-h', '-?'):
337
- print('usage: python [-uBEPOsSIbdvqR] [-W filter] [-X option] [-c code | -m module | file | -] [args ...]')
338
- print('Dedicated Pyodide interpreter; stdin is noninteractive.')
339
- print('-u: unbuffered binary output; -B: disable bytecode writes; -E: ignore PYTHON* settings')
340
- print('-P: omit automatic unsafe sys.path entry; -W: Python warning filter')
341
- print('-O/-OO, -S/-s/-I, -b/-bb, -d/-v/-q/-R: CPython startup flags')
342
- print('-X: utf8, dev, warn_default_encoding, int_max_str_digits; interactive flags are unsupported.')
343
- return
344
- if option == '--version':
345
- version_count += 1
346
- continue
347
- if option.startswith('--'):
348
- raise _SafeOptionError('unsupported option ' + option)
349
- index = 1
350
- while index < len(option):
351
- flag = option[index]
352
- if flag in ('h', '?'):
353
- args = ['--help']
354
- break
355
- if flag == 'V':
356
- version_count += 1
357
- index += 1
358
- continue
359
- if flag in ('c', 'm', 'W', 'X'):
360
- operand = option[index + 1:] if index + 1 < len(option) else args.pop(0) if args else None
361
- if operand is None:
362
- raise _SafeOptionError('argument expected for -' + flag)
363
- if flag in ('W', 'X'):
364
- if flag == 'W': warning_options.append(operand)
365
- break
366
- args = ['-' + flag, operand] + args
367
- break
368
- elif flag in ('O', 'S', 's', 'I', 'b', 'd', 'v', 'q', 'R'):
369
- pass # Applied by CPython startup configuration before bootstrap.
370
- elif flag == 'u':
371
- unbuffered = True
372
- elif flag == 'B':
373
- sys.dont_write_bytecode = True
374
- elif flag == 'E':
375
- ignore_env = True
376
- elif flag == 'P':
377
- safe_path = True
378
- else:
379
- raise _SafeOptionError('unsupported option -' + flag)
380
- index += 1
381
- if args and args[0] in ('-c', '-m'):
382
- break
383
- if version_count:
384
- print('Python ' + (sys.version if version_count > 1 else sys.version.split()[0]))
385
- return
386
- if not ignore_env:
387
- unbuffered = unbuffered or bool(os.environ.get('PYTHONUNBUFFERED'))
388
- sys.dont_write_bytecode = sys.dont_write_bytecode or bool(os.environ.get('PYTHONDONTWRITEBYTECODE'))
389
- safe_path = safe_path or bool(os.environ.get('PYTHONSAFEPATH'))
390
- path = os.environ.get('PYTHONPATH')
391
- if path:
392
- sys.path[0:0] = [os.path.abspath(entry) for entry in path.split(os.pathsep)]
393
- if os.environ.get('PYTHONWARNINGS'):
394
- warning_options[0:0] = os.environ['PYTHONWARNINGS'].split(',')
395
- encoding = os.environ.get('PYTHONIOENCODING')
396
- if encoding:
397
- name, separator, errors = encoding.partition(':')
398
- for stream in (sys.stdin, sys.stdout):
399
- stream.reconfigure(encoding=name or None, errors=(errors or 'strict'))
400
- sys.stderr.reconfigure(encoding=name or None, errors='backslashreplace')
401
- # CPython's -b/-bb filter follows environment and command-line -W filters.
402
- byte_warning = ('error' if sys.flags.bytes_warning > 1 else 'default') + '::BytesWarning'
403
- native_before = [value for value in native_warning_options if not (sys.flags.bytes_warning and value == byte_warning)]
404
- warning_options = native_before + warning_options + ([byte_warning] if sys.flags.bytes_warning else [])
405
- warnings._processoptions(warning_options)
406
- sys.warnoptions[:] = warning_options
407
- if unbuffered:
408
- for name in ('stdout', 'stderr'):
409
- stream = getattr(sys, name)
410
- stream.flush()
411
- encoding, errors = stream.encoding, stream.errors
412
- binary = stream.detach()
413
- raw = binary.detach() if hasattr(binary, 'detach') else binary
414
- replacement = io.TextIOWrapper(raw, encoding=encoding, errors=errors, write_through=True)
415
- setattr(sys, name, replacement)
416
- setattr(sys, '__' + name + '__', replacement)
417
- main = types.ModuleType('__main__')
418
- main.__dict__.update(__package__=None, __spec__=None, __loader__=__import__('importlib.machinery', fromlist=['BuiltinImporter']).BuiltinImporter, __builtins__=__builtins__)
419
- sys.modules['__main__'] = main
420
- if not sys.flags.no_site:
421
- sys.argv = [args[0]] + args[2:] if not options_terminated and args and args[0] in ('-c', '-m') else args or ['']
422
- import site
423
- site.addsitepackages(site.addusersitepackages(None), [_safe_runtime_mount])
424
- if not options_terminated and args and args[0] == '-c':
425
- sys.argv = ['-c'] + args[2:]
426
- if not safe_path: sys.path.insert(0, '')
427
- source = textwrap.dedent(args[1])
428
- code = compile(source, '<string>', 'exec')
429
- # CPython 3.14 retains -c source for both top-level and nested tracebacks.
430
- linecache._register_code(code, source, '<string>')
431
- exec(code, main.__dict__)
432
- elif not options_terminated and args and args[0] == '-m':
433
- sys.argv = args[1:]
434
- if not safe_path: sys.path.insert(0, os.getcwd())
435
- runpy._run_module_as_main(args[1], alter_argv=True)
436
- elif not args or args[0] == '-':
437
- sys.argv = (['-'] + args[1:]) if args else ['']
438
- if not safe_path: sys.path.insert(0, '')
439
- main.__file__ = '<stdin>'
440
- exec(compile(sys.stdin.buffer.read(), '<stdin>', 'exec'), main.__dict__)
441
- else:
442
- sys.argv = args
443
- # CPython makes __file__ absolute without collapsing ./ or ../ components.
444
- path = args[0] if os.path.isabs(args[0]) else os.path.join(os.getcwd(), args[0])
445
- importer = __import__('pkgutil').get_importer(path)
446
- if importer is not None:
447
- sys.path.insert(0, path)
448
- runpy._run_module_as_main('__main__', alter_argv=False)
449
- else:
450
- if not safe_path: sys.path.insert(0, os.path.dirname(os.path.realpath(path)))
451
- try:
452
- with open(path, 'rb') as source:
453
- code = source.read()
454
- except OSError as error:
455
- print("python: can't open file " + repr(path) + ': [Errno ' + str(error.errno) + '] ' + error.strerror, file=sys.stderr)
456
- return 2
457
- main.__file__ = path
458
- main.__loader__ = __import__('importlib.machinery', fromlist=['SourceFileLoader']).SourceFileLoader('__main__', path)
459
- exec(compile(code, path, 'exec'), main.__dict__)
460
- return 0
461
-
462
- try:
463
- _safe_exit = _safe_launch() or 0
464
- except SystemExit as _error:
465
- _safe_exit = _safe_system_exit(_error)
466
- except _SafeOptionError as _error:
467
- print('python: ' + str(_error), file=sys.stderr)
468
- _safe_exit = 2
469
- except BaseException as _error:
470
- # Hide bridge frames while preserving actual Python frames and chained errors.
471
- _trace = _error.__traceback__
472
- while _trace is not None and _trace.tb_frame.f_code.co_filename == '<exec>':
473
- _trace = _trace.tb_next
474
- _error.__traceback__ = _trace
475
- sys.last_exc = _error
476
- _safe_exit = 130 if isinstance(_error, KeyboardInterrupt) else 1
477
- try:
478
- sys.excepthook(type(_error), _error, _trace)
479
- except SystemExit as _hook_error:
480
- _safe_exit = _safe_system_exit(_hook_error)
481
- except BaseException as _hook_error:
482
- print('Error in sys.excepthook:', file=sys.stderr)
483
- traceback.print_exception(type(_hook_error), _hook_error, _hook_error.__traceback__.tb_next)
484
- print('\\nOriginal exception was:', file=sys.stderr)
485
- sys.__excepthook__(type(_error), _error, _trace)
486
- finally:
487
- for _stream in (sys.stdout, sys.stderr):
488
- if _stream is not None and not getattr(_stream, 'closed', False):
489
- try:
490
- _stream.flush()
491
- except BaseException:
492
- _safe_exit = 120
493
- _safe_exit
494
- `;
495
-
496
- // packages/safe-bash-command-python/src/runtime-scripts.ts
497
- var pythonRuntimeRelocation = `
498
- import sys, zipimport, importlib.machinery
499
-
500
- def _rebase_runtime_path(value):
501
- return _safe_runtime_mount + value if isinstance(value, str) and (value == '/lib' or value.startswith('/lib/')) else value
502
-
503
- def _rebase_runtime_loader(loader):
504
- if isinstance(loader, zipimport.zipimporter):
505
- archive = _rebase_runtime_path(loader.archive)
506
- if archive != loader.archive:
507
- return zipimport.zipimporter(archive + '/' + loader.prefix)
508
- elif isinstance(loader, (importlib.machinery.SourceFileLoader, importlib.machinery.SourcelessFileLoader, importlib.machinery.ExtensionFileLoader)):
509
- path = _rebase_runtime_path(loader.path)
510
- if path != loader.path:
511
- return type(loader)(loader.name, path)
512
- return loader
513
- sys.path[:] = [_rebase_runtime_path(value) for value in sys.path]
514
- for _module in list(sys.modules.values()):
515
- if _module is None:
516
- continue
517
- for _attribute in ('__file__', '__cached__'):
518
- if hasattr(_module, _attribute):
519
- setattr(_module, _attribute, _rebase_runtime_path(getattr(_module, _attribute)))
520
- if hasattr(_module, '__path__'):
521
- _module.__path__ = [_rebase_runtime_path(value) for value in _module.__path__]
522
- if hasattr(_module, '__loader__'):
523
- _module.__loader__ = _rebase_runtime_loader(_module.__loader__)
524
- _spec = getattr(_module, '__spec__', None)
525
- if _spec is not None:
526
- _spec.origin = _rebase_runtime_path(_spec.origin)
527
- _spec.loader = _rebase_runtime_loader(_spec.loader)
528
- if _spec.submodule_search_locations is not None:
529
- _spec.submodule_search_locations = [_rebase_runtime_path(value) for value in _spec.submodule_search_locations]
530
- sys.path_importer_cache.clear()
531
- `;
532
- var pythonImportMetadata = `
533
- import importlib._bootstrap_external, types, json
534
- _safe_import_stat_callback = _safe_import_stat
535
- _safe_original_import_stat = importlib._bootstrap_external._path_stat
536
- def _safe_import_path_stat(path):
537
- if path == _safe_runtime_mount or path.startswith(_safe_runtime_mount + '/'):
538
- return _safe_original_import_stat(path)
539
- value = json.loads(_safe_import_stat_callback(path))
540
- if 'errno' in value:
541
- raise OSError(value['errno'], 'filesystem import metadata unavailable', path)
542
- return types.SimpleNamespace(st_mode=value['mode'], st_size=value['size'], st_mtime=value['mtimeMs'] / 1000)
543
- importlib._bootstrap_external._path_stat = _safe_import_path_stat
544
- `;
545
- var pythonDirectoryEntries = `
546
- import os, json, errno
547
- _safe_directory_callback = _safe_directory_entries
548
- def _safe_listdir(path='.'):
549
- if isinstance(path, int):
550
- raise OSError(errno.ENOTSUP, 'retained directory descriptors are unsupported')
551
- original = os.fspath(path) if path is not None else '.'
552
- value = json.loads(_safe_directory_callback(os.fsdecode(original)))
553
- if 'errno' in value:
554
- raise OSError(value['errno'], 'directory enumeration failed', path)
555
- return [os.fsencode(name) for name in value['entries']] if isinstance(original, bytes) else value['entries']
556
- os.listdir = _safe_listdir
557
- # The frozen importer holds the posix module separately from os.
558
- importlib._bootstrap_external._os.listdir = _safe_listdir
559
- `;
560
- var pythonStatProjection = `
561
- import os, json, errno
562
- _safe_stat_callback = _safe_stat_projection
563
- _safe_stat_type = os.stat_result
564
- _safe_fspath = os.fspath
565
- _safe_fsdecode = os.fsdecode
566
-
567
- def _safe_stat(path, *, dir_fd=None, follow_symlinks=True):
568
- if dir_fd is not None:
569
- raise OSError(errno.ENOTSUP, 'dir_fd metadata is unsupported')
570
- if isinstance(path, int):
571
- if not follow_symlinks:
572
- raise ValueError('stat: cannot use fd and follow_symlinks together')
573
- else:
574
- path = _safe_fsdecode(_safe_fspath(path))
575
- value = json.loads(_safe_stat_callback(path, follow_symlinks))
576
- if 'errno' in value:
577
- raise OSError(value['errno'], 'filesystem metadata unavailable', path)
578
- keys = ('mode','ino','dev','nlink','uid','gid','size')
579
- if any(key not in value for key in keys):
580
- raise OSError(errno.EOVERFLOW, 'canonical identity or required stat metadata unavailable', path)
581
- times = [value[key] / 1000 for key in ('atimeMs','mtimeMs','ctimeMs')]
582
- extras = dict(zip(('st_atime','st_mtime','st_ctime'), times))
583
- for name, milliseconds in zip(('atime','mtime','ctime'), (value['atimeMs'],value['mtimeMs'],value['ctimeMs'])):
584
- seconds = int(milliseconds // 1000)
585
- extras['st_' + name + '_ns'] = seconds * 1000000000 + round((milliseconds - seconds * 1000) * 1000000)
586
- for key in ('blocks','blksize','rdev'):
587
- if key in value:
588
- extras['st_' + key] = value[key]
589
- return _safe_stat_type(tuple(value[key] for key in keys) + tuple(int(time // 1) for time in times), extras)
590
-
591
- def _safe_lstat(path, *, dir_fd=None):
592
- return _safe_stat(path, dir_fd=dir_fd, follow_symlinks=False)
593
-
594
- def _safe_fstat(fd):
595
- if not isinstance(fd, int):
596
- raise TypeError('file descriptor must be an integer')
597
- return _safe_stat(fd)
598
- os.stat = _safe_stat
599
- os.lstat = _safe_lstat
600
- os.fstat = _safe_fstat
601
- import stat as _safe_stat_module
602
- class _SafeDirEntry:
603
- def __init__(self, root, name):
604
- self.name = name
605
- self.path = os.path.join(root, name)
606
- self._cache = {}
607
- def __fspath__(self):
608
- return self.path
609
- def stat(self, *, follow_symlinks=True):
610
- if follow_symlinks not in self._cache:
611
- self._cache[follow_symlinks] = os.stat(self.path, follow_symlinks=follow_symlinks)
612
- return self._cache[follow_symlinks]
613
- def inode(self):
614
- return self.stat(follow_symlinks=False).st_ino
615
- def is_dir(self, *, follow_symlinks=True):
616
- try:
617
- return _safe_stat_module.S_ISDIR(self.stat(follow_symlinks=follow_symlinks).st_mode)
618
- except FileNotFoundError:
619
- return False
620
- def is_file(self, *, follow_symlinks=True):
621
- try:
622
- return _safe_stat_module.S_ISREG(self.stat(follow_symlinks=follow_symlinks).st_mode)
623
- except FileNotFoundError:
624
- return False
625
- def is_symlink(self):
626
- try:
627
- return _safe_stat_module.S_ISLNK(self.stat(follow_symlinks=False).st_mode)
628
- except FileNotFoundError:
629
- return False
630
- class _SafeScandir:
631
- def __init__(self, path):
632
- self._entries = iter([_SafeDirEntry(path, name) for name in os.listdir(path)])
633
- def __iter__(self):
634
- return self
635
- def __next__(self):
636
- return next(self._entries)
637
- def close(self):
638
- self._entries = iter(())
639
- def __enter__(self):
640
- return self
641
- def __exit__(self, *args):
642
- self.close()
643
- def _safe_scandir(path='.'):
644
- if isinstance(path, int):
645
- raise OSError(errno.ENOTSUP, 'retained directory descriptors are unsupported')
646
- return _SafeScandir(os.fspath(path) if path is not None else '.')
647
- os.scandir = _safe_scandir
648
-
649
- `;
650
- var pythonHardLinks = `
651
- import os, json, errno
652
- _safe_link_callback = _safe_hard_link
653
- def _safe_link(src, dst, *, src_dir_fd=None, dst_dir_fd=None, follow_symlinks=True):
654
- if src_dir_fd is not None or dst_dir_fd is not None:
655
- raise OSError(errno.ENOTSUP, 'dir_fd hard links are unsupported')
656
- source = os.fsdecode(os.fspath(src))
657
- destination = os.fsdecode(os.fspath(dst))
658
- value = json.loads(_safe_link_callback(source, destination, bool(follow_symlinks)))
659
- if 'errno' in value:
660
- raise OSError(value['errno'], 'hard link creation failed', src, None, dst)
661
- os.link = _safe_link
662
- os.supports_follow_symlinks.add(_safe_link)
663
- `;
664
- var pythonTreeCleanup = `
665
- import shutil, os, json
666
- _safe_tree_callback = _safe_tree_cleanup
667
- _safe_original_rmtree_impl = shutil._rmtree_impl
668
- def _safe_rmtree_impl(path, dir_fd, onexc):
669
- if dir_fd is not None:
670
- return _safe_original_rmtree_impl(path, dir_fd, onexc)
671
- value = json.loads(_safe_tree_callback(os.fsdecode(path)))
672
- if not value['supported']:
673
- return _safe_original_rmtree_impl(path, dir_fd, onexc)
674
- if 'errno' in value:
675
- onexc(os.rmdir, path, OSError(value['errno'], 'directory cleanup failed', path))
676
- shutil._rmtree_impl = _safe_rmtree_impl
677
- `;
678
-
679
- export {
680
- PythonInvocationError,
681
- parsePythonInvocation,
682
- pythonPackageUrlHash,
683
- installPythonPackages,
684
- pythonExecution,
685
- pythonRuntimeRelocation,
686
- pythonImportMetadata,
687
- pythonDirectoryEntries,
688
- pythonStatProjection,
689
- pythonHardLinks,
690
- pythonTreeCleanup
691
- };