@poe-platform/safe-bash 0.1.823 → 0.1.824

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 (220) hide show
  1. package/dist/safe-bash/command-chunks/{chunk-LDR3PPM3.js → chunk-22QEL76N.js} +3 -3
  2. package/dist/safe-bash/command-chunks/{chunk-BSLXS4PE.js → chunk-3DH5QBZC.js} +1 -1
  3. package/dist/safe-bash/command-chunks/{chunk-64HIOP7Q.js → chunk-3EBQOZET.js} +33 -353
  4. package/dist/safe-bash/command-chunks/{chunk-KQE2D7PX.js → chunk-3HUCLYKJ.js} +2 -2
  5. package/dist/safe-bash/command-chunks/{chunk-J4I7KCQQ.js → chunk-4JABZEDO.js} +4 -4
  6. package/dist/safe-bash/command-chunks/{chunk-PVKSBXHB.js → chunk-4M6D4IUB.js} +4 -4
  7. package/dist/safe-bash/command-chunks/{chunk-UVM6QG2H.js → chunk-4MVQE6CT.js} +1 -1
  8. package/dist/safe-bash/command-chunks/{chunk-QWQHLMDX.js → chunk-4VTB4DGE.js} +3 -3
  9. package/dist/safe-bash/command-chunks/{chunk-JQPDVCBU.js → chunk-565AAQTV.js} +3 -3
  10. package/dist/safe-bash/command-chunks/{chunk-JSW6YH6T.js → chunk-5PRXCH54.js} +5 -5
  11. package/dist/safe-bash/command-chunks/{chunk-42OQIFPW.js → chunk-5RLK2QSY.js} +3 -3
  12. package/dist/safe-bash/command-chunks/{chunk-PYYAX5FB.js → chunk-63WEGFLL.js} +16 -16
  13. package/dist/safe-bash/command-chunks/{chunk-5QR4LTAK.js → chunk-6KZXFPOT.js} +6 -6
  14. package/dist/safe-bash/command-chunks/{chunk-LJLB7TBN.js → chunk-6YTXU3NF.js} +6 -6
  15. package/dist/safe-bash/command-chunks/{chunk-NNYOPI7K.js → chunk-7NF44M2V.js} +5 -5
  16. package/dist/safe-bash/command-chunks/{chunk-ZRHKXN6W.js → chunk-7RQGRFHJ.js} +2 -2
  17. package/dist/safe-bash/command-chunks/{chunk-QGSY4ZAU.js → chunk-7UYBNOOM.js} +2 -2
  18. package/dist/safe-bash/command-chunks/{chunk-6REH56FL.js → chunk-AA254KE5.js} +4 -4
  19. package/dist/safe-bash/command-chunks/{chunk-2VSNIHIW.js → chunk-APUXNXXQ.js} +11 -11
  20. package/dist/safe-bash/command-chunks/{chunk-XE75H5ZZ.js → chunk-AVXSR5MO.js} +6 -6
  21. package/dist/safe-bash/command-chunks/{chunk-22D6Q6SW.js → chunk-BKCVCMUX.js} +2 -2
  22. package/dist/safe-bash/command-chunks/{chunk-UDRJKA3P.js → chunk-C23L4HZB.js} +2 -2
  23. package/dist/safe-bash/command-chunks/{chunk-PAEAEFK3.js → chunk-C3EEMMQL.js} +3 -3
  24. package/dist/safe-bash/command-chunks/{chunk-NDJPULBE.js → chunk-CEKBIZGU.js} +2 -2
  25. package/dist/safe-bash/command-chunks/{chunk-75OUKYCM.js → chunk-CH5JDE3C.js} +1 -1
  26. package/dist/safe-bash/command-chunks/{chunk-XNVL6AOV.js → chunk-CIYGC7WU.js} +6 -6
  27. package/dist/safe-bash/command-chunks/{chunk-RUXY7GN5.js → chunk-CMJBRGU2.js} +1 -1
  28. package/dist/safe-bash/command-chunks/{chunk-DGFMOT4O.js → chunk-CO4HYNPS.js} +1 -1
  29. package/dist/safe-bash/command-chunks/{chunk-TMJG745A.js → chunk-CQLZM75U.js} +3 -3
  30. package/dist/safe-bash/command-chunks/{chunk-T2LZWXWF.js → chunk-DBCTHLB5.js} +4 -4
  31. package/dist/safe-bash/command-chunks/{chunk-6RE4MZYM.js → chunk-DBEJMI7J.js} +1 -1
  32. package/dist/safe-bash/command-chunks/{chunk-XXUMECE4.js → chunk-DEEZYCOQ.js} +6 -6
  33. package/dist/safe-bash/command-chunks/{chunk-YJMS5Q4Y.js → chunk-DHTTI7CE.js} +8 -8
  34. package/dist/safe-bash/command-chunks/{chunk-D3WMD32B.js → chunk-DLLGOC4Q.js} +6 -6
  35. package/dist/safe-bash/command-chunks/{chunk-HVLF3Y4B.js → chunk-DYCYAIET.js} +5 -5
  36. package/dist/safe-bash/command-chunks/{chunk-5NC2IQMQ.js → chunk-EV7A5FNN.js} +1 -1
  37. package/dist/safe-bash/command-chunks/{chunk-2YC6MWQB.js → chunk-EY3UE26F.js} +1 -1
  38. package/dist/safe-bash/command-chunks/{chunk-ZQ4NQ24M.js → chunk-FJLVISSD.js} +4 -4
  39. package/dist/safe-bash/command-chunks/{chunk-WOO3YO2X.js → chunk-HTMGN3KL.js} +4 -4
  40. package/dist/safe-bash/command-chunks/{chunk-2E53ZL5D.js → chunk-HU72CZBN.js} +4 -4
  41. package/dist/safe-bash/command-chunks/{chunk-AH3ZEPAN.js → chunk-IGHFIRXK.js} +1 -1
  42. package/dist/safe-bash/command-chunks/{chunk-WDTWJFPK.js → chunk-IKBTII7C.js} +35 -73
  43. package/dist/safe-bash/command-chunks/{chunk-J3ISXTYB.js → chunk-JTEAYB72.js} +2 -2
  44. package/dist/safe-bash/command-chunks/{chunk-NR7POLKP.js → chunk-KCS25XUJ.js} +2 -2
  45. package/dist/safe-bash/command-chunks/chunk-LKAFLJ5L.js +123 -0
  46. package/dist/safe-bash/command-chunks/{chunk-EU5SR3LS.js → chunk-LSH6UKCT.js} +2 -2
  47. package/dist/safe-bash/command-chunks/{chunk-WV3C6BRD.js → chunk-MHZ7UTRX.js} +5 -5
  48. package/dist/safe-bash/command-chunks/{chunk-K6J3KFQ2.js → chunk-MSA5BQFK.js} +3 -3
  49. package/dist/safe-bash/command-chunks/{chunk-OMD45J52.js → chunk-MW3L6JB7.js} +6 -6
  50. package/dist/safe-bash/command-chunks/{chunk-AR65HNNX.js → chunk-N2TN7IBE.js} +1 -1
  51. package/dist/safe-bash/command-chunks/{chunk-EO3RYGUZ.js → chunk-NNGWTDVJ.js} +476 -75
  52. package/dist/safe-bash/command-chunks/{chunk-NWA7ZJDV.js → chunk-NU64GWGN.js} +3 -3
  53. package/dist/safe-bash/command-chunks/{chunk-RGKHTSUY.js → chunk-NW3S6T6R.js} +1 -1
  54. package/dist/safe-bash/command-chunks/chunk-NXCJNPL3.js +47 -0
  55. package/dist/safe-bash/command-chunks/{chunk-GAYTDZPP.js → chunk-ORWYNKKL.js} +3 -3
  56. package/dist/safe-bash/command-chunks/{chunk-FCGMSOF6.js → chunk-P6YTNXRV.js} +1 -1
  57. package/dist/safe-bash/command-chunks/{chunk-3RDEX4AF.js → chunk-PAS4YSNN.js} +1 -1
  58. package/dist/safe-bash/command-chunks/{chunk-TTPT3OME.js → chunk-PSNTCRL5.js} +4 -4
  59. package/dist/safe-bash/command-chunks/{chunk-FGK6HLSY.js → chunk-QC2RWSYM.js} +3 -3
  60. package/dist/safe-bash/command-chunks/{chunk-HCZITM4C.js → chunk-QPY3NCMC.js} +5 -5
  61. package/dist/safe-bash/command-chunks/{chunk-3TXPZLFI.js → chunk-R6RVR6ZZ.js} +5 -5
  62. package/dist/safe-bash/command-chunks/{chunk-HQFX5XKV.js → chunk-RB7XAYO2.js} +3 -3
  63. package/dist/safe-bash/command-chunks/{chunk-6PDXNY3T.js → chunk-RF5VEKFU.js} +9 -9
  64. package/dist/safe-bash/command-chunks/{chunk-VAMBWXDV.js → chunk-RUAGHZNF.js} +18 -18
  65. package/dist/safe-bash/command-chunks/{chunk-3MFYCMQU.js → chunk-S2T7DDGY.js} +16 -16
  66. package/dist/safe-bash/command-chunks/{chunk-LZHFVNEV.js → chunk-S3QYSI5E.js} +1 -1
  67. package/dist/safe-bash/command-chunks/{chunk-ZLMCWAAU.js → chunk-STTXZKR6.js} +3 -3
  68. package/dist/safe-bash/command-chunks/{chunk-AXUHORS3.js → chunk-SUYSZJI3.js} +1 -1
  69. package/dist/safe-bash/command-chunks/{chunk-C5SLY3RB.js → chunk-U2C6A3QO.js} +1 -1
  70. package/dist/safe-bash/command-chunks/{chunk-HCJWEB6P.js → chunk-U6IEK2CI.js} +7 -7
  71. package/dist/safe-bash/command-chunks/{chunk-NN6OWOJG.js → chunk-UC6DUY3K.js} +2 -2
  72. package/dist/safe-bash/command-chunks/{chunk-64L57DEI.js → chunk-UQTU7H6T.js} +9 -9
  73. package/dist/safe-bash/command-chunks/{chunk-ARA57PMC.js → chunk-V5PVNBOS.js} +4 -4
  74. package/dist/safe-bash/command-chunks/{chunk-ZZ6EIACJ.js → chunk-VGHRMAI4.js} +5 -5
  75. package/dist/safe-bash/command-chunks/{chunk-DZTT5SLG.js → chunk-VP7R7HKY.js} +5 -5
  76. package/dist/safe-bash/command-chunks/{chunk-TP5MZHCB.js → chunk-W5Y7Y7PS.js} +3 -3
  77. package/dist/safe-bash/command-chunks/{chunk-ZTW2E5OT.js → chunk-WAE3OCOU.js} +3 -3
  78. package/dist/safe-bash/command-chunks/{chunk-DBYY7IDI.js → chunk-WCM47S5A.js} +10 -10
  79. package/dist/safe-bash/command-chunks/{chunk-U6VSRO6E.js → chunk-WNVBS4GV.js} +4 -4
  80. package/dist/safe-bash/command-chunks/{chunk-CXOAMPOV.js → chunk-WUIS2INH.js} +13 -13
  81. package/dist/safe-bash/command-chunks/{chunk-4HJEZGYN.js → chunk-YODHIRPW.js} +7 -7
  82. package/dist/safe-bash/command-chunks/{chunk-C3FERGHU.js → chunk-YRMTOLG5.js} +3 -3
  83. package/dist/safe-bash/command-chunks/{chunk-YXIJOYT6.js → chunk-ZUOCXDYW.js} +1 -1
  84. package/dist/safe-bash/command-chunks/{chunk-LBBJ5S3W.js → chunk-ZZKJPLIH.js} +1 -1
  85. package/dist/safe-bash/command-chunks/{engine-UPLVIV72-IGXUDNO5.js → engine-UPLVIV72-MSSFJLK4.js} +1 -1
  86. package/dist/safe-bash/commands/python/source-archive.d.ts +2 -0
  87. package/dist/safe-bash/commands/python/source-archive.js +2 -0
  88. package/dist/safe-bash/commands/python/source-zip.d.ts +2 -0
  89. package/dist/safe-bash/commands/python/source-zip.js +2 -0
  90. package/dist/safe-bash-command-exiftool/index.js +41 -0
  91. package/dist/safe-bash-command-git/git_rust.wasm +0 -0
  92. package/dist/safe-bash-command-playwright-cli/index.js +36 -36
  93. package/dist/safe-bash-command-playwright-cli/playwright/abilities.js +7 -7
  94. package/dist/safe-bash-command-playwright-cli/playwright/adapter.js +3 -3
  95. package/dist/safe-bash-command-playwright-cli/playwright/capability-events.js +1 -1
  96. package/dist/safe-bash-command-playwright-cli/playwright/capability-result.js +1 -1
  97. package/dist/safe-bash-command-playwright-cli/playwright/controller.js +15 -15
  98. package/dist/safe-bash-command-playwright-cli/playwright/download-capabilities.js +1 -1
  99. package/dist/safe-bash-command-playwright-cli/playwright/drop-capability.js +1 -1
  100. package/dist/safe-bash-command-playwright-cli/playwright/index.js +35 -35
  101. package/dist/safe-bash-command-playwright-cli/playwright/modal-capabilities.js +1 -1
  102. package/dist/safe-bash-command-playwright-cli/playwright/native-evaluation.js +1 -1
  103. package/dist/safe-bash-command-playwright-cli/playwright/native-json-snapshot.js +1 -1
  104. package/dist/safe-bash-command-playwright-cli/playwright/native-snapshot.js +1 -1
  105. package/dist/safe-bash-command-playwright-cli/playwright/native-storage-replacement.js +2 -2
  106. package/dist/safe-bash-command-playwright-cli/playwright/profile.js +3 -3
  107. package/dist/safe-bash-command-playwright-cli/playwright/recording-capabilities.js +1 -1
  108. package/dist/safe-bash-command-playwright-cli/playwright/route-capabilities.js +1 -1
  109. package/dist/safe-bash-command-playwright-cli/playwright/snapshot.js +1 -1
  110. package/dist/safe-bash-command-playwright-cli/playwright/standard-capabilities.js +6 -6
  111. package/dist/safe-bash-command-playwright-cli/playwright/storage-capabilities.js +5 -5
  112. package/dist/safe-bash-command-playwright-cli/playwright/tracing-capabilities.js +1 -1
  113. package/dist/safe-bash-command-playwright-cli/playwright/webmcp-capabilities.js +1 -1
  114. package/dist/safe-bash-command-python/build-backend.d.ts +45 -3
  115. package/dist/safe-bash-command-python/build-dependencies.d.ts +2 -1
  116. package/dist/safe-bash-command-python/executor.d.ts +1 -1
  117. package/dist/safe-bash-command-python/executor.js +5 -4
  118. package/dist/safe-bash-command-python/index.js +5 -4
  119. package/dist/safe-bash-command-python/jspi.js +2 -2
  120. package/dist/safe-bash-command-python/manifest.d.ts +5 -1
  121. package/dist/safe-bash-command-python/provisioning.d.ts +7 -3
  122. package/dist/safe-bash-command-python/provisioning.js +2 -1
  123. package/dist/safe-bash-command-python/source-archive.d.ts +4 -0
  124. package/dist/safe-bash-command-python/source-archive.js +136 -0
  125. package/dist/safe-bash-command-python/source-environment.d.ts +4 -1
  126. package/dist/safe-bash-command-python/source-zip.d.ts +8 -0
  127. package/dist/safe-bash-command-python/source-zip.js +8 -0
  128. package/dist/safe-bash-command-python/worker.js +1 -1
  129. package/dist/safe-bash-command-safejs/index.js +5 -5
  130. package/dist/safe-bash-command-safejs/runtime.js +3 -3
  131. package/dist/safe-bash-command-ssconvert/index.js +8 -8
  132. package/dist/safe-bash-compression-engine/bounded-codec.js +2 -2
  133. package/dist/safe-bash-compression-engine/codec-loader.js +1 -1
  134. package/dist/safe-bash-compression-engine/files.js +5 -5
  135. package/dist/safe-bash-compression-engine/index.js +4 -4
  136. package/dist/safe-bash-compression-engine/operand.js +5 -5
  137. package/dist/safe-bash-compression-engine/stream.js +4 -4
  138. package/dist/safe-bash-compression-engine/zstd-decode.js +3 -3
  139. package/dist/safe-bash-presentation-engine/accessibility.js +15 -15
  140. package/dist/safe-bash-presentation-engine/animation-editing.js +5 -5
  141. package/dist/safe-bash-presentation-engine/animations.js +5 -5
  142. package/dist/safe-bash-presentation-engine/backgrounds.js +6 -6
  143. package/dist/safe-bash-presentation-engine/chart-editing.js +18 -18
  144. package/dist/safe-bash-presentation-engine/chart-object-operations.js +12 -12
  145. package/dist/safe-bash-presentation-engine/charts.js +15 -15
  146. package/dist/safe-bash-presentation-engine/command-placeholder.js +39 -39
  147. package/dist/safe-bash-presentation-engine/comments.js +6 -6
  148. package/dist/safe-bash-presentation-engine/connector-operations.js +16 -16
  149. package/dist/safe-bash-presentation-engine/connectors.js +13 -13
  150. package/dist/safe-bash-presentation-engine/diff.js +21 -21
  151. package/dist/safe-bash-presentation-engine/drawing-format.js +7 -7
  152. package/dist/safe-bash-presentation-engine/drawing-operations.js +15 -15
  153. package/dist/safe-bash-presentation-engine/drawing-schema.js +8 -8
  154. package/dist/safe-bash-presentation-engine/equations.js +6 -6
  155. package/dist/safe-bash-presentation-engine/fields.js +6 -6
  156. package/dist/safe-bash-presentation-engine/image-extraction.js +7 -7
  157. package/dist/safe-bash-presentation-engine/image-formatting.js +16 -16
  158. package/dist/safe-bash-presentation-engine/image-insertion.js +6 -6
  159. package/dist/safe-bash-presentation-engine/image-replacement.js +7 -7
  160. package/dist/safe-bash-presentation-engine/images.js +6 -6
  161. package/dist/safe-bash-presentation-engine/index.js +104 -104
  162. package/dist/safe-bash-presentation-engine/layouts.js +5 -5
  163. package/dist/safe-bash-presentation-engine/links.js +5 -5
  164. package/dist/safe-bash-presentation-engine/masters.js +4 -4
  165. package/dist/safe-bash-presentation-engine/media-editing.js +13 -13
  166. package/dist/safe-bash-presentation-engine/media-extraction.js +7 -7
  167. package/dist/safe-bash-presentation-engine/media.js +6 -6
  168. package/dist/safe-bash-presentation-engine/memberships.js +5 -5
  169. package/dist/safe-bash-presentation-engine/notes.js +6 -6
  170. package/dist/safe-bash-presentation-engine/ole-insertion.js +6 -6
  171. package/dist/safe-bash-presentation-engine/opaque-objects.js +2 -2
  172. package/dist/safe-bash-presentation-engine/package-tools.js +6 -6
  173. package/dist/safe-bash-presentation-engine/presentation-model.js +38 -38
  174. package/dist/safe-bash-presentation-engine/presentation-settings.js +5 -5
  175. package/dist/safe-bash-presentation-engine/properties.js +6 -6
  176. package/dist/safe-bash-presentation-engine/retained-inspection.js +3 -3
  177. package/dist/safe-bash-presentation-engine/retained-text.js +16 -16
  178. package/dist/safe-bash-presentation-engine/sanitize.js +7 -7
  179. package/dist/safe-bash-presentation-engine/selectors.js +2 -2
  180. package/dist/safe-bash-presentation-engine/shape-groups.js +15 -15
  181. package/dist/safe-bash-presentation-engine/shape-operations.js +14 -14
  182. package/dist/safe-bash-presentation-engine/shape-path-operations.js +16 -16
  183. package/dist/safe-bash-presentation-engine/shape-paths.js +5 -5
  184. package/dist/safe-bash-presentation-engine/shape-selection.js +15 -15
  185. package/dist/safe-bash-presentation-engine/shape-transforms.js +5 -5
  186. package/dist/safe-bash-presentation-engine/shapes.js +11 -11
  187. package/dist/safe-bash-presentation-engine/slide-copy.js +7 -7
  188. package/dist/safe-bash-presentation-engine/slide-import.js +6 -6
  189. package/dist/safe-bash-presentation-engine/slide-merge-split.js +8 -8
  190. package/dist/safe-bash-presentation-engine/slide-model.js +25 -25
  191. package/dist/safe-bash-presentation-engine/slide-removal.js +7 -7
  192. package/dist/safe-bash-presentation-engine/slide-transfer-budget.js +2 -2
  193. package/dist/safe-bash-presentation-engine/slides.js +5 -5
  194. package/dist/safe-bash-presentation-engine/table-operations.js +17 -17
  195. package/dist/safe-bash-presentation-engine/table-spans.js +16 -16
  196. package/dist/safe-bash-presentation-engine/tables.js +15 -15
  197. package/dist/safe-bash-presentation-engine/tags.js +6 -6
  198. package/dist/safe-bash-presentation-engine/template-bindings.js +16 -16
  199. package/dist/safe-bash-presentation-engine/template-repeat.js +26 -26
  200. package/dist/safe-bash-presentation-engine/text-fitting.js +11 -11
  201. package/dist/safe-bash-presentation-engine/text-frames.js +11 -11
  202. package/dist/safe-bash-presentation-engine/text-paragraphs.js +11 -11
  203. package/dist/safe-bash-presentation-engine/text-reading.js +3 -3
  204. package/dist/safe-bash-presentation-engine/text-replacement.js +6 -6
  205. package/dist/safe-bash-presentation-engine/text-runs.js +8 -8
  206. package/dist/safe-bash-presentation-engine/themes.js +5 -5
  207. package/dist/safe-bash-presentation-engine/transitions.js +6 -6
  208. package/dist/safe-bash-presentation-engine/validation.js +2 -2
  209. package/dist/safe-bash-presentation-engine/xml-parts.js +5 -5
  210. package/package.json +12 -2
  211. package/dist/safe-bash/command-chunks/{biff-AYJZR2YV-YFF3BK43.js → biff-AYJZR2YV-2BK47I2W.js} +1 -1
  212. package/dist/safe-bash/command-chunks/{chunk-SKDJCMGI.js → chunk-ATUZ7J3B.js} +3 -3
  213. package/dist/safe-bash/command-chunks/{chunk-4Q4R3VZU.js → chunk-ETFJ4L7F.js} +0 -0
  214. package/dist/safe-bash/command-chunks/{chunk-QWHBQBPB.js → chunk-EXDMIGZY.js} +6 -6
  215. package/dist/safe-bash/command-chunks/{chunk-SKF6PGA5.js → chunk-I2OKE2NI.js} +3 -3
  216. package/dist/safe-bash/command-chunks/{chunk-2H6RJPCQ.js → chunk-JDDZRKC4.js} +3 -3
  217. package/dist/safe-bash/command-chunks/{chunk-3TP4SSPS.js → chunk-SRXARACJ.js} +3 -3
  218. package/dist/safe-bash/command-chunks/{chunk-D54L2IOZ.js → chunk-Y7UXJ77P.js} +3 -3
  219. package/dist/safe-bash/command-chunks/{dif-BXKPQOCO-FVJYYGYB.js → dif-BXKPQOCO-4KB3RC6G.js} +4 -4
  220. package/dist/safe-bash/command-chunks/{sylk-25D7TL2Y-NJKBZZTF.js → sylk-25D7TL2Y-RU6ANKGT.js} +4 -4
@@ -1,17 +1,20 @@
1
1
  import {
2
2
  createPythonPackageEnvironment,
3
3
  createPythonPackageManifestStore,
4
- openPythonPackageFile,
5
4
  pythonDocumentPackages,
6
5
  stagePythonPackage
7
- } from "./chunk-WDTWJFPK.js";
6
+ } from "./chunk-IKBTII7C.js";
8
7
  import {
9
8
  pythonShellDispatchActive
10
9
  } from "./chunk-NHAG4DWL.js";
10
+ import {
11
+ openPythonPackageFile
12
+ } from "./chunk-NXCJNPL3.js";
11
13
  import {
12
14
  PythonInvocationError,
13
- parsePythonInvocation
14
- } from "./chunk-64HIOP7Q.js";
15
+ parsePythonInvocation,
16
+ pythonPackageUrlHash
17
+ } from "./chunk-3EBQOZET.js";
15
18
  import {
16
19
  pythonLlmProvider
17
20
  } from "./chunk-YYRVGXJH.js";
@@ -113,11 +116,13 @@ function encodePythonReply(value, maxBytes) {
113
116
  }
114
117
 
115
118
  // packages/safe-bash-command-python/src/installation.ts
116
- var pythonInstallationHelp = `Usage: python -m pip install [-r/--requirement FILE] [OPTIONS] PACKAGE ...
119
+ var PythonInstallationError = class extends Error {
120
+ };
121
+ var pythonInstallationHelp = `Usage: python -m pip install [OPTIONS] PACKAGE ...
117
122
  python -m pip uninstall [-y/--yes] PACKAGE ...
118
- Install options: --pre, -U/--upgrade, --force-reinstall, --no-cache-dir
119
- Compatible wheels; configure transport with the Python package SDK.
120
- Both accept -h/--help and --. Other pip operations are unsupported.
123
+ Install: -r/--requirement FILE, -e/--editable PATH, --pre, -U/--upgrade,
124
+ --force-reinstall, --no-cache-dir
125
+ Both accept -h/--help and --.
121
126
  `;
122
127
  function parsePythonInstallation(pipArgs) {
123
128
  const controls = {};
@@ -138,12 +143,9 @@ function parsePythonInstallation(pipArgs) {
138
143
  packages.push(option);
139
144
  continue;
140
145
  }
141
- if (!uninstall && (option === "--pre" || option === "--no-cache-dir")) {
142
- controls[option === "--pre" ? "pre" : "noCache"] = true;
143
- continue;
144
- }
145
- if (!uninstall && (option === "-U" || option === "--upgrade" || option === "--force-reinstall")) {
146
- controls[option === "--force-reinstall" ? "forceReinstall" : "upgrade"] = true;
146
+ const flag = { "--pre": "pre", "--no-cache-dir": "noCache", "-U": "upgrade", "--upgrade": "upgrade", "--force-reinstall": "forceReinstall" }[option];
147
+ if (!uninstall && flag) {
148
+ controls[flag] = true;
147
149
  continue;
148
150
  }
149
151
  if (option === "--") {
@@ -158,15 +160,19 @@ function parsePythonInstallation(pipArgs) {
158
160
  yes = true;
159
161
  continue;
160
162
  }
161
- if (!uninstall && (option === "-r" || option === "--requirement" || option.startsWith("--requirement=") || option.startsWith("-r"))) {
162
- const path = option.startsWith("--requirement=") ? option.slice("--requirement=".length) : option !== "-r" && option.startsWith("-r") ? option.slice(2) : pipArgs[++index];
163
- if (!path || path.startsWith("-")) throw new PythonInvocationError(option + " requires a path");
164
- requirements.push(path);
165
- continue;
163
+ if (!uninstall) {
164
+ const kind = ["requirement", "editable"].find((name) => option.startsWith("-" + name[0]) || option.split("=", 1)[0] === "--" + name);
165
+ if (kind) {
166
+ const prefix = "--" + kind;
167
+ const path = option.startsWith(prefix + "=") ? option.slice(prefix.length + 1) : option === prefix || option.length === 2 ? pipArgs[++index] : option.slice(2);
168
+ if (!path || path.startsWith("-")) throw new PythonInvocationError(option + " requires a path");
169
+ (kind === "editable" ? controls.editable ??= [] : requirements).push(path);
170
+ continue;
171
+ }
166
172
  }
167
173
  throw new PythonInvocationError("unsupported pip option " + option);
168
174
  }
169
- if (!help && packages.length === 0 && requirements.length === 0) throw new PythonInvocationError("pip " + pipArgs[0] + " requires at least one package or requirements file");
175
+ if (!help && packages.length === 0 && requirements.length === 0 && !controls.editable?.length) throw new PythonInvocationError("pip " + pipArgs[0] + " requires at least one package or requirements file");
170
176
  return { packages, requirements, help, controls, ...uninstall ? { uninstall, yes } : {} };
171
177
  }
172
178
 
@@ -845,7 +851,7 @@ function createPythonLlmToolLoader(options) {
845
851
  const queue = [];
846
852
  let waiter;
847
853
  let serial3 = 0, controls = 0, loaded = false, initializationFailed = false, closed = false, closing;
848
- const encoder = new TextEncoder();
854
+ const encoder2 = new TextEncoder();
849
855
  const fail = (error) => {
850
856
  ready.reject(error);
851
857
  queue.length = 0;
@@ -930,7 +936,7 @@ function createPythonLlmToolLoader(options) {
930
936
  return null;
931
937
  }
932
938
  if (message.op === "register" || message.op === "toolbox" || message.op === "plugins") {
933
- controls += encoder.encode(JSON.stringify(message)).length;
939
+ controls += encoder2.encode(JSON.stringify(message)).length;
934
940
  if (controls > maxInputBytes) throw new RangeError("Python tool definition byte limit exceeded");
935
941
  }
936
942
  if (message.op === "plugins") {
@@ -1000,7 +1006,7 @@ function createPythonLlmToolLoader(options) {
1000
1006
  let bytes, target = job.output;
1001
1007
  if (message.op === "text") {
1002
1008
  if (typeof message.text !== "string" || message.text.length > 8192) throw new TypeError("Invalid Python tool output window");
1003
- bytes = encoder.encode(message.text);
1009
+ bytes = encoder2.encode(message.text);
1004
1010
  if (bytes.length > 16384) throw new TypeError("Invalid Python tool output window");
1005
1011
  } else {
1006
1012
  if (!Array.isArray(message.bytes) || message.bytes.length > 4096 || message.bytes.some((value2) => typeof value2 !== "number" || !Number.isInteger(value2) || value2 < 0 || value2 > 255)) throw new TypeError("Invalid Python attachment window");
@@ -1016,7 +1022,7 @@ function createPythonLlmToolLoader(options) {
1016
1022
  if (message.op === "attachment") {
1017
1023
  const metadata = record(message.descriptor);
1018
1024
  if (typeof metadata.mimeType !== "string" || typeof metadata.id !== "string" || metadata.url !== void 0 && typeof metadata.url !== "string") throw new TypeError("Invalid Python tool attachment");
1019
- const size = encoder.encode(JSON.stringify(metadata)).length;
1025
+ const size = encoder2.encode(JSON.stringify(metadata)).length;
1020
1026
  if (size > job.limit - job.bytes) throw new RangeError("Python tool attachment metadata limit exceeded");
1021
1027
  job.bytes += size;
1022
1028
  const index = job.attachments.length;
@@ -1097,6 +1103,7 @@ function createPythonLlmToolLoader(options) {
1097
1103
  function createPythonBuildEnvironment(options = {}) {
1098
1104
  const manifestStore = createPythonPackageManifestStore({ maxEntries: 1, ...options.maxManifestBytes === void 0 ? {} : { maxBytes: options.maxManifestBytes } });
1099
1105
  const isolated = { ...options, manifestStore, scope: "build" };
1106
+ delete isolated.editable;
1100
1107
  delete isolated.requirements;
1101
1108
  delete isolated.requirementFiles;
1102
1109
  delete isolated.profile;
@@ -1110,14 +1117,58 @@ function createPythonBuildEnvironment(options = {}) {
1110
1117
  // packages/safe-bash-command-python/src/build-dependencies.ts
1111
1118
  import { toByteSource as toByteSource6 } from "../../safe-bash-contracts/index.js";
1112
1119
 
1120
+ // packages/safe-bash-command-python/src/source-origin-program.generated.ts
1121
+ var pythonSourceOriginProgram = "def read_source_origin(request):\n import re, json\n from urllib.parse import urlsplit, urlunsplit\n source = request['source']\n if source.startswith('/'):\n from pathlib import Path\n source = Path(source).as_uri()\n url = urlsplit(source)\n netloc = url.netloc\n if '@' in netloc:\n credentials, host = netloc.split('@', 1)\n if not re.match(r'^\\$\\{[A-Za-z0-9-_]+\\}(:\\$\\{[A-Za-z0-9-_]+\\})?$', credentials): netloc = host\n result = {'url': urlunsplit((url.scheme, netloc, url.path, url.query, ''))}\n subdirectory = re.search(r'[#&]subdirectory=([^&]*)', source)\n if subdirectory: result['subdirectory'] = subdirectory.group(1)\n info = {}\n if not request['directory']:\n hashed = re.search(r'(sha1|sha224|sha384|sha256|sha512|md5)=([a-f0-9]+)', source)\n if hashed: info['hash'] = hashed.group(1) + '=' + hashed.group(2)\n result['dir_info' if request['directory'] else 'archive_info'] = info\n return json.dumps(result, sort_keys=True)\n";
1122
+
1123
+ // packages/safe-bash-command-python/src/source-filename-program.ts
1124
+ var pythonDownloadFilenameProgram = /* @__PURE__ */ (() => String.raw`
1125
+ MIME_PREFERENCES = {"application/andrew-inset":".ez","application/applixware":".aw","application/atom+xml":".atom","application/atomcat+xml":".atomcat","application/atomsvc+xml":".atomsvc","application/ccxml+xml":".ccxml","application/cdmi-capability":".cdmia","application/cdmi-container":".cdmic","application/cdmi-domain":".cdmid","application/cdmi-object":".cdmio","application/cdmi-queue":".cdmiq","application/cu-seeme":".cu","application/davmount+xml":".davmount","application/docbook+xml":".dbk","application/dssc+der":".dssc","application/dssc+xml":".xdssc","application/ecmascript":".ecma","application/emma+xml":".emma","application/epub+zip":".epub","application/exi":".exi","application/font-tdpfr":".pfr","application/gml+xml":".gml","application/gpx+xml":".gpx","application/gxf":".gxf","application/hyperstudio":".stk","application/inkml+xml":".ink","application/ipfix":".ipfix","application/java-archive":".jar","application/java-serialized-object":".ser","application/java-vm":".class","application/json":".json","application/jsonml+json":".jsonml","application/lost+xml":".lostxml","application/mac-binhex40":".hqx","application/mac-compactpro":".cpt","application/mads+xml":".mads","application/manifest+json":".webmanifest","application/marc":".mrc","application/marcxml+xml":".mrcx","application/mathematica":".ma","application/mathml+xml":".mathml","application/mbox":".mbox","application/mediaservercontrol+xml":".mscml","application/metalink+xml":".metalink","application/metalink4+xml":".meta4","application/mets+xml":".mets","application/mods+xml":".mods","application/mp21":".m21","application/mp4":".mp4s","application/msword":".doc","application/mxf":".mxf","application/octet-stream":".bin","application/oda":".oda","application/oebps-package+xml":".opf","application/ogg":".ogx","application/omdoc+xml":".omdoc","application/onenote":".onetoc","application/oxps":".oxps","application/patch-ops-error+xml":".xer","application/pdf":".pdf","application/pgp-encrypted":".pgp","application/pgp-signature":".asc","application/pics-rules":".prf","application/pkcs10":".p10","application/pkcs7-mime":".p7c","application/pkcs7-signature":".p7s","application/pkcs8":".p8","application/pkix-attr-cert":".ac","application/pkix-cert":".cer","application/pkix-crl":".crl","application/pkix-pkipath":".pkipath","application/pkixcmp":".pki","application/pls+xml":".pls","application/postscript":".ps","application/prs.cww":".cww","application/pskc+xml":".pskcxml","application/rdf+xml":".rdf","application/reginfo+xml":".rif","application/relax-ng-compact-syntax":".rnc","application/resource-lists+xml":".rl","application/resource-lists-diff+xml":".rld","application/rls-services+xml":".rs","application/rpki-ghostbusters":".gbr","application/rpki-manifest":".mft","application/rpki-roa":".roa","application/rsd+xml":".rsd","application/rss+xml":".rss","application/rtf":".rtf","application/sbml+xml":".sbml","application/scvp-cv-request":".scq","application/scvp-cv-response":".scs","application/scvp-vp-request":".spq","application/scvp-vp-response":".spp","application/sdp":".sdp","application/set-payment-initiation":".setpay","application/set-registration-initiation":".setreg","application/shf+xml":".shf","application/smil+xml":".smi","application/sparql-query":".rq","application/sparql-results+xml":".srx","application/srgs":".gram","application/srgs+xml":".grxml","application/sru+xml":".sru","application/ssdl+xml":".ssdl","application/ssml+xml":".ssml","application/tei+xml":".tei","application/thraud+xml":".tfi","application/timestamped-data":".tsd","application/vnd.3gpp.pic-bw-large":".plb","application/vnd.3gpp.pic-bw-small":".psb","application/vnd.3gpp.pic-bw-var":".pvb","application/vnd.3gpp2.tcap":".tcap","application/vnd.3m.post-it-notes":".pwn","application/vnd.accpac.simply.aso":".aso","application/vnd.accpac.simply.imp":".imp","application/vnd.acucobol":".acu","application/vnd.acucorp":".atc","application/vnd.adobe.air-application-installer-package+zip":".air","application/vnd.adobe.formscentral.fcdt":".fcdt","application/vnd.adobe.fxp":".fxp","application/vnd.adobe.xdp+xml":".xdp","application/vnd.adobe.xfdf":".xfdf","application/vnd.ahead.space":".ahead","application/vnd.airzip.filesecure.azf":".azf","application/vnd.airzip.filesecure.azs":".azs","application/vnd.amazon.ebook":".azw","application/vnd.americandynamics.acc":".acc","application/vnd.amiga.ami":".ami","application/vnd.android.package-archive":".apk","application/vnd.anser-web-certificate-issue-initiation":".cii","application/vnd.anser-web-funds-transfer-initiation":".fti","application/vnd.antix.game-component":".atx","application/vnd.apple.installer+xml":".mpkg","application/vnd.aristanetworks.swi":".swi","application/vnd.astraea-software.iota":".iota","application/vnd.audiograph":".aep","application/vnd.blueice.multipass":".mpm","application/vnd.bmi":".bmi","application/vnd.businessobjects":".rep","application/vnd.chemdraw+xml":".cdxml","application/vnd.chipnuts.karaoke-mmd":".mmd","application/vnd.cinderella":".cdy","application/vnd.claymore":".cla","application/vnd.cloanto.rp9":".rp9","application/vnd.clonk.c4group":".c4g","application/vnd.cluetrust.cartomobile-config":".c11amc","application/vnd.cluetrust.cartomobile-config-pkg":".c11amz","application/vnd.commonspace":".csp","application/vnd.contact.cmsg":".cdbcmsg","application/vnd.cosmocaller":".cmc","application/vnd.crick.clicker":".clkx","application/vnd.crick.clicker.keyboard":".clkk","application/vnd.crick.clicker.palette":".clkp","application/vnd.crick.clicker.template":".clkt","application/vnd.crick.clicker.wordbank":".clkw","application/vnd.criticaltools.wbs+xml":".wbs","application/vnd.ctc-posml":".pml","application/vnd.cups-ppd":".ppd","application/vnd.curl.car":".car","application/vnd.curl.pcurl":".pcurl","application/vnd.dart":".dart","application/vnd.data-vision.rdz":".rdz","application/vnd.dece.data":".uvf","application/vnd.dece.ttml+xml":".uvt","application/vnd.dece.unspecified":".uvx","application/vnd.dece.zip":".uvz","application/vnd.denovo.fcselayout-link":".fe_launch","application/vnd.dna":".dna","application/vnd.dolby.mlp":".mlp","application/vnd.dpgraph":".dpg","application/vnd.dreamfactory":".dfac","application/vnd.ds-keypoint":".kpxx","application/vnd.dvb.ait":".ait","application/vnd.dvb.service":".svc","application/vnd.dynageo":".geo","application/vnd.ecowin.chart":".mag","application/vnd.enliven":".nml","application/vnd.epson.esf":".esf","application/vnd.epson.msf":".msf","application/vnd.epson.quickanime":".qam","application/vnd.epson.salt":".slt","application/vnd.epson.ssf":".ssf","application/vnd.eszigno3+xml":".es3","application/vnd.ezpix-album":".ez2","application/vnd.ezpix-package":".ez3","application/vnd.fdf":".fdf","application/vnd.fdsn.mseed":".mseed","application/vnd.fdsn.seed":".seed","application/vnd.flographit":".gph","application/vnd.fluxtime.clip":".ftc","application/vnd.framemaker":".fm","application/vnd.frogans.fnc":".fnc","application/vnd.frogans.ltf":".ltf","application/vnd.fsc.weblaunch":".fsc","application/vnd.fujitsu.oasys":".oas","application/vnd.fujitsu.oasys2":".oa2","application/vnd.fujitsu.oasys3":".oa3","application/vnd.fujitsu.oasysgp":".fg5","application/vnd.fujitsu.oasysprs":".bh2","application/vnd.fujixerox.ddd":".ddd","application/vnd.fujixerox.docuworks":".xdw","application/vnd.fujixerox.docuworks.binder":".xbd","application/vnd.fuzzysheet":".fzs","application/vnd.genomatix.tuxedo":".txd","application/vnd.geogebra.file":".ggb","application/vnd.geogebra.slides":".ggs","application/vnd.geogebra.tool":".ggt","application/vnd.geometry-explorer":".gex","application/vnd.geonext":".gxt","application/vnd.geoplan":".g2w","application/vnd.geospace":".g3w","application/vnd.gmx":".gmx","application/vnd.google-earth.kml+xml":".kml","application/vnd.google-earth.kmz":".kmz","application/vnd.grafeq":".gqf","application/vnd.groove-account":".gac","application/vnd.groove-help":".ghf","application/vnd.groove-identity-message":".gim","application/vnd.groove-injector":".grv","application/vnd.groove-tool-message":".gtm","application/vnd.groove-tool-template":".tpl","application/vnd.groove-vcard":".vcg","application/vnd.hal+xml":".hal","application/vnd.handheld-entertainment+xml":".zmm","application/vnd.hbci":".hbci","application/vnd.hhe.lesson-player":".les","application/vnd.hp-hpgl":".hpgl","application/vnd.hp-hpid":".hpid","application/vnd.hp-hps":".hps","application/vnd.hp-jlyt":".jlt","application/vnd.hp-pcl":".pcl","application/vnd.hp-pclxl":".pclxl","application/vnd.hydrostatix.sof-data":".sfd-hdstx","application/vnd.ibm.minipay":".mpy","application/vnd.ibm.modcap":".afp","application/vnd.ibm.rights-management":".irm","application/vnd.ibm.secure-container":".sc","application/vnd.iccprofile":".icc","application/vnd.igloader":".igl","application/vnd.immervision-ivp":".ivp","application/vnd.immervision-ivu":".ivu","application/vnd.insors.igm":".igm","application/vnd.intercon.formnet":".xpw","application/vnd.intergeo":".i2g","application/vnd.intu.qbo":".qbo","application/vnd.intu.qfx":".qfx","application/vnd.ipunplugged.rcprofile":".rcprofile","application/vnd.irepository.package+xml":".irp","application/vnd.is-xpr":".xpr","application/vnd.isac.fcs":".fcs","application/vnd.jam":".jam","application/vnd.jcp.javame.midlet-rms":".rms","application/vnd.jisp":".jisp","application/vnd.joost.joda-archive":".joda","application/vnd.kahootz":".ktz","application/vnd.kde.karbon":".karbon","application/vnd.kde.kchart":".chrt","application/vnd.kde.kformula":".kfo","application/vnd.kde.kivio":".flw","application/vnd.kde.kontour":".kon","application/vnd.kde.kpresenter":".kpr","application/vnd.kde.kspread":".ksp","application/vnd.kde.kword":".kwd","application/vnd.kenameaapp":".htke","application/vnd.kidspiration":".kia","application/vnd.kinar":".kne","application/vnd.koan":".skp","application/vnd.kodak-descriptor":".sse","application/vnd.las.las+xml":".lasxml","application/vnd.llamagraphics.life-balance.desktop":".lbd","application/vnd.llamagraphics.life-balance.exchange+xml":".lbe","application/vnd.lotus-1-2-3":".123","application/vnd.lotus-approach":".apr","application/vnd.lotus-freelance":".pre","application/vnd.lotus-notes":".nsf","application/vnd.lotus-organizer":".org","application/vnd.lotus-screencam":".scm","application/vnd.lotus-wordpro":".lwp","application/vnd.macports.portpkg":".portpkg","application/vnd.mcd":".mcd","application/vnd.medcalcdata":".mc1","application/vnd.mediastation.cdkey":".cdkey","application/vnd.mfer":".mwf","application/vnd.mfmp":".mfm","application/vnd.micrografx.flo":".flo","application/vnd.micrografx.igx":".igx","application/vnd.mif":".mif","application/vnd.mobius.daf":".daf","application/vnd.mobius.dis":".dis","application/vnd.mobius.mbk":".mbk","application/vnd.mobius.mqy":".mqy","application/vnd.mobius.msl":".msl","application/vnd.mobius.plc":".plc","application/vnd.mobius.txf":".txf","application/vnd.mophun.application":".mpn","application/vnd.mophun.certificate":".mpc","application/vnd.mozilla.xul+xml":".xul","application/vnd.ms-artgalry":".cil","application/vnd.ms-cab-compressed":".cab","application/vnd.ms-excel":".xls","application/vnd.ms-excel.addin.macroenabled.12":".xlam","application/vnd.ms-excel.sheet.binary.macroenabled.12":".xlsb","application/vnd.ms-excel.sheet.macroenabled.12":".xlsm","application/vnd.ms-excel.template.macroenabled.12":".xltm","application/vnd.ms-fontobject":".eot","application/vnd.ms-htmlhelp":".chm","application/vnd.ms-ims":".ims","application/vnd.ms-lrm":".lrm","application/vnd.ms-officetheme":".thmx","application/vnd.ms-pki.seccat":".cat","application/vnd.ms-pki.stl":".stl","application/vnd.ms-powerpoint":".ppt","application/vnd.ms-powerpoint.addin.macroenabled.12":".ppam","application/vnd.ms-powerpoint.presentation.macroenabled.12":".pptm","application/vnd.ms-powerpoint.slide.macroenabled.12":".sldm","application/vnd.ms-powerpoint.slideshow.macroenabled.12":".ppsm","application/vnd.ms-powerpoint.template.macroenabled.12":".potm","application/vnd.ms-project":".mpp","application/vnd.ms-word.document.macroenabled.12":".docm","application/vnd.ms-word.template.macroenabled.12":".dotm","application/vnd.ms-works":".wps","application/vnd.ms-wpl":".wpl","application/vnd.ms-xpsdocument":".xps","application/vnd.mseq":".mseq","application/vnd.musician":".mus","application/vnd.muvee.style":".msty","application/vnd.mynfc":".taglet","application/vnd.neurolanguage.nlu":".nlu","application/vnd.nitf":".ntf","application/vnd.noblenet-directory":".nnd","application/vnd.noblenet-sealer":".nns","application/vnd.noblenet-web":".nnw","application/vnd.nokia.n-gage.data":".ngdat","application/vnd.nokia.n-gage.symbian.install":".n-gage","application/vnd.nokia.radio-preset":".rpst","application/vnd.nokia.radio-presets":".rpss","application/vnd.novadigm.edm":".edm","application/vnd.novadigm.edx":".edx","application/vnd.novadigm.ext":".ext","application/vnd.oasis.opendocument.chart":".odc","application/vnd.oasis.opendocument.chart-template":".otc","application/vnd.oasis.opendocument.database":".odb","application/vnd.oasis.opendocument.formula":".odf","application/vnd.oasis.opendocument.formula-template":".odft","application/vnd.oasis.opendocument.graphics":".odg","application/vnd.oasis.opendocument.graphics-template":".otg","application/vnd.oasis.opendocument.image":".odi","application/vnd.oasis.opendocument.image-template":".oti","application/vnd.oasis.opendocument.presentation":".odp","application/vnd.oasis.opendocument.presentation-template":".otp","application/vnd.oasis.opendocument.spreadsheet":".ods","application/vnd.oasis.opendocument.spreadsheet-template":".ots","application/vnd.oasis.opendocument.text":".odt","application/vnd.oasis.opendocument.text-master":".odm","application/vnd.oasis.opendocument.text-template":".ott","application/vnd.oasis.opendocument.text-web":".oth","application/vnd.olpc-sugar":".xo","application/vnd.oma.dd2+xml":".dd2","application/vnd.openofficeorg.extension":".oxt","application/vnd.openxmlformats-officedocument.presentationml.presentation":".pptx","application/vnd.openxmlformats-officedocument.presentationml.slide":".sldx","application/vnd.openxmlformats-officedocument.presentationml.slideshow":".ppsx","application/vnd.openxmlformats-officedocument.presentationml.template":".potx","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":".xlsx","application/vnd.openxmlformats-officedocument.spreadsheetml.template":".xltx","application/vnd.openxmlformats-officedocument.wordprocessingml.document":".docx","application/vnd.openxmlformats-officedocument.wordprocessingml.template":".dotx","application/vnd.osgeo.mapguide.package":".mgp","application/vnd.osgi.dp":".dp","application/vnd.osgi.subsystem":".esa","application/vnd.palm":".pdb","application/vnd.pawaafile":".paw","application/vnd.pg.format":".str","application/vnd.pg.osasli":".ei6","application/vnd.picsel":".efif","application/vnd.pmi.widget":".wg","application/vnd.pocketlearn":".plf","application/vnd.powerbuilder6":".pbd","application/vnd.previewsystems.box":".box","application/vnd.proteus.magazine":".mgz","application/vnd.publishare-delta-tree":".qps","application/vnd.pvi.ptid1":".ptid","application/vnd.quark.quarkxpress":".qxd","application/vnd.realvnc.bed":".bed","application/vnd.recordare.musicxml":".mxl","application/vnd.recordare.musicxml+xml":".musicxml","application/vnd.rig.cryptonote":".cryptonote","application/vnd.rim.cod":".cod","application/vnd.rn-realmedia":".rm","application/vnd.rn-realmedia-vbr":".rmvb","application/vnd.route66.link66+xml":".link66","application/vnd.sailingtracker.track":".st","application/vnd.seemail":".see","application/vnd.sema":".sema","application/vnd.semd":".semd","application/vnd.semf":".semf","application/vnd.shana.informed.formdata":".ifm","application/vnd.shana.informed.formtemplate":".itp","application/vnd.shana.informed.interchange":".iif","application/vnd.shana.informed.package":".ipk","application/vnd.simtech-mindmapper":".twd","application/vnd.smaf":".mmf","application/vnd.smart.teacher":".teacher","application/vnd.solent.sdkm+xml":".sdkm","application/vnd.spotfire.dxp":".dxp","application/vnd.spotfire.sfs":".sfs","application/vnd.stardivision.calc":".sdc","application/vnd.stardivision.draw":".sda","application/vnd.stardivision.impress":".sdd","application/vnd.stardivision.math":".smf","application/vnd.stardivision.writer":".sdw","application/vnd.stardivision.writer-global":".sgl","application/vnd.stepmania.package":".smzip","application/vnd.stepmania.stepchart":".sm","application/vnd.sun.xml.calc":".sxc","application/vnd.sun.xml.calc.template":".stc","application/vnd.sun.xml.draw":".sxd","application/vnd.sun.xml.draw.template":".std","application/vnd.sun.xml.impress":".sxi","application/vnd.sun.xml.impress.template":".sti","application/vnd.sun.xml.math":".sxm","application/vnd.sun.xml.writer":".sxw","application/vnd.sun.xml.writer.global":".sxg","application/vnd.sun.xml.writer.template":".stw","application/vnd.sus-calendar":".sus","application/vnd.svd":".svd","application/vnd.symbian.install":".sis","application/vnd.syncml+xml":".xsm","application/vnd.syncml.dm+wbxml":".bdm","application/vnd.syncml.dm+xml":".xdm","application/vnd.tao.intent-module-archive":".tao","application/vnd.tcpdump.pcap":".pcap","application/vnd.tmobile-livetv":".tmo","application/vnd.trid.tpt":".tpt","application/vnd.triscape.mxs":".mxs","application/vnd.trueapp":".tra","application/vnd.ufdl":".ufd","application/vnd.uiq.theme":".utz","application/vnd.umajin":".umj","application/vnd.unity":".unityweb","application/vnd.uoml+xml":".uoml","application/vnd.vcx":".vcx","application/vnd.visio":".vsd","application/vnd.visionary":".vis","application/vnd.vsf":".vsf","application/vnd.wap.wbxml":".wbxml","application/vnd.wap.wmlc":".wmlc","application/vnd.wap.wmlscriptc":".wmlsc","application/vnd.webturbo":".wtb","application/vnd.wolfram.player":".nbp","application/vnd.wordperfect":".wpd","application/vnd.wqd":".wqd","application/vnd.wt.stf":".stf","application/vnd.xara":".xar","application/vnd.xfdl":".xfdl","application/vnd.yamaha.hv-dic":".hvd","application/vnd.yamaha.hv-script":".hvs","application/vnd.yamaha.hv-voice":".hvp","application/vnd.yamaha.openscoreformat":".osf","application/vnd.yamaha.openscoreformat.osfpvg+xml":".osfpvg","application/vnd.yamaha.smaf-audio":".saf","application/vnd.yamaha.smaf-phrase":".spf","application/vnd.yellowriver-custom-menu":".cmp","application/vnd.zul":".zir","application/vnd.zzazz.deck+xml":".zaz","application/voicexml+xml":".vxml","application/wasm":".wasm","application/widget":".wgt","application/winhlp":".hlp","application/wsdl+xml":".wsdl","application/wspolicy+xml":".wspolicy","application/x-7z-compressed":".7z","application/x-abiword":".abw","application/x-ace-compressed":".ace","application/x-apple-diskimage":".dmg","application/x-authorware-bin":".aab","application/x-authorware-map":".aam","application/x-authorware-seg":".aas","application/x-bcpio":".bcpio","application/x-bittorrent":".torrent","application/x-blorb":".blb","application/x-bzip":".bz","application/x-bzip2":".bz2","application/x-cbr":".cbr","application/x-cdlink":".vcd","application/x-cfs-compressed":".cfs","application/x-chat":".chat","application/x-chess-pgn":".pgn","application/x-conference":".nsc","application/x-cpio":".cpio","application/x-csh":".csh","application/x-debian-package":".deb","application/x-dgc-compressed":".dgc","application/x-director":".dir","application/x-doom":".wad","application/x-dtbncx+xml":".ncx","application/x-dtbook+xml":".dtb","application/x-dtbresource+xml":".res","application/x-dvi":".dvi","application/x-envoy":".evy","application/x-eva":".eva","application/x-font-bdf":".bdf","application/x-font-ghostscript":".gsf","application/x-font-linux-psf":".psf","application/x-font-pcf":".pcf","application/x-font-snf":".snf","application/x-font-type1":".pfa","application/x-freearc":".arc","application/x-futuresplash":".spl","application/x-gca-compressed":".gca","application/x-glulx":".ulx","application/x-gnumeric":".gnumeric","application/x-gramps-xml":".gramps","application/x-gtar":".gtar","application/x-hdf":".hdf","application/x-install-instructions":".install","application/x-iso9660-image":".iso","application/x-java-jnlp-file":".jnlp","application/x-latex":".latex","application/x-lzh-compressed":".lzh","application/x-mie":".mie","application/x-mobipocket-ebook":".prc","application/x-mpegurl":".m3u8","application/x-ms-application":".application","application/x-ms-shortcut":".lnk","application/x-ms-wmd":".wmd","application/x-ms-xbap":".xbap","application/x-msaccess":".mdb","application/x-msbinder":".obd","application/x-mscardfile":".crd","application/x-msclip":".clp","application/x-msdownload":".exe","application/x-msmediaview":".mvb","application/x-msmetafile":".wmf","application/x-msmoney":".mny","application/x-mspublisher":".pub","application/x-msschedule":".scd","application/x-msterminal":".trm","application/x-mswrite":".wri","application/x-netcdf":".cdf","application/x-nzb":".nzb","application/x-pkcs12":".p12","application/x-pkcs7-certificates":".p7b","application/x-pkcs7-certreqresp":".p7r","application/x-python-code":".pyc","application/x-rar-compressed":".rar","application/x-research-info-systems":".ris","application/x-sh":".sh","application/x-shar":".shar","application/x-shockwave-flash":".swf","application/x-silverlight-app":".xap","application/x-sql":".sql","application/x-stuffit":".sit","application/x-stuffitx":".sitx","application/x-subrip":".srt","application/x-sv4cpio":".sv4cpio","application/x-sv4crc":".sv4crc","application/x-t3vm-image":".t3","application/x-tads":".gam","application/x-tar":".tar","application/x-tcl":".tcl","application/x-tex":".tex","application/x-tex-tfm":".tfm","application/x-texinfo":".texi","application/x-tgif":".obj","application/x-ustar":".ustar","application/x-wais-source":".src","application/x-x509-ca-cert":".der","application/x-xfig":".fig","application/x-xliff+xml":".xlf","application/x-xpinstall":".xpi","application/x-xz":".xz","application/x-zmachine":".z1","application/xaml+xml":".xaml","application/xcap-diff+xml":".xdf","application/xenc+xml":".xenc","application/xhtml+xml":".xhtml","application/xml":".xsl","application/xml-dtd":".dtd","application/xop+xml":".xop","application/xproc+xml":".xpl","application/xslt+xml":".xslt","application/xspf+xml":".xspf","application/xv+xml":".mxml","application/yang":".yang","application/yin+xml":".yin","application/zip":".zip","audio/adpcm":".adp","audio/basic":".au","audio/midi":".mid","audio/mp4":".m4a","audio/mp4a-latm":".m4a","audio/mpeg":".mp3","audio/ogg":".oga","audio/s3m":".s3m","audio/silk":".sil","audio/vnd.dece.audio":".uva","audio/vnd.digital-winds":".eol","audio/vnd.dra":".dra","audio/vnd.dts":".dts","audio/vnd.dts.hd":".dtshd","audio/vnd.lucent.voice":".lvp","audio/vnd.ms-playready.media.pya":".pya","audio/vnd.nuera.ecelp4800":".ecelp4800","audio/vnd.nuera.ecelp7470":".ecelp7470","audio/vnd.nuera.ecelp9600":".ecelp9600","audio/vnd.rip":".rip","audio/webm":".weba","audio/x-aac":".aac","audio/x-aiff":".aif","audio/x-caf":".caf","audio/x-flac":".flac","audio/x-matroska":".mka","audio/x-mpegurl":".m3u","audio/x-ms-wax":".wax","audio/x-ms-wma":".wma","audio/x-pn-realaudio":".ra","audio/x-pn-realaudio-plugin":".rmp","audio/x-wav":".wav","audio/xm":".xm","chemical/x-cdx":".cdx","chemical/x-cif":".cif","chemical/x-cmdf":".cmdf","chemical/x-cml":".cml","chemical/x-csml":".csml","chemical/x-xyz":".xyz","font/collection":".ttc","font/otf":".otf","font/ttf":".ttf","font/woff":".woff","font/woff2":".woff2","image/avif":".avif","image/bmp":".bmp","image/cgm":".cgm","image/g3fax":".g3","image/gif":".gif","image/ief":".ief","image/jp2":".jp2","image/jpeg":".jpg","image/jxl":".jxl","image/ktx":".ktx","image/pict":".pict","image/png":".png","image/prs.btif":".btif","image/sgi":".sgi","image/svg+xml":".svg","image/tiff":".tiff","image/vnd.adobe.photoshop":".psd","image/vnd.dece.graphic":".uvi","image/vnd.djvu":".djvu","image/vnd.dwg":".dwg","image/vnd.dxf":".dxf","image/vnd.fastbidsheet":".fbs","image/vnd.fpx":".fpx","image/vnd.fst":".fst","image/vnd.fujixerox.edmics-mmr":".mmr","image/vnd.fujixerox.edmics-rlc":".rlc","image/vnd.ms-modi":".mdi","image/vnd.ms-photo":".wdp","image/vnd.net-fpx":".npx","image/vnd.wap.wbmp":".wbmp","image/vnd.xiff":".xif","image/webp":".webp","image/x-3ds":".3ds","image/x-cmu-raster":".ras","image/x-cmx":".cmx","image/x-freehand":".fh","image/x-icon":".ico","image/x-macpaint":".pntg","image/x-mrsid-image":".sid","image/x-pcx":".pcx","image/x-pict":".pic","image/x-portable-anymap":".pnm","image/x-portable-bitmap":".pbm","image/x-portable-graymap":".pgm","image/x-portable-pixmap":".ppm","image/x-quicktime":".qtif","image/x-rgb":".rgb","image/x-tga":".tga","image/x-xbitmap":".xbm","image/x-xpixmap":".xpm","image/x-xwindowdump":".xwd","message/rfc822":".eml","model/iges":".igs","model/mesh":".msh","model/vnd.collada+xml":".dae","model/vnd.dwf":".dwf","model/vnd.gdl":".gdl","model/vnd.gtw":".gtw","model/vnd.vtu":".vtu","model/vrml":".wrl","model/x3d+binary":".x3db","model/x3d+vrml":".x3dv","model/x3d+xml":".x3d","text/cache-manifest":".manifest","text/calendar":".ics","text/css":".css","text/csv":".csv","text/html":".html","text/javascript":".js","text/n3":".n3","text/plain":".txt","text/prs.lines.tag":".dsc","text/richtext":".rtx","text/sgml":".sgml","text/tab-separated-values":".tsv","text/troff":".t","text/turtle":".ttl","text/uri-list":".uri","text/vcard":".vcard","text/vnd.curl":".curl","text/vnd.curl.dcurl":".dcurl","text/vnd.curl.mcurl":".mcurl","text/vnd.curl.scurl":".scurl","text/vnd.dvb.subtitle":".sub","text/vnd.fly":".fly","text/vnd.fmi.flexstor":".flx","text/vnd.graphviz":".gv","text/vnd.in3d.3dml":".3dml","text/vnd.in3d.spot":".spot","text/vnd.sun.j2me.app-descriptor":".jad","text/vnd.wap.wml":".wml","text/vnd.wap.wmlscript":".wmls","text/x-asm":".s","text/x-c":".c","text/x-fortran":".f","text/x-java-source":".java","text/x-nfo":".nfo","text/x-opml":".opml","text/x-pascal":".p","text/x-python":".py","text/x-setext":".etx","text/x-sfv":".sfv","text/x-uuencode":".uu","text/x-vcalendar":".vcs","text/x-vcard":".vcf","video/3gpp":".3gp","video/3gpp2":".3g2","video/h261":".h261","video/h263":".h263","video/h264":".h264","video/jpeg":".jpgv","video/jpm":".jpm","video/mj2":".mj2","video/mp2t":".ts","video/mp4":".mp4","video/mpeg":".mpeg","video/ogg":".ogv","video/quicktime":".mov","video/vnd.dece.hd":".uvh","video/vnd.dece.mobile":".uvm","video/vnd.dece.pd":".uvp","video/vnd.dece.sd":".uvs","video/vnd.dece.video":".uvv","video/vnd.dvb.file":".dvb","video/vnd.fvt":".fvt","video/vnd.mpegurl":".mxu","video/vnd.ms-playready.media.pyv":".pyv","video/vnd.uvvu.mp4":".uvu","video/vnd.vivo":".viv","video/webm":".webm","video/x-dv":".dv","video/x-f4v":".f4v","video/x-fli":".fli","video/x-flv":".flv","video/x-m4v":".m4v","video/x-matroska":".mkv","video/x-mng":".mng","video/x-ms-asf":".asf","video/x-ms-vob":".vob","video/x-ms-wm":".wm","video/x-ms-wmv":".wmv","video/x-ms-wmx":".wmx","video/x-ms-wvx":".wvx","video/x-msvideo":".avi","video/x-sgi-movie":".movie","video/x-smv":".smv","x-conference/x-cooltalk":".ice"}
1126
+
1127
+ def read_download_filename(request):
1128
+ from urllib.parse import urlsplit, unquote
1129
+ import posixpath
1130
+ url = urlsplit(request['source'])
1131
+ filename = unquote(posixpath.basename(url.path.rstrip('/'))) or url.netloc.rsplit('@', 1)[-1]
1132
+ headers = {key.lower(): value for key, value in request['headers']}
1133
+ # CPython 3.9 cgi.parse_header rules, including last duplicate wins.
1134
+ remaining = ';' + headers.get('content-disposition', '')
1135
+ parameters = []
1136
+ while remaining[:1] == ';':
1137
+ remaining = remaining[1:]
1138
+ end = remaining.find(';')
1139
+ while end > 0 and (remaining.count('"', 0, end) - remaining.count('\\"', 0, end)) % 2:
1140
+ end = remaining.find(';', end + 1)
1141
+ if end < 0: end = len(remaining)
1142
+ parameters.append(remaining[:end].strip())
1143
+ remaining = remaining[end:]
1144
+ selected = None
1145
+ for parameter in parameters[1:]:
1146
+ if '=' not in parameter: continue
1147
+ key, value = parameter.split('=', 1)
1148
+ if key.strip().lower() != 'filename': continue
1149
+ value = value.strip()
1150
+ if len(value) >= 2 and value[0] == value[-1] == '"':
1151
+ value = value[1:-1].replace('\\\\', '\\').replace('\\"', '"')
1152
+ selected = posixpath.basename(value) if value else ''
1153
+ filename = selected or filename
1154
+ ext = posixpath.splitext(filename)[1]
1155
+ if not ext:
1156
+ ext = MIME_PREFERENCES.get(headers.get('content-type', '').lower())
1157
+ if ext: filename += ext
1158
+ if not ext and request['source'] != request['responseUrl']:
1159
+ ext = posixpath.splitext(request['responseUrl'])[1]
1160
+ if ext: filename += ext
1161
+ return filename
1162
+ `)();
1163
+
1113
1164
  // packages/safe-bash-command-python/src/build-backend.ts
1114
1165
  import { toByteSource as toByteSource5 } from "../../safe-bash-contracts/index.js";
1115
1166
  function createPythonBuildBackend(options) {
1116
1167
  if (!options.createExecutor || !options.environment || options.provisioning) throw new TypeError("Python build hooks require an asynchronous executor and explicit environment");
1117
1168
  const capabilities = /* @__PURE__ */ new WeakMap();
1118
- const environment = options.environment;
1169
+ const environment = options.environment, legacy = /* @__PURE__ */ new WeakSet();
1119
1170
  const command = createPythonExecutorCommands({ ...options, environment: { ...environment, async prepare(context) {
1120
- return { ...await environment.prepare(context), bootstrap: true };
1171
+ return { ...await environment.prepare(context), bootstrap: true, ...context.args && legacy.has(context.args) ? { bootstrapPackages: ["setuptools"] } : {} };
1121
1172
  } }, createCapabilities(context) {
1122
1173
  const provided = options.createCapabilities?.(context) ?? {};
1123
1174
  if (provided.python_build) throw new Error("Python build capability is reserved");
@@ -1129,12 +1180,20 @@ function createPythonBuildBackend(options) {
1129
1180
  context.signal.throwIfAborted();
1130
1181
  const { maxBytes } = context;
1131
1182
  if (maxBytes !== Infinity && (!Number.isSafeInteger(maxBytes) || maxBytes < 0)) throw new RangeError("Invalid Python build metadata limit");
1132
- if (!input || !["read_build_system", "check_build_requirements", "get_requires_for_build_wheel", "build_wheel"].includes(input.hook) || typeof input.source !== "string" || !input.source) throw new TypeError("Invalid Python build hook request");
1133
- if (input.hook === "check_build_requirements") {
1183
+ if (!input || !["read_source_origin", "read_download_filename", "read_editable_requirement", "get_requires_for_legacy_wheel", "read_source_requirement", "read_build_system", "check_build_requirements", "get_requires_for_build_wheel", "build_wheel", "build_legacy_wheel"].includes(input.hook) || typeof input.source !== "string" || !input.source) throw new TypeError("Invalid Python build hook request");
1184
+ if (input.hook === "read_editable_requirement" && input.requirementLine !== void 0 && typeof input.requirementLine !== "boolean") throw new TypeError("Invalid editable requirement line");
1185
+ if (input.hook === "read_source_origin") {
1186
+ if (typeof input.directory !== "boolean") throw new TypeError("Invalid Python source origin");
1187
+ } else if (input.hook === "read_download_filename") {
1188
+ if (typeof input.responseUrl !== "string" || !Array.isArray(input.headers) || input.headers.some((pair) => !Array.isArray(pair) || pair.length !== 2 || pair.some((value) => typeof value !== "string"))) throw new TypeError("Invalid Python download metadata");
1189
+ } else if (input.hook === "build_legacy_wheel") {
1190
+ if (typeof input.wheelDirectory !== "string" || !input.wheelDirectory || input.editable !== void 0 && typeof input.editable !== "boolean") throw new TypeError("Invalid Python legacy wheel directory");
1191
+ } else if (input.hook === "check_build_requirements") {
1134
1192
  if ([input.requirements, input.installed].some((values) => !Array.isArray(values) || values.some((value) => typeof value !== "string"))) throw new TypeError("Invalid Python build requirements request");
1135
1193
  } else if (input.hook === "read_build_system") {
1194
+ if (input.installation !== void 0 && !["directory", "archive"].includes(input.installation)) throw new TypeError("Invalid Python source installation");
1136
1195
  if (input.name !== void 0 && typeof input.name !== "string" || input.usePep517 !== void 0 && typeof input.usePep517 !== "boolean") throw new TypeError("Invalid Python build system request");
1137
- } else {
1196
+ } else if (input.hook !== "read_source_requirement" && input.hook !== "read_editable_requirement" && input.hook !== "get_requires_for_legacy_wheel") {
1138
1197
  if (typeof input.backend !== "string" || !input.backend || input.backendPath !== void 0 && (!Array.isArray(input.backendPath) || input.backendPath.some((path) => typeof path !== "string")) || input.hook === "build_wheel" && (typeof input.wheelDirectory !== "string" || !input.wheelDirectory || input.metadataDirectory !== void 0 && typeof input.metadataDirectory !== "string")) throw new TypeError("Invalid Python build hook request");
1139
1198
  if (input.configSettings !== void 0 && (!input.configSettings || typeof input.configSettings !== "object" || Array.isArray(input.configSettings) || Object.values(input.configSettings).some((value) => typeof value !== "string" && (!Array.isArray(value) || value.some((item) => typeof item !== "string"))))) throw new TypeError("Invalid Python build configuration");
1140
1199
  }
@@ -1142,6 +1201,7 @@ function createPythonBuildBackend(options) {
1142
1201
  let done = false, size = 0, failure;
1143
1202
  const chunks = [];
1144
1203
  const invocation = { ...context, command: "python", args: ["-c", pythonBuildBackendProgram], stdin: toByteSource5("") };
1204
+ if (request.hook === "build_legacy_wheel" || request.hook === "get_requires_for_legacy_wheel") legacy.add(invocation.args);
1145
1205
  capabilities.set(invocation.args, { async call(value) {
1146
1206
  try {
1147
1207
  context.signal.throwIfAborted();
@@ -1150,7 +1210,7 @@ function createPythonBuildBackend(options) {
1150
1210
  if (message.op === "request") return request;
1151
1211
  if (message.op === "error") {
1152
1212
  if (typeof message.type !== "string" || typeof message.message !== "string") throw new TypeError("Invalid Python build failure");
1153
- failure ??= Object.assign(new Error(message.message), { name: message.type });
1213
+ failure ??= Object.assign(message.type === "InstallationError" ? new PythonInstallationError(message.message) : new Error(message.message), { name: message.type });
1154
1214
  done = true;
1155
1215
  return null;
1156
1216
  }
@@ -1176,7 +1236,12 @@ function createPythonBuildBackend(options) {
1176
1236
  if (result.exitCode) throw new Error(`Python build interpreter exited with status ${result.exitCode}`);
1177
1237
  if (!done) throw new Error("Python build interpreter returned no result");
1178
1238
  const value = JSON.parse(chunks.join(""));
1179
- if (request.hook === "check_build_requirements") {
1239
+ if (request.hook === "read_source_origin" || request.hook === "read_download_filename") {
1240
+ if (typeof value !== "string") throw new TypeError("Invalid Python download filename");
1241
+ } else if (request.hook === "read_source_requirement" || request.hook === "read_editable_requirement") {
1242
+ const result2 = value;
1243
+ if (result2 !== null && (!result2 || typeof result2.name !== "string" || typeof result2.url !== "string" || typeof result2.active !== "boolean" || result2.marker !== null && typeof result2.marker !== "string" || !Array.isArray(result2.extras) || result2.extras.some((extra) => typeof extra !== "string"))) throw new TypeError("Invalid Python source requirement");
1244
+ } else if (request.hook === "check_build_requirements") {
1180
1245
  const result2 = value;
1181
1246
  if (!result2 || !Array.isArray(result2.missing) || result2.missing.some((value2) => typeof value2 !== "string") || !Array.isArray(result2.conflicting) || result2.conflicting.some((pair) => !Array.isArray(pair) || pair.length !== 2 || pair.some((value2) => typeof value2 !== "string"))) throw new TypeError("Invalid Python build requirement status");
1182
1247
  } else if (request.hook === "read_build_system") {
@@ -1185,21 +1250,26 @@ function createPythonBuildBackend(options) {
1185
1250
  const details = value;
1186
1251
  if (typeof details.backend !== "string" || !details.backend || ["requires", "check", "backendPath"].some((key) => !Array.isArray(details[key]) || details[key].some((item) => typeof item !== "string"))) throw new TypeError("Invalid Python build system");
1187
1252
  }
1188
- } else if (request.hook === "build_wheel") {
1253
+ } else if (request.hook === "build_wheel" || request.hook === "build_legacy_wheel") {
1189
1254
  if (typeof value !== "string" || !value.endsWith(".whl") || value.includes("/") || value.includes("\\") || value.includes("\0")) throw new TypeError("Invalid Python build wheel filename");
1190
1255
  } else if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) throw new TypeError("Invalid Python build requirements");
1191
1256
  return value;
1192
1257
  } finally {
1193
1258
  capabilities.delete(invocation.args);
1259
+ legacy.delete(invocation.args);
1194
1260
  }
1195
1261
  };
1196
1262
  }
1197
1263
  var pythonBuildBackendProgram = /* @__PURE__ */ (() => String.raw`
1198
1264
  import importlib, json, os, sys, safe_host
1265
+ ${pythonDownloadFilenameProgram}
1199
1266
 
1200
1267
  def send(op, **fields):
1201
1268
  return safe_host.call('python_build', dict(op=op, **fields))
1202
1269
 
1270
+
1271
+ ${pythonSourceOriginProgram}
1272
+
1203
1273
  def parse_build_requirement(value):
1204
1274
  from urllib.parse import urlparse, urlunparse
1205
1275
  from micropip._vendored.packaging.src.packaging.requirements import Requirement, InvalidRequirement
@@ -1234,6 +1304,8 @@ def read_build_system(request):
1234
1304
  source = request['source']
1235
1305
  filename = os.path.join(source, 'pyproject.toml')
1236
1306
  has_project, has_setup = os.path.isfile(filename), os.path.isfile(os.path.join(source, 'setup.py'))
1307
+ if request.get('installation') == 'directory' and not has_project and not has_setup:
1308
+ raise InstallationError("Directory {!r} is not installable. Neither 'setup.py' nor 'pyproject.toml' found.".format(request.get('name', source)))
1237
1309
  system = None
1238
1310
  if has_project:
1239
1311
  limit = request['maxBytes']
@@ -1248,7 +1320,10 @@ def read_build_system(request):
1248
1320
  if selected is False: raise InstallationError('Disabling PEP 517 processing is invalid: project specifies a build backend of {} in pyproject.toml'.format(system['build-backend']))
1249
1321
  selected = True
1250
1322
  elif selected is None: selected = has_project
1251
- if not selected: return None
1323
+ if not selected:
1324
+ if request.get('installation') and not os.path.exists(os.path.join(source, 'setup.py')):
1325
+ raise InstallationError('File "setup.py" not found for legacy project {}.'.format(request.get('name', source)))
1326
+ return None
1252
1327
  defaults = ['setuptools>=40.8.0', 'wheel']
1253
1328
  if system is None: system = {'requires': defaults, 'build-backend': 'setuptools.build_meta:__legacy__'}
1254
1329
  def invalid(reason):
@@ -1263,8 +1338,75 @@ def read_build_system(request):
1263
1338
  backend = system.get('build-backend')
1264
1339
  return dict(requires=requirements, backend=backend if backend is not None else 'setuptools.build_meta:__legacy__', check=defaults if backend is None else [], backendPath=system.get('backend-path', []))
1265
1340
 
1341
+ def build_legacy_wheel(request):
1342
+ source = os.path.realpath(request['source'])
1343
+ directory = os.path.abspath(request['wheelDirectory'])
1344
+ filename = os.path.join(source, 'setup.py')
1345
+ os.chdir(source)
1346
+ sys.path.insert(0, '')
1347
+ sys.argv = [filename, 'bdist_wheel', '-d', directory]
1348
+ namespace = dict(__name__='__main__', __file__=filename)
1349
+ try:
1350
+ exec("import io, os, sys, setuptools, tokenize\nsys.argv[0] = __file__\nf = getattr(tokenize, 'open', open)(__file__) if os.path.exists(__file__) else io.StringIO('from setuptools import setup; setup()')\ncode = f.read().replace('\\r\\n', '\\n')\nf.close()\nexec(compile(code, __file__, 'exec'))", namespace)
1351
+ except SystemExit as error:
1352
+ if error.code not in (None, 0): raise
1353
+ first = None
1354
+ with os.scandir(directory) as entries:
1355
+ for entry in entries:
1356
+ if first is None or entry.name < first: first = entry.name
1357
+ if first is None: raise RuntimeError('Legacy wheel build created no files')
1358
+ return first
1359
+
1360
+ def read_source_requirement(request):
1361
+ from micropip._vendored.packaging.src.packaging.requirements import InvalidRequirement
1362
+ try: requirement = parse_build_requirement(request['source'])
1363
+ except InvalidRequirement: return None
1364
+ if not requirement.url: return None
1365
+ marker = requirement.marker
1366
+ return dict(name=requirement.name, extras=sorted({'_'.join(part for part in extra.lower().split('_') if part) for extra in requirement.extras}), url=requirement.url, marker=str(marker) if marker else None, active=not marker or marker.evaluate({'extra': ''}))
1367
+
1368
+ def read_editable_requirement(request):
1369
+ from pathlib import Path
1370
+ from micropip._vendored.packaging.src.packaging.requirements import Requirement
1371
+ class InstallationError(Exception): pass
1372
+ source, extras = request['source'], None
1373
+ if request.get('requirementLine'):
1374
+ import shlex, optparse
1375
+ class OptionParsingError(Exception): pass
1376
+ class Parser(optparse.OptionParser):
1377
+ def exit(self, status=0, message=None): raise OptionParsingError(message)
1378
+ parser = Parser(add_help_option=False)
1379
+ parser.add_option('-e', '--editable', action='append', dest='editables')
1380
+ options, _ = parser.parse_args(shlex.split(source))
1381
+ if not options.editables: raise InstallationError('Editable requirement line requires -e')
1382
+ source = options.editables[0]
1383
+ start = source.rfind('[')
1384
+ if start > 0 and source.endswith(']') and start < len(source) - 2 and ']' not in source[start + 1:-1]:
1385
+ source, extras = source[:start], source[start:]
1386
+ if os.path.isdir(source):
1387
+ if not any(os.path.exists(os.path.join(source, name)) for name in ('setup.py', 'setup.cfg')):
1388
+ message = 'File "setup.py" or "setup.cfg" not found. Directory cannot be installed in editable mode: {}'.format(os.path.abspath(source))
1389
+ if os.path.isfile(os.path.join(source, 'pyproject.toml')): message += '\n(A "pyproject.toml" file was found, but editable mode currently requires a setuptools-based build.)'
1390
+ raise InstallationError(message)
1391
+ source = Path(os.path.abspath(source)).as_uri()
1392
+ if not source.lower().startswith('file:'): raise InstallationError('Editable source requires a local directory')
1393
+ name = ''
1394
+ for index, character in enumerate(source):
1395
+ if character in '#&' and source.startswith('egg=', index + 1):
1396
+ name = source[index + 5:].split('&', 1)[0]
1397
+ break
1398
+ return dict(name=name, url=source, extras=sorted(Requirement('placeholder' + extras.lower()).extras) if extras else [], marker=None, active=True)
1399
+
1266
1400
  def main():
1267
1401
  request = send('request')
1402
+ if request['hook'] == 'get_requires_for_legacy_wheel': request.update(hook='get_requires_for_build_wheel', backend='setuptools.build_meta:__legacy__')
1403
+ if request['hook'] == 'read_source_origin': return read_source_origin(request)
1404
+ if request['hook'] == 'read_download_filename': return read_download_filename(request)
1405
+ if request['hook'] == 'read_source_requirement': return read_source_requirement(request)
1406
+ if request['hook'] == 'read_editable_requirement': return read_editable_requirement(request)
1407
+ if request['hook'] == 'build_legacy_wheel':
1408
+ if not request.get('editable'): return build_legacy_wheel(request)
1409
+ request.update(hook='build_wheel', backend='setuptools.build_meta:__legacy__')
1268
1410
  if request['hook'] == 'read_build_system': return read_build_system(request)
1269
1411
  if request['hook'] == 'check_build_requirements': return check_build_requirements(request)
1270
1412
  source = os.path.realpath(request['source'])
@@ -1290,7 +1432,8 @@ def main():
1290
1432
  except AttributeError: result = []
1291
1433
  else: result = hook(settings)
1292
1434
  else:
1293
- result = backend.build_wheel(wheel_directory, settings, metadata_directory)
1435
+ if request.get('editable'): result = backend.build_editable(wheel_directory, {'editable_mode': 'compat'}, metadata_directory)
1436
+ else: result = backend.build_wheel(wheel_directory, settings, metadata_directory)
1294
1437
  return result
1295
1438
 
1296
1439
  try:
@@ -1312,7 +1455,7 @@ function createPythonBuildDependencies(options) {
1312
1455
  const context = { ...caller };
1313
1456
  context.signal.throwIfAborted();
1314
1457
  const request = structuredClone(input), { source, buildSystem, configSettings } = request;
1315
- if (typeof source !== "string" || !source || request.name !== void 0 && typeof request.name !== "string" || !buildSystem || typeof buildSystem.backend !== "string" || !buildSystem.backend || [buildSystem.requires, buildSystem.check, buildSystem.backendPath].some((values) => !Array.isArray(values) || values.some((value) => typeof value !== "string"))) throw new TypeError("Invalid Python build dependency request");
1458
+ if (typeof source !== "string" || !source || request.name !== void 0 && typeof request.name !== "string" || buildSystem !== null && (!buildSystem || typeof buildSystem.backend !== "string" || !buildSystem.backend || [buildSystem.requires, buildSystem.check, buildSystem.backendPath].some((values) => !Array.isArray(values) || values.some((value) => typeof value !== "string")))) throw new TypeError("Invalid Python build dependency request");
1316
1459
  if (configSettings !== void 0 && (!configSettings || typeof configSettings !== "object" || Array.isArray(configSettings) || Object.values(configSettings).some((value) => typeof value !== "string" && (!Array.isArray(value) || value.some((item) => typeof item !== "string"))))) throw new TypeError("Invalid Python build configuration");
1317
1460
  if (context.maxBytes !== Infinity && (!Number.isSafeInteger(context.maxBytes) || context.maxBytes < 0)) throw new RangeError("Invalid Python build metadata limit");
1318
1461
  const install = async (requirements2) => {
@@ -1335,10 +1478,12 @@ function createPythonBuildDependencies(options) {
1335
1478
  if (status.conflicting.length) throw Object.assign(new Error("Some build dependencies for " + (request.name ?? source) + " conflict with " + against + ": " + [...status.conflicting].sort(([a, b], [c, d]) => a < c ? -1 : a > c ? 1 : b < d ? -1 : b > d ? 1 : 0).map(([installed2, wanted]) => installed2 + " is incompatible with " + wanted).join(", ") + "."), { name: "InstallationError" });
1336
1479
  return status.missing;
1337
1480
  };
1338
- await install(buildSystem.requires);
1339
- const missing = await check(buildSystem.check, "PEP 517/518 supported requirements");
1340
- if (missing.length) await context.stderr.write(new TextEncoder().encode("Missing build requirements in pyproject.toml for " + (request.name ?? source) + ".\nThe project does not specify a build backend, and pip cannot fall back to setuptools without " + missing.map((value) => "'" + value + "'").join(" and ") + ".\n"));
1341
- const requirements = await hook({ hook: "get_requires_for_build_wheel", source, backend: buildSystem.backend, backendPath: buildSystem.backendPath, ...configSettings === void 0 ? {} : { configSettings } }, context);
1481
+ if (buildSystem) {
1482
+ await install(buildSystem.requires);
1483
+ const missing = await check(buildSystem.check, "PEP 517/518 supported requirements");
1484
+ if (missing.length) await context.stderr.write(new TextEncoder().encode("Missing build requirements in pyproject.toml for " + (request.name ?? source) + ".\nThe project does not specify a build backend, and pip cannot fall back to setuptools without " + missing.map((value) => "'" + value + "'").join(" and ") + ".\n"));
1485
+ }
1486
+ const requirements = await hook(buildSystem ? { hook: "get_requires_for_build_wheel", source, backend: buildSystem.backend, backendPath: buildSystem.backendPath, ...configSettings === void 0 ? {} : { configSettings } } : { hook: "get_requires_for_legacy_wheel", source }, context);
1342
1487
  await install(await check(requirements, "the backend dependencies"));
1343
1488
  };
1344
1489
  }
@@ -1859,41 +2004,267 @@ async function publishPythonBuildWheel(source, directory, maxBytes, context) {
1859
2004
  }
1860
2005
  }
1861
2006
 
2007
+ // packages/safe-bash-command-python/src/source-origin.ts
2008
+ import { FsError as FsError4 } from "../../safe-bash-contracts/index.js";
2009
+ import { resolvePath as resolvePath3, dirname, basename as basename2 } from "../../safe-bash-contracts/path.js";
2010
+ function withPythonSourceOrigins(environment, directory, maxBytes) {
2011
+ const origins = /* @__PURE__ */ new Map(), encoder2 = new TextEncoder();
2012
+ return {
2013
+ ...environment,
2014
+ async dispatch(operation, args, context) {
2015
+ const result = await environment.dispatch(operation, args, context), session = String(args[0]);
2016
+ if (operation === "package-open") {
2017
+ origins.delete(session);
2018
+ const url = new URL(String(args[1]));
2019
+ if (url.protocol === "file:" && url.hash.startsWith("#python-source=")) {
2020
+ const parent = dirname(decodeURIComponent(url.pathname));
2021
+ if (basename2(parent) !== result.key) return result;
2022
+ let root;
2023
+ try {
2024
+ root = await context.fs.realpath(resolvePath3(context.cwd, directory), { signal: context.signal });
2025
+ } catch (error) {
2026
+ if (error instanceof FsError4 && error.code === "ENOENT") return result;
2027
+ throw error;
2028
+ }
2029
+ if (dirname(parent) !== root) return result;
2030
+ const origin = decodeURIComponent(url.hash.slice("#python-source=".length));
2031
+ if (encoder2.encode(origin).length > maxBytes) throw new RangeError("Python source origin exceeds maxMetadataBytes");
2032
+ origins.set(session, { key: result.key, origin });
2033
+ }
2034
+ } else if (operation === "package-retain") {
2035
+ const origin = origins.get(session);
2036
+ origins.delete(session);
2037
+ if (origin !== void 0) return { ...result, metadata: origin.origin === "null" ? {} : { "direct_url.json": origin.origin } };
2038
+ } else if (operation === "package-close" && origins.get(session)?.key === String(args[1])) origins.delete(session);
2039
+ return result;
2040
+ },
2041
+ finish(start) {
2042
+ origins.delete(start.session);
2043
+ return environment.finish(start);
2044
+ },
2045
+ async dispose() {
2046
+ try {
2047
+ await environment.dispose();
2048
+ } finally {
2049
+ origins.clear();
2050
+ }
2051
+ }
2052
+ };
2053
+ }
2054
+
1862
2055
  // packages/safe-bash-command-python/src/source-environment.ts
1863
2056
  import { compareIdentity as compareIdentity2 } from "@poe-platform/safe-fs/core";
1864
- import { FsError as FsError4, toByteSource as toByteSource7 } from "../../safe-bash-contracts/index.js";
1865
- import { resolvePath as resolvePath3 } from "../../safe-bash-contracts/path.js";
2057
+ import { FsError as FsError5, toByteSource as toByteSource7 } from "../../safe-bash-contracts/index.js";
2058
+ import { resolvePath as resolvePath5 } from "../../safe-bash-contracts/path.js";
2059
+
2060
+ // packages/safe-bash-command-python/src/source-download.ts
2061
+ import { dirname as dirname2, resolvePath as resolvePath4 } from "../../safe-bash-contracts/path.js";
2062
+ import { sha224, sha256, sha384, sha512 } from "@noble/hashes/sha2.js";
2063
+ import { sha1, md5 } from "@noble/hashes/legacy.js";
2064
+ async function* verifiedBytes(source, expected, maxBytes, signal) {
2065
+ const checksum = expected ? { sha1, sha224, sha384, sha256, sha512, md5 }[expected[0]].create() : void 0;
2066
+ let count = 0;
2067
+ try {
2068
+ for await (const bytes of source) {
2069
+ signal.throwIfAborted();
2070
+ if (!(bytes instanceof Uint8Array)) throw new TypeError("Python package body must yield bytes");
2071
+ if (bytes.length > maxBytes - count) throw new Error("Package download exceeds maxDownloadBytes");
2072
+ count += bytes.length;
2073
+ for (let offset = 0; offset < bytes.length; offset += 65536) {
2074
+ signal.throwIfAborted();
2075
+ const chunk = bytes.subarray(offset, offset + 65536);
2076
+ checksum?.update(chunk);
2077
+ yield chunk;
2078
+ }
2079
+ }
2080
+ if (checksum && Array.from(checksum.digest(), (byte) => byte.toString(16).padStart(2, "0")).join("") !== expected[1]) throw new Error("Python source archive integrity mismatch: " + expected[0]);
2081
+ } finally {
2082
+ checksum?.destroy();
2083
+ }
2084
+ }
2085
+ async function downloadPythonSourceArchive(url, path, options, context) {
2086
+ const { fs, signal } = context, cacheDirectory = resolvePath4(context.cwd, options.cacheDirectory ?? dirname2(path));
2087
+ const caps = await fs.capabilitiesFor?.(cacheDirectory, { signal }) ?? fs.capabilities;
2088
+ if (!caps.retainedStagingWrite || !caps.retainedStagingCleanup || !caps.retainedRead || !caps.atomicFileStaging || !fs.createStagedFile || !fs.openReadFile || !fs.publishStagedFile || !fs.confineExtraction) throw new Error("Remote Python sources require retained caller storage");
2089
+ const output = await fs.confineExtraction([dirname2(path)], { signal });
2090
+ if (!output.writeStream) throw new Error("Remote Python sources require streaming writes");
2091
+ const expected = pythonPackageUrlHash(url.href), supplied = options.transport, maxBytes = options.maxDownloadBytes ?? Infinity;
2092
+ const transport = supplied && expected ? Object.assign(async (request) => {
2093
+ const response = await supplied(request);
2094
+ return response.status >= 200 && response.status < 300 ? {
2095
+ status: response.status,
2096
+ statusText: response.statusText,
2097
+ headers: response.headers,
2098
+ ...response.httpVersion === void 0 ? {} : { httpVersion: response.httpVersion },
2099
+ ...response.contentDecoded === void 0 ? {} : { contentDecoded: response.contentDecoded },
2100
+ body: verifiedBytes(response.body, expected, maxBytes, signal),
2101
+ dispose: response.dispose.bind(response)
2102
+ } : response;
2103
+ }, supplied.supportsPrivateNetworkDeny ? { supportsPrivateNetworkDeny: true } : {}) : supplied;
2104
+ const environment = createPythonBuildEnvironment({ ...options, ...transport ? { transport } : {}, cacheDirectory });
2105
+ try {
2106
+ const start = await environment.prepare({ ...context, requirements: [], requirementFiles: [] });
2107
+ try {
2108
+ const address = new URL(url);
2109
+ address.hash = "";
2110
+ const receipt = await environment.dispatch("package-open", [start.session, address.href], context);
2111
+ let consumed = false;
2112
+ const bytes = verifiedBytes((async function* () {
2113
+ for (let offset = 0; offset < receipt.size; ) {
2114
+ const chunk = await environment.dispatch("package-read", [start.session, receipt.key, offset, Math.min(65536, receipt.size - offset)], context);
2115
+ if (!chunk.length) throw new Error("Remote Python source ended early");
2116
+ offset += chunk.length;
2117
+ yield Uint8Array.from(chunk);
2118
+ }
2119
+ consumed = true;
2120
+ })(), expected, maxBytes, signal);
2121
+ try {
2122
+ await output.writeStream(path, bytes, { flag: "wx", mode: 384, signal });
2123
+ if (!consumed) throw new Error("Remote Python source write ended early");
2124
+ } finally {
2125
+ await bytes.return(void 0);
2126
+ }
2127
+ return { url: receipt.url, headers: receipt.headers };
2128
+ } finally {
2129
+ await environment.finish(start);
2130
+ }
2131
+ } finally {
2132
+ await environment.dispose();
2133
+ }
2134
+ }
2135
+ async function snapshotPythonSourceArchive(source, path, url, maxBytes, context) {
2136
+ const { fs, signal } = context;
2137
+ if (!fs.writeStream) throw new Error("Local Python sources require streaming writes");
2138
+ const file = await openPythonPackageFile(context, source, maxBytes);
2139
+ if (!file) throw new Error("Local Python sources require retained reads");
2140
+ const bytes = verifiedBytes((async function* () {
2141
+ for (let offset = 0; offset < file.size; ) {
2142
+ const chunk = await file.read(offset, Math.min(65536, file.size - offset));
2143
+ offset += chunk.length;
2144
+ yield chunk;
2145
+ }
2146
+ })(), pythonPackageUrlHash(url), maxBytes, signal);
2147
+ let complete = false;
2148
+ try {
2149
+ await fs.writeStream(path, (async function* () {
2150
+ yield* bytes;
2151
+ complete = true;
2152
+ })(), { flag: "wx", mode: 384, signal });
2153
+ if (!complete) throw new Error("Local Python source write ended early");
2154
+ } finally {
2155
+ try {
2156
+ await bytes.return(void 0);
2157
+ } finally {
2158
+ await file.close();
2159
+ }
2160
+ }
2161
+ }
2162
+
2163
+ // packages/safe-bash-command-python/src/source-environment.ts
1866
2164
  var serial2 = 0;
2165
+ var archiveSuffix = (path) => [".zip", ".tar", ".tar.gz", ".tgz", ".tar.bz2", ".tbz", ".tar.xz", ".txz"].find((suffix) => path.toLowerCase().endsWith(suffix));
2166
+ var wheelLink = (url) => {
2167
+ let path = url.pathname;
2168
+ while (path.endsWith("/")) path = path.slice(0, -1);
2169
+ const parts = (path.slice(path.lastIndexOf("/") + 1) || url.host).split("%");
2170
+ let name = parts.shift();
2171
+ for (const part of parts) {
2172
+ const hex = part.slice(0, 2).toLowerCase();
2173
+ name += hex.length === 2 && [...hex].every((value) => "0123456789abcdef".includes(value)) ? String.fromCharCode(Number.parseInt(hex, 16)) + part.slice(2) : "%" + part;
2174
+ }
2175
+ name = name.slice(name.lastIndexOf("/") + 1);
2176
+ return name.endsWith(".whl") && name.slice(0, -4).split(".").some(Boolean);
2177
+ };
1867
2178
  function createPythonSourcePackageEnvironment(options, build) {
1868
2179
  if (options.prepareRequirements || !build.python.createExecutor || !build.directory) throw new TypeError("Source packages require an asynchronous build executor and caller storage");
1869
- const prepareRequirement = async (requirement, context) => {
1870
- const { fs, signal } = context, settings = { signal };
1871
- let source = requirement;
1872
- if (source.startsWith("file:")) {
2180
+ const prepareRequirement = async (requirement, context, editable = false) => {
2181
+ const { fs, signal } = context, settings = { signal }, requirementLine = requirement.startsWith("-");
2182
+ editable ||= requirementLine;
2183
+ let source = requirement, named = null;
2184
+ let remote;
2185
+ const at = requirement.indexOf("@");
2186
+ let namedSource = false;
2187
+ if (at >= 0 && !requirement.startsWith("file:")) {
2188
+ const tail = requirement.slice(at + 1).trimStart();
2189
+ let end = 0;
2190
+ while (end < tail.length && ![" ", " ", "\r", "\n"].includes(tail[end])) end++;
2191
+ try {
2192
+ const url = new URL(tail.slice(0, end));
2193
+ namedSource = url.protocol === "file:" || ["http:", "https:"].includes(url.protocol) && !wheelLink(url);
2194
+ } catch {
2195
+ }
2196
+ }
2197
+ const editableExtras = editable && requirement.endsWith("]") && requirement.lastIndexOf("[") > 0;
2198
+ if (namedSource || editableExtras || requirementLine) {
2199
+ if (!context.stdout || !context.stderr || !context.env) throw new TypeError("Source requirement parsing requires command output and environment context");
2200
+ const environment2 = createPythonBuildEnvironment(options);
2201
+ const parsing = { ...context, env: context.env, stdout: context.stdout, stderr: context.stderr, maxBytes: options.maxMetadataBytes ?? Infinity };
2202
+ Reflect.deleteProperty(parsing, "editable");
2203
+ try {
2204
+ named = await createPythonBuildBackend({ ...build.python, environment: environment2 })({ hook: editableExtras || requirementLine ? "read_editable_requirement" : "read_source_requirement", source: requirement, ...requirementLine ? { requirementLine } : {} }, parsing);
2205
+ } finally {
2206
+ await environment2.dispose();
2207
+ }
2208
+ if (named) {
2209
+ if (!named.active) return requirement;
2210
+ source = named.url;
2211
+ }
2212
+ }
2213
+ const originalLink = source.slice(0, 5).toLowerCase() === "file:" || source.startsWith("https://") || source.startsWith("http://") ? source : void 0;
2214
+ let subdirectory;
2215
+ if (source.startsWith("file:") || source.startsWith("https://") || source.startsWith("http://")) {
2216
+ for (let index = 0; index < source.length; index++) if ((source[index] === "#" || source[index] === "&") && source.startsWith("subdirectory=", index + 1)) {
2217
+ const start = index + 1 + "subdirectory=".length, end = source.indexOf("&", start);
2218
+ subdirectory = source.slice(start, end < 0 ? void 0 : end);
2219
+ break;
2220
+ }
2221
+ }
2222
+ if (source.slice(0, 5).toLowerCase() === "file:") {
1873
2223
  const url = new URL(source);
1874
- if (url.host && url.host !== "localhost") return requirement;
2224
+ if (url.host && url.host !== "localhost") {
2225
+ if (editable) throw new Error("Editable source requires a local directory");
2226
+ return requirement;
2227
+ }
1875
2228
  source = decodeURIComponent(url.pathname);
1876
- } else if (source.includes("://")) return requirement;
1877
- source = resolvePath3(context.cwd, source);
1878
- try {
1879
- if ((await fs.stat(source, settings)).type !== "directory") return requirement;
1880
- } catch (error) {
1881
- if (error instanceof FsError4 && error.code === "ENOENT") return requirement;
1882
- throw error;
2229
+ } else if (source.startsWith("https://") || source.startsWith("http://")) remote = new URL(source);
2230
+ else if (source.includes("://")) {
2231
+ if (editable) throw new Error("Editable source requires a local directory");
2232
+ return requirement;
1883
2233
  }
2234
+ if (editable && remote) throw new Error("Editable source requires a local directory");
2235
+ const suffix = archiveSuffix(remote?.pathname ?? source);
2236
+ let archived = !!remote && !wheelLink(remote);
2237
+ if (remote) {
2238
+ if (!archived) return requirement;
2239
+ } else {
2240
+ source = resolvePath5(context.cwd, source);
2241
+ try {
2242
+ const stat = await fs.stat(source, settings);
2243
+ archived = stat.type === "file" && !!suffix;
2244
+ if (editable && stat.type !== "directory") throw new Error("Editable source requires a local directory");
2245
+ if (stat.type !== "directory" && !archived) return requirement;
2246
+ } catch (error) {
2247
+ if (error instanceof FsError5 && error.code === "ENOENT") {
2248
+ if (editable) throw new Error("Editable source requires an existing local directory");
2249
+ return requirement;
2250
+ }
2251
+ throw error;
2252
+ }
2253
+ }
2254
+ const originSource = originalLink ?? source;
1884
2255
  if (!context.stdout || !context.stderr || !context.env) throw new TypeError("Source package preparation requires command output and environment context");
1885
2256
  if (!fs.prepareDirectory || !fs.removeTreeConditional || !fs.confineExtraction) throw new Error("Source packages require conditional caller storage");
1886
- const root = await fs.realpath(resolvePath3(context.cwd, build.directory), settings), parent = await fs.stat(root, settings);
2257
+ const root = await fs.realpath(resolvePath5(context.cwd, build.directory), settings), parent = await fs.stat(root, settings);
1887
2258
  const caps = await fs.capabilitiesFor?.(root, settings) ?? fs.capabilities;
1888
2259
  if (!caps.atomicTreeRemoval) throw new Error("Source packages require conditional tree cleanup");
1889
2260
  let path = "", owned;
1890
2261
  for (let attempt = 0; attempt < 16; attempt++) {
1891
- path = resolvePath3(root, ".python-build-" + ++serial2);
2262
+ path = resolvePath5(root, ".python-build-" + ++serial2);
1892
2263
  try {
1893
2264
  owned = await fs.prepareDirectory(path, { parent, expected: null, mode: 448, signal });
1894
2265
  break;
1895
2266
  } catch (error) {
1896
- if (!(error instanceof FsError4) || !["EEXIST", "EAGAIN"].includes(error.code)) throw error;
2267
+ if (!(error instanceof FsError5) || !["EEXIST", "EAGAIN"].includes(error.code)) throw error;
1897
2268
  signal.throwIfAborted();
1898
2269
  }
1899
2270
  }
@@ -1920,17 +2291,45 @@ function createPythonSourcePackageEnvironment(options, build) {
1920
2291
  return typeof value === "function" ? value.bind(owner) : value;
1921
2292
  } });
1922
2293
  const command = { ...context, env: context.env, stdout: context.stdout, stderr: context.stderr, command: "python", args: [], stdin: toByteSource7("") };
1923
- const snapshot = await createPythonSourceSnapshot(source, path, { ...command, fs: staging });
1924
- const wheelDirectory = resolvePath3(path, "wheels");
1925
- await confined.mkdir(wheelDirectory, settings);
2294
+ Reflect.deleteProperty(command, "editable");
1926
2295
  const configuration = { ...build.python, environment }, hook = createPythonBuildBackend(configuration), hookContext = { ...command, maxBytes: options.maxMetadataBytes ?? Infinity };
1927
- const buildSystem = await hook({ hook: "read_build_system", source: snapshot.path }, hookContext);
1928
- if (!buildSystem) throw new Error("Legacy setup.py source installation is not yet available");
1929
- await createPythonBuildDependencies(configuration)({ source: snapshot.path, buildSystem }, hookContext);
1930
- const filename = await hook({ hook: "build_wheel", source: snapshot.path, backend: buildSystem.backend, backendPath: buildSystem.backendPath, wheelDirectory }, hookContext);
1931
- const published = await publishPythonBuildWheel(resolvePath3(wheelDirectory, filename), root, options.maxDownloadBytes ?? Infinity, context);
2296
+ let prepared;
2297
+ if (archived) {
2298
+ prepared = resolvePath5(path, "source");
2299
+ await confined.mkdir(prepared, settings);
2300
+ if (!build.extractArchive) throw new Error("Source archives require an extraction capability");
2301
+ let metadata;
2302
+ if (remote) {
2303
+ source = resolvePath5(path, "archive");
2304
+ const response = await downloadPythonSourceArchive(remote, source, options, command);
2305
+ const filename2 = await hook({ hook: "read_download_filename", source: remote.href, responseUrl: response.url, headers: response.headers }, hookContext);
2306
+ const headers = new Map(response.headers.map(([key, value]) => [key.toLowerCase(), value]));
2307
+ metadata = { filename: filename2, ...headers.has("content-type") ? { contentType: headers.get("content-type") } : {} };
2308
+ }
2309
+ if (!remote && originalLink && pythonPackageUrlHash(originalLink)) {
2310
+ const snapshot = resolvePath5(path, "archive" + suffix);
2311
+ await snapshotPythonSourceArchive(source, snapshot, originalLink, options.maxDownloadBytes ?? Infinity, { ...command, fs: staging });
2312
+ source = snapshot;
2313
+ }
2314
+ await build.extractArchive(source, prepared, options.maxDownloadBytes ?? Infinity, { ...command, fs: staging }, metadata);
2315
+ } else prepared = editable ? await fs.realpath(source, settings) : (await createPythonSourceSnapshot(source, path, { ...command, fs: staging })).path;
2316
+ if (subdirectory) {
2317
+ const selected = resolvePath5(prepared, subdirectory);
2318
+ if (selected !== prepared && !selected.startsWith(prepared + "/")) throw new Error("Source subdirectory escapes the build tree");
2319
+ const root2 = await fs.realpath(prepared, settings), actual = await fs.realpath(selected, settings);
2320
+ if (actual !== root2 && !actual.startsWith(root2 + "/")) throw new Error("Source subdirectory escapes the build tree");
2321
+ prepared = actual;
2322
+ }
2323
+ const wheelDirectory = resolvePath5(path, "wheels");
2324
+ await confined.mkdir(wheelDirectory, settings);
2325
+ const buildSystem = await hook({ hook: "read_build_system", source: prepared, name: requirement, installation: archived ? "archive" : "directory" }, hookContext);
2326
+ await createPythonBuildDependencies(configuration)({ source: prepared, buildSystem }, hookContext);
2327
+ const filename = await hook(editable ? { hook: "build_legacy_wheel", source: prepared, wheelDirectory, editable: true } : buildSystem ? { hook: "build_wheel", source: prepared, backend: buildSystem.backend, backendPath: buildSystem.backendPath, wheelDirectory } : { hook: "build_legacy_wheel", source: prepared, wheelDirectory }, hookContext);
2328
+ const published = await publishPythonBuildWheel(resolvePath5(wheelDirectory, filename), root, options.maxDownloadBytes ?? Infinity, context);
2329
+ const origin = buildSystem && !editable ? await hook({ hook: "read_source_origin", source: originSource, directory: !archived }, hookContext) : void 0;
2330
+ const url = published.url + "#python-source=" + encodeURIComponent(origin ?? "null");
1932
2331
  await cleanup();
1933
- return published.url;
2332
+ return named ? (named.name || filename.slice(0, filename.indexOf("-"))) + (named.extras.length ? "[" + named.extras.join(",") + "]" : "") + " @ " + url + (named.marker ? " ; " + named.marker : "") : url;
1934
2333
  } catch (error) {
1935
2334
  try {
1936
2335
  await cleanup();
@@ -1941,14 +2340,16 @@ function createPythonSourcePackageEnvironment(options, build) {
1941
2340
  throw error;
1942
2341
  }
1943
2342
  };
1944
- return createPythonPackageEnvironment({ ...options, async prepareRequirements(requirements, context) {
2343
+ return withPythonSourceOrigins(createPythonPackageEnvironment({ ...options, async prepareRequirements(requirements, context) {
1945
2344
  const resolved = [];
2345
+ for (const requirement of /* @__PURE__ */ new Set([...options.editable ?? [], ...context.editable ?? []])) resolved.push(await prepareRequirement(requirement, context, true));
1946
2346
  for (const requirement of new Set(requirements)) resolved.push(await prepareRequirement(requirement, context));
1947
2347
  return resolved;
1948
- } });
2348
+ } }), build.directory, options.maxMetadataBytes ?? Infinity);
1949
2349
  }
1950
2350
 
1951
2351
  // packages/safe-bash-command-python/src/executor.ts
2352
+ var encoder = new TextEncoder();
1952
2353
  var PythonInputChunkError = class extends RangeError {
1953
2354
  };
1954
2355
  function createPythonExecutorCommands(options) {
@@ -1970,7 +2371,7 @@ function createPythonExecutorCommands(options) {
1970
2371
  const environment = options.environment ?? createPythonPackageEnvironment(options.provisioning);
1971
2372
  const execute = async (context) => {
1972
2373
  if (pythonShellDispatchActive(context.executionScope)) {
1973
- await writeBytes(context.stderr, new TextEncoder().encode("python: nested Python execution is unavailable while the parent interpreter is suspended\n"), context.signal);
2374
+ await writeBytes(context.stderr, encoder.encode("python: nested Python execution is unavailable while the parent interpreter is suspended\n"), context.signal);
1974
2375
  return { exitCode: 1 };
1975
2376
  }
1976
2377
  let installation;
@@ -1979,17 +2380,17 @@ function createPythonExecutorCommands(options) {
1979
2380
  installation = invocation.module?.name === "pip" ? parsePythonInstallation(invocation.module.args) : void 0;
1980
2381
  } catch (error) {
1981
2382
  if (!(error instanceof PythonInvocationError)) throw error;
1982
- await writeBytes(context.stderr, new TextEncoder().encode("python: " + error.message + "\n"), context.signal);
2383
+ await writeBytes(context.stderr, encoder.encode("python: " + error.message + "\n"), context.signal);
1983
2384
  return { exitCode: 2 };
1984
2385
  }
1985
2386
  if (installation?.help) {
1986
- await writeBytes(context.stdout, new TextEncoder().encode(pythonInstallationHelp), context.signal);
2387
+ await writeBytes(context.stdout, encoder.encode(pythonInstallationHelp), context.signal);
1987
2388
  return { exitCode: 0 };
1988
2389
  }
1989
2390
  context.signal.throwIfAborted();
1990
2391
  if (activeWorkers >= maxConcurrentWorkers) {
1991
2392
  const failure = reportPythonFailure("capacity", void 0, options.onDiagnostic);
1992
- await writeBytes(context.stderr, new TextEncoder().encode("python: " + failure.message + "\n"), context.signal);
2393
+ await writeBytes(context.stderr, encoder.encode("python: " + failure.message + "\n"), context.signal);
1993
2394
  return { exitCode: 1 };
1994
2395
  }
1995
2396
  const controller = new AbortController();
@@ -2077,7 +2478,7 @@ function createPythonExecutorCommands(options) {
2077
2478
  if (!filesystemDiagnostics.has(category)) {
2078
2479
  filesystemDiagnostics.add(category);
2079
2480
  const failure = reportPythonFailure(category, error, options.onDiagnostic);
2080
- await writeBytes(stderrOperation.output, new TextEncoder().encode("python: " + failure.message + "\n"), signal);
2481
+ await writeBytes(stderrOperation.output, encoder.encode("python: " + failure.message + "\n"), signal);
2081
2482
  }
2082
2483
  };
2083
2484
  const dispatch = async (request) => {
@@ -2353,9 +2754,9 @@ function createPythonExecutorCommands(options) {
2353
2754
  });
2354
2755
  }
2355
2756
  } catch (reason) {
2356
- if (!signal.aborted && reason instanceof PythonInputChunkError) {
2757
+ if (!signal.aborted && (reason instanceof PythonInputChunkError || reason instanceof PythonInstallationError)) {
2357
2758
  try {
2358
- await writeBytes(stderrOperation.output, new TextEncoder().encode("python: " + reason.message + "\n"), signal);
2759
+ await writeBytes(stderrOperation.output, encoder.encode("python: " + reason.message + "\n"), signal);
2359
2760
  } catch (error) {
2360
2761
  primary = { reason: error };
2361
2762
  }
@@ -2377,7 +2778,7 @@ function createPythonExecutorCommands(options) {
2377
2778
  if (primary) {
2378
2779
  if (!(primary.reason instanceof PythonFailure)) throw primary.reason;
2379
2780
  const failure = primary.reason;
2380
- await writeBytes(context.stderr, new TextEncoder().encode("python: " + failure.message + "\n"), context.signal);
2781
+ await writeBytes(context.stderr, encoder.encode("python: " + failure.message + "\n"), context.signal);
2381
2782
  return { exitCode: 1 };
2382
2783
  }
2383
2784
  return { exitCode: result };